This commit is contained in:
张壹 2023-12-24 10:13:04 +08:00
parent 24a2adda64
commit 554439818b
11 changed files with 45855 additions and 54 deletions

10
README
View File

@ -1,4 +1,4 @@
This is TetGen version 1.6.0 (released on August 31, 2020)
This is TetGen version 1.6.0_1 (released on December 23, 2023)
Please see the documentation of TetGen for compiling and using TetGen.
It is available at the following link:
@ -22,3 +22,11 @@ BEFORE INTALLING OR USING TetGen(R) READ the
GENERAL LICENSE TERMS AND CONDITIONS
-------------------------------------------------------------------
------------------- IMPORTANCE NOTICE -----------------------------
(1) This version is modified to support outputs of Gmsh .msh file.
(2) Fixed a bug for outputing VTK files when the first node index is zero.
Please send corresponding bugs/comments to Yi Zhang <yizhang-geo@zju.edu.cn>
-------------------------------------------------------------------

54
installer Executable file
View File

@ -0,0 +1,54 @@
#!/bin/bash
if [[ $# == 0 || ${1} == "help" ]]; then
echo "Compiles executables/libraries and maintains installed files. Two tools 'Cmake' and 'stow' are empolyed here. For more information, see https://cmake.org and https://www.gnu.org/software/stow/."
echo ""
echo "School of Earth Sciences, Zhejiang University"
echo "Yi Zhang (yizhang-geo@zju.edu.cn)"
echo ""
echo "Usage: ./config.sh [option] [Cmake options]"
echo ""
echo "Options:"
echo "(1) configure: Configure Cmake project(s). This option could take extra Cmake options as in <option>=<value>."
echo "(2) build: Build executables/libraries."
echo "(3) install: Install executables/libraries to the directory of CMAKE_INSTALL_PREFIX and sym-links them to the target address. This offers a quick and clean remove of the installed files."
echo "(4) clean: Clean build/ folder(s)."
echo "(5) uninstall: Delete the installed files and sym-links."
echo "(6) info: Print out current setups."
echo "(7) help: Show help information."
exit 0
fi
package=tetgen
address=/opt/stow
taress=/usr/local
option="-DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=${address}/${package}"
if [[ $# -gt 1 ]]; then
for opt in "$@"; do
if [[ ${opt} != "configure" ]]; then
option="${option} ${opt}"
fi
done
fi
if [[ ${1} == "configure" && ! -d "build/" ]]; then
mkdir build && cd build && cmake .. ${option}
elif [[ ${1} == "configure" ]]; then
cd build && rm -rf * && cmake .. ${option}
elif [[ ${1} == "build" ]]; then
cd build && make
elif [[ ${1} == "install" ]]; then
cd build && sudo make install
sudo stow --dir=${address} --target=${taress} -S ${package}
elif [[ ${1} == "clean" ]]; then
rm -rf build/
elif [[ ${1} == "uninstall" ]]; then
sudo stow --dir=${address} --target=${taress} -D ${package}
sudo rm -rf ${address}/${package}
elif [[ ${1} == "info" ]]; then
echo "package name:" ${package}
echo "stow address:" ${address}
echo "target address:" ${taress}
echo "Cmake options:" ${option}
fi

View File

@ -2503,7 +2503,9 @@ void tetgenio::save_nodes(const char *filebasename)
char outmtrfilename[FILENAMESIZE];
int i, j;
sprintf(outnodefilename, "%s.node", filebasename);
// modified by Yi Zhang on 2023-12-22
//sprintf(outnodefilename, "%s.node", filebasename);
snprintf(outnodefilename, FILENAMESIZE, "%s.node", filebasename);
printf("Saving nodes to %s\n", outnodefilename);
fout = fopen(outnodefilename, "w");
fprintf(fout, "%d %d %d %d\n", numberofpoints, mesh_dim,
@ -2529,7 +2531,9 @@ void tetgenio::save_nodes(const char *filebasename)
// If the point metrics exist, output them to a .mtr file.
if ((numberofpointmtrs > 0) && (pointmtrlist != (REAL *) NULL)) {
sprintf(outmtrfilename, "%s.mtr", filebasename);
// modified by Yi Zhang on 2023-12-22
//sprintf(outmtrfilename, "%s.mtr", filebasename);
snprintf(outmtrfilename, FILENAMESIZE, "%s.mtr", filebasename);
printf("Saving metrics to %s\n", outmtrfilename);
fout = fopen(outmtrfilename, "w");
fprintf(fout, "%d %d\n", numberofpoints, numberofpointmtrs);
@ -2555,7 +2559,9 @@ void tetgenio::save_elements(const char* filebasename)
char outelefilename[FILENAMESIZE];
int i, j;
sprintf(outelefilename, "%s.ele", filebasename);
// modified by Yi Zhang on 2023-12-22
//sprintf(outelefilename, "%s.ele", filebasename);
snprintf(outelefilename, FILENAMESIZE, "%s.ele", filebasename);
printf("Saving elements to %s\n", outelefilename);
fout = fopen(outelefilename, "w");
if (mesh_dim == 3) {
@ -2602,7 +2608,9 @@ void tetgenio::save_faces(const char* filebasename)
char outfacefilename[FILENAMESIZE];
int i;
sprintf(outfacefilename, "%s.face", filebasename);
// modified by Yi Zhang on 2023-12-22
//sprintf(outfacefilename, "%s.face", filebasename);
snprintf(outfacefilename, FILENAMESIZE, "%s.face", filebasename);
printf("Saving faces to %s\n", outfacefilename);
fout = fopen(outfacefilename, "w");
fprintf(fout, "%d %d\n", numberoftrifaces,
@ -2631,7 +2639,9 @@ void tetgenio::save_edges(char* filebasename)
char outedgefilename[FILENAMESIZE];
int i;
sprintf(outedgefilename, "%s.edge", filebasename);
// modified by Yi Zhang on 2023-12-22
//sprintf(outedgefilename, "%s.edge", filebasename);
snprintf(outedgefilename, FILENAMESIZE, "%s.edge", filebasename);
printf("Saving edges to %s\n", outedgefilename);
fout = fopen(outedgefilename, "w");
fprintf(fout, "%d %d\n", numberofedges, edgemarkerlist != NULL ? 1 : 0);
@ -2659,7 +2669,9 @@ void tetgenio::save_neighbors(char* filebasename)
char outneighborfilename[FILENAMESIZE];
int i;
sprintf(outneighborfilename, "%s.neigh", filebasename);
// modified by Yi Zhang on 2023-12-22
//sprintf(outneighborfilename, "%s.neigh", filebasename);
snprintf(outneighborfilename, FILENAMESIZE, "%s.neigh", filebasename);
printf("Saving neighbors to %s\n", outneighborfilename);
fout = fopen(outneighborfilename, "w");
fprintf(fout, "%d %d\n", numberoftetrahedra, mesh_dim + 1);
@ -2694,7 +2706,9 @@ void tetgenio::save_poly(const char *filebasename)
char outpolyfilename[FILENAMESIZE];
int i, j, k;
sprintf(outpolyfilename, "%s.poly", filebasename);
// modified by Yi Zhang on 2023-12-22
//sprintf(outpolyfilename, "%s.poly", filebasename);
snprintf(outpolyfilename, FILENAMESIZE, "%s.poly", filebasename);
printf("Saving poly to %s\n", outpolyfilename);
fout = fopen(outpolyfilename, "w");
@ -2792,7 +2806,9 @@ void tetgenio::save_faces2smesh(char* filebasename)
char outsmeshfilename[FILENAMESIZE];
int i, j;
sprintf(outsmeshfilename, "%s.smesh", filebasename);
// modified by Yi Zhang on 2023-12-22
//sprintf(outsmeshfilename, "%s.smesh", filebasename);
snprintf(outsmeshfilename, FILENAMESIZE, "%s.smesh", filebasename);
printf("Saving faces to %s\n", outsmeshfilename);
fout = fopen(outsmeshfilename, "w");
@ -2824,6 +2840,93 @@ void tetgenio::save_faces2smesh(char* filebasename)
fclose(fout);
}
//============================================================================//
// //
// save_mesh2gmsh() Save mesh to a .msh file. //
// //
//============================================================================//
void tetgenio::save_mesh2gmsh(const char *filebasename)
{
FILE *fout;
char outnodefilename[FILENAMESIZE];
char outmtrfilename[FILENAMESIZE];
int i, j;
if (numberofcorners != 4)
{
printf(" Write Gmsh not implemented for order 2 elements \n");
return;
}
// modified by Yi Zhang on 2023-12-22
//sprintf(outnodefilename, "%s.node", filebasename);
snprintf(outnodefilename, FILENAMESIZE, "%s.msh", filebasename);
printf("Saving mesh to %s\n", outnodefilename);
fout = fopen(outnodefilename, "w");
fprintf(fout, "$MeshFormat\n2.2 0 8\n$EndMeshFormat\n");
fprintf(fout, "$Nodes\n");
fprintf(fout, "%d\n", numberofpoints);
for (i = 0; i < numberofpoints; i++)
{
fprintf(fout, "%d %.16g %.16g %.16g\n", i + firstnumber,
pointlist[i * 3], pointlist[i * 3 + 1], pointlist[i * 3 + 2]);
}
fprintf(fout, "$EndNodes\n");
fprintf(fout, "$Elements\n");
fprintf(fout, "%d\n", numberoftetrahedra + numberoftrifaces);
int fac_tag = 0;
if (trifacemarkerlist != NULL) fac_tag = 1;
for (i = 0; i < numberoftrifaces; i++) {
fprintf(fout, "%d 2 %d", i + firstnumber, fac_tag);
if (trifacemarkerlist != NULL) {
fprintf(fout, " %d", trifacemarkerlist[i]);
}
fprintf(fout, " %d %d %d\n", trifacelist[i * 3], trifacelist[i * 3 + 1], trifacelist[i * 3 + 2]);
}
int st_number = numberoftrifaces + firstnumber;
for (i = 0; i < numberoftetrahedra; i++) {
fprintf(fout, "%d 4 %d", i + st_number, numberoftetrahedronattributes);
for (j = 0; j < numberoftetrahedronattributes; j++) {
fprintf(fout, " %g", tetrahedronattributelist[i * numberoftetrahedronattributes + j]);
}
for (j = 0; j < numberofcorners; j++) {
fprintf(fout, " %d", tetrahedronlist[i * numberofcorners + j]);
}
fprintf(fout, "\n");
}
fprintf(fout, "$EndElements\n");
if (trifacemarkerlist != NULL) {
fprintf(fout, "$ElementData\n1\n\"Face Tag\"\n1\n0\n3\n0\n1\n");
fprintf(fout, "%d\n", numberoftrifaces);
for (i = 0; i < numberoftrifaces; i++) {
fprintf(fout, "%d %d\n", i + firstnumber, trifacemarkerlist[i]);
}
fprintf(fout, "$EndElementData\n");
}
for (j = 0; j < numberoftetrahedronattributes; j++) {
//fprintf(fout, "$ElementData\n1\n\"Element Tag\"\n1\n0\n3\n0\n1\n");
fprintf(fout, "$ElementData\n1\n\"Element Tag");
fprintf(fout, " %d\"\n1\n0\n3\n0\n1\n", j+1);
fprintf(fout, "%d\n", numberoftetrahedra);
for (i = 0; i < numberoftetrahedra; i++) {
fprintf(fout, "%d %g\n", i + st_number, tetrahedronattributelist[i * numberoftetrahedronattributes + j]);
}
fprintf(fout, "$EndElementData\n");
}
fclose(fout);
}
//============================================================================//
// //
// readline() Read a nonempty line from a file. //
@ -2964,7 +3067,7 @@ char* tetgenio::findnextnumber(char *string)
void tetgenbehavior::syntax()
{
printf(" tetgen [-pYrq_Aa_miO_S_T_XMwcdzfenvgkJBNEFICQVh] input_file\n");
printf(" tetgen [-pYrq_Aa_miO_S_T_XMwcdzfenvgGkJBNEFICQVh] input_file\n"); // Modified by Yi Zhang
printf(" -p Tetrahedralizes a piecewise linear complex (PLC).\n");
printf(" -Y Preserves the input surface mesh (does not modify it).\n");
printf(" -r Reconstructs a previously generated mesh.\n");
@ -2987,6 +3090,7 @@ void tetgenbehavior::syntax()
printf(" -e Outputs all edges to .edge file.\n");
printf(" -n Outputs tetrahedra neighbors to .neigh file.\n");
printf(" -g Outputs mesh to .mesh file for viewing by Medit.\n");
printf(" -G Outputs mesh to .msh file for viewing by Gmsh.\n"); // Modified by Yi Zhang
printf(" -k Outputs mesh to .vtk file for viewing by Paraview.\n");
printf(" -J No jettison of unused vertices from output .node file.\n");
printf(" -B Suppresses output of boundary information.\n");
@ -3011,10 +3115,10 @@ void tetgenbehavior::usage()
printf("TetGen\n");
printf("A Quality Tetrahedral Mesh Generator and 3D Delaunay ");
printf("Triangulator\n");
printf("Version 1.6\n");
printf("August, 2020\n");
printf("Version 1.6.0_1\n");
printf("December, 2023\n");
printf("\n");
printf("Copyright (C) 2002 - 2020\n");
printf("Copyright (C) 2023\n");
printf("\n");
printf("What Can TetGen Do?\n");
printf("\n");
@ -3056,7 +3160,11 @@ void tetgenbehavior::usage()
printf("have volume\n of 0.1 or less, and writes the mesh to ");
printf("object.1.node, object.1.ele,\n object.1.face, and object.1.edge\n");
printf("\n");
printf("Please send bugs/comments to Hang Si <si@wias-berlin.de>\n");
printf("Please send bugs/comments to Hang Si <si@wias-berlin.de>\n\n");
printf("Updates:\n");
printf("(1) This version is modified to support outputs of Gmsh .msh file.\n");
printf("(2) Fixed a bug for outputing VTK files when the first node index is zero.\n");
printf("Please send corresponding bugs/comments to Yi Zhang <yizhang-geo@zju.edu.cn>\n");
terminatetetgen(NULL, 0);
}
@ -3423,6 +3531,8 @@ bool tetgenbehavior::parse_commandline(int argc, char **argv)
neighout++;
} else if (argv[i][j] == 'g') {
meditview = 1;
} else if (argv[i][j] == 'G') { // modified by Yi Zhang
gmshview = 1; // modified by Yi Zhang
} else if (argv[i][j] == 'k') {
if (argv[i][j + 1] == '2') { // -k2
vtksurfview = 1;
@ -3782,7 +3892,9 @@ bool tetgenbehavior::parse_commandline(int argc, char **argv)
workstring[increment] = '%';
workstring[increment + 1] = 'd';
workstring[increment + 2] = '\0';
sprintf(outfilename, workstring, meshnumber + 1);
// modified by Yi Zhang on 2023-12-22
//sprintf(outfilename, workstring, meshnumber + 1);
snprintf(outfilename, 1024, workstring, meshnumber + 1);
}
// Additional input file name has the end ".a".
strcpy(addinfilename, infilename);
@ -32989,13 +33101,17 @@ void tetgenmesh::qualitystatistics()
shortest, longest);
printf(" Smallest asp.ratio: %13.5g | Largest asp.ratio: %13.5g\n",
smallestratio, biggestratio);
sprintf(sbuf, "%.17g", biggestfaangle);
// modified by Yi Zhang on 2023-12-22
//sprintf(sbuf, "%.17g", biggestfaangle);
snprintf(sbuf, 128, "%.17g", biggestfaangle);
if (strlen(sbuf) > 8) {
sbuf[8] = '\0';
}
printf(" Smallest facangle: %14.5g | Largest facangle: %s\n",
smallestfaangle, sbuf);
sprintf(sbuf, "%.17g", biggestdiangle);
// modified by Yi Zhang on 2023-12-22
//sprintf(sbuf, "%.17g", biggestdiangle);
snprintf(sbuf, 128, "%.17g", biggestdiangle);
if (strlen(sbuf) > 8) {
sbuf[8] = '\0';
}
@ -35790,6 +35906,181 @@ void tetgenmesh::outmesh2medit(char* mfilename)
//============================================================================//
// //
// outmesh2gmsh() Write mesh to a .msh file, which can be read and //
// rendered by Gmsh (an open source 3D finite element mesh //
// generator with a built-in CAD engine and post-processor).//
// //
// You can specify a filename (without suffix) in 'mfilename'. If you don't //
// supply a filename (let mfilename be NULL), the default name stored in //
// 'tetgenbehavior' will be used. The output file will have the suffix .msh. //
// //
//============================================================================//
void tetgenmesh::outmesh2gmsh(char* mfilename)
{
FILE *outfile;
char mefilename[FILENAMESIZE];
tetrahedron* tetptr;
face faceloop;
point ptloop, p1, p2, p3, p4;
int pointnumber;
int marker;
if (b->order == 2) {
printf(" Write Gmsh not implemented for order 2 elements \n");
return;
}
if (mfilename != (char *) NULL && mfilename[0] != '\0') {
strcpy(mefilename, mfilename);
} else if (b->outfilename[0] != '\0') {
strcpy(mefilename, b->outfilename);
} else {
strcpy(mefilename, "unnamed");
}
strcat(mefilename, ".msh");
if (!b->quiet) {
printf("Writing %s.\n", mefilename);
}
outfile = fopen(mefilename, "w");
if (outfile == (FILE *) NULL) {
printf("File I/O Error: Cannot create file %s.\n", mefilename);
return;
}
fprintf(outfile, "$MeshFormat\n2.2 0 8\n$EndMeshFormat\n");
fprintf(outfile, "$Nodes\n");
fprintf(outfile, "%ld\n", points->items);
points->traversalinit();
ptloop = pointtraverse();
pointnumber = 1;
while (ptloop != (point) NULL) {
// Point coordinates.
fprintf(outfile, "%d %.17g %.17g %.17g\n", pointnumber, ptloop[0], ptloop[1], ptloop[2]);
setpointmark(ptloop, pointnumber);
ptloop = pointtraverse();
pointnumber++;
}
fprintf(outfile, "$EndNodes\n");
long ntets = tetrahedrons->items - hullsize;
long nfaces = subfaces->items;
fprintf(outfile, "$Elements\n");
fprintf(outfile, "%ld\n", ntets + nfaces);
int *face_marks = new int [nfaces];
double *ele_marks = new double [numelemattrib * ntets];
triface abuttingtet;
int t1ver;
subfaces->traversalinit();
faceloop.sh = shellfacetraverse(subfaces);
int facidx = 1;
while (faceloop.sh != (shellface *) NULL) {
stpivot(faceloop, abuttingtet);
// If there is a tetrahedron containing this subface, orient it so
// that the normal of this face points to inside of the volume by
// right-hand rule.
if (abuttingtet.tet != NULL) {
if (ishulltet(abuttingtet)) {
fsymself(abuttingtet);
}
}
if (abuttingtet.tet != NULL) {
p1 = org (abuttingtet);
p2 = dest(abuttingtet);
p3 = apex(abuttingtet);
} else {
// A dangling subfacet.
p1 = sorg(faceloop);
p2 = sdest(faceloop);
p3 = sapex(faceloop);
}
if (!b->nobound) {
marker = shellmark(faceloop);
face_marks[facidx-1] = marker;
}
fprintf(outfile, "%d 2 1 %d %d %d %d\n",
facidx, marker, pointmark(p1), pointmark(p2), pointmark(p3));
facidx++;
faceloop.sh = shellfacetraverse(subfaces);
}
tetrahedrons->traversalinit();
tetptr = tetrahedrontraverse();
int tetnumber = facidx;
int tetcount = 0;
while (tetptr != (tetrahedron *) NULL) {
if (!b->reversetetori) {
p1 = (point) tetptr[4];
p2 = (point) tetptr[5];
} else {
p1 = (point) tetptr[5];
p2 = (point) tetptr[4];
}
p3 = (point) tetptr[6];
p4 = (point) tetptr[7];
fprintf(outfile, "%d 4 %d", tetnumber, numelemattrib);
for (int i = 0; i < numelemattrib; i++) {
ele_marks[tetcount * numelemattrib + i] = elemattribute(tetptr, i);
fprintf(outfile, " %.17g", elemattribute(tetptr, i));
}
fprintf(outfile, " %d %d %d %d\n",
pointmark(p1), pointmark(p2),
pointmark(p3), pointmark(p4));
// Remember the index of this element (for counting edges).
setelemindex(tetptr, tetnumber);
tetptr = tetrahedrontraverse();
tetnumber++;
tetcount++;
}
fprintf(outfile, "$EndElements\n");
for (int i = 0; i < nfaces; i++)
{
fprintf(outfile, "$ElementData\n1\n\"Face Tag\"\n1\n0\n3\n0\n1\n");
fprintf(outfile, "%ld\n", nfaces);
for (i = 0; i < nfaces; i++) {
fprintf(outfile, "%d %d\n", i + 1, face_marks[i]);
}
fprintf(outfile, "$EndElementData\n");
}
tetnumber = nfaces + 1;
for (int j = 0; j < numelemattrib; j++) {
fprintf(outfile, "$ElementData\n1\n\"Element Tag");
fprintf(outfile, " %d\"\n1\n0\n3\n0\n1\n", j+1);
fprintf(outfile, "%ld\n", ntets);
for (int i = 0; i < ntets; i++) {
fprintf(outfile, "%d %g\n", i + tetnumber, ele_marks[i * numelemattrib + j]);
}
fprintf(outfile, "$EndElementData\n");
}
fclose(outfile);
delete[] face_marks;
delete[] ele_marks;
}
//============================================================================//
// //
@ -35820,7 +36111,9 @@ void tetgenmesh::outmesh2vtk(char* ofilename, int mesh_idx)
if (ofilename != (char *) NULL && ofilename[0] != '\0') {
//strcpy(vtkfilename, ofilename);
sprintf(vtkfilename, "%s.%d.vtk", ofilename, mesh_idx);
// modified by Yi Zhang on 2023-12-22
//sprintf(vtkfilename, "%s.%d.vtk", ofilename, mesh_idx);
snprintf(vtkfilename, FILENAMESIZE, "%s.%d.vtk", ofilename, mesh_idx);
} else if (b->outfilename[0] != '\0') {
strcpy(vtkfilename, b->outfilename);
strcat(vtkfilename, ".vtk");
@ -35863,6 +36156,7 @@ void tetgenmesh::outmesh2vtk(char* ofilename, int mesh_idx)
tetrahedrons->traversalinit();
tptr = tetrahedrontraverse();
//elementnumber = firstindex; // in->firstnumber;
int first_id = 1;
while (tptr != (tetrahedron *) NULL) {
if (!b->reversetetori) {
p1 = (point) tptr[4];
@ -35873,10 +36167,12 @@ void tetgenmesh::outmesh2vtk(char* ofilename, int mesh_idx)
}
p3 = (point) tptr[6];
p4 = (point) tptr[7];
n1 = pointmark(p1) - in->firstnumber;
n2 = pointmark(p2) - in->firstnumber;
n3 = pointmark(p3) - in->firstnumber;
n4 = pointmark(p4) - in->firstnumber;
// modified by Yi Zhang
// VTK's node index allways starts with zero
n1 = pointmark(p1) - first_id; //in->firstnumber;
n2 = pointmark(p2) - first_id; //in->firstnumber;
n3 = pointmark(p3) - first_id; //in->firstnumber;
n4 = pointmark(p4) - first_id; //in->firstnumber;
fprintf(outfile, "%d %4d %4d %4d %4d\n", nnodes, n1, n2, n3, n4);
tptr = tetrahedrontraverse();
}
@ -35929,7 +36225,9 @@ void tetgenmesh::out_surfmesh_vtk(char* ofilename, int mesh_idx)
if (ofilename != (char *) NULL && ofilename[0] != '\0') {
//strcpy(vtkfilename, ofilename);
sprintf(vtkfilename, "%s.%d.vtk", ofilename, mesh_idx);
// modified by Yi Zhang on 2023-12-22
//sprintf(vtkfilename, "%s.%d.vtk", ofilename, mesh_idx);
snprintf(vtkfilename, FILENAMESIZE, "%s.%d.vtk", ofilename, mesh_idx);
} else if (b->outfilename[0] != '\0') {
strcpy(vtkfilename, b->outfilename);
strcat(vtkfilename, ".surf.vtk");
@ -35972,6 +36270,7 @@ void tetgenmesh::out_surfmesh_vtk(char* ofilename, int mesh_idx)
subfaces->traversalinit();
faceloop.sh = shellfacetraverse(subfaces);
//facenumber = firstindex; // in->firstnumber;
int first_id = 1;
while (faceloop.sh != (shellface *) NULL) {
stpivot(faceloop, abuttingtet);
// If there is a tetrahedron containing this subface, orient it so
@ -35993,9 +36292,11 @@ void tetgenmesh::out_surfmesh_vtk(char* ofilename, int mesh_idx)
tapex = sapex(faceloop);
}
n1 = pointmark(torg) - in->firstnumber;
n2 = pointmark(tdest) - in->firstnumber;
n3 = pointmark(tapex) - in->firstnumber;
// modified by Yi Zhang
// VTK's node index allways starts with zero
n1 = pointmark(torg) - first_id; //in->firstnumber;
n2 = pointmark(tdest) - first_id; //in->firstnumber;
n3 = pointmark(tapex) - first_id; //in->firstnumber;
fprintf(outfile, "%d %4d %4d %4d\n", nnodes, n1, n2, n3);
//facenumber++;
@ -36452,6 +36753,10 @@ void tetrahedralize(tetgenbehavior *b, tetgenio *in, tetgenio *out,
m.outmesh2medit(b->outfilename);
}
// modified by Yi Zhang
if (!out && b->gmshview) {
m.outmesh2gmsh(b->outfilename);
}
if (!out && b->vtkview) {
m.outmesh2vtk(NULL, 0); // b->outfilename

View File

@ -45,6 +45,18 @@
// //
//============================================================================//
//============================================================================//
// Version 1.6.0_1 //
// December 22, 2023 //
// //
// Copyright (C) 2023 //
// //
// Yi Zhang //
// School of Earth Sciences, Zhejiang University //
// yizhang-geo@zju.edu.cn //
// //
// Modified based on v1.6.0 to support Gmsh outputs //
//============================================================================//
#ifndef tetgenH
#define tetgenH
@ -359,6 +371,7 @@ public:
void save_neighbors(char*);
void save_poly(const char*);
void save_faces2smesh(char*);
void save_mesh2gmsh(const char*);
// Read line and parse string functions.
char *readline(char* string, FILE* infile, int *linenumber);
@ -645,6 +658,7 @@ public:
int neighout; // '-n', 0.
int voroout; // '-v', 0.
int meditview; // '-g', 0.
int gmshview; // '-G', 0. // Modified by Yi Zhang
int vtkview; // '-k', 0.
int vtksurfview; // '-k', 0.
int nobound; // '-B', 0.
@ -765,6 +779,7 @@ public:
neighout = 0;
voroout = 0;
meditview = 0;
gmshview = 0; // Modified by Yi Zhang
vtkview = 0;
vtksurfview = 0;
nobound = 0;
@ -2230,6 +2245,7 @@ public:
void outvoronoi(tetgenio*);
void outsmesh(char*);
void outmesh2medit(char*);
void outmesh2gmsh(char*);
void outmesh2vtk(char*, int);
void out_surfmesh_vtk(char*, int);
void out_intersected_facets();

View File

@ -179,6 +179,14 @@ int main(int argc, char *argv[])
in.facetmarkerlist[4] = 0;
in.facetmarkerlist[5] = 0;
in.numberofregions = 1;
in.regionlist = new REAL [in.numberofregions * 5];
in.regionlist[0] = 1.0;
in.regionlist[1] = 1.0;
in.regionlist[2] = 6.0;
in.regionlist[3] = 2;
in.regionlist[4] = 0.1;
// Output the PLC to files 'barin.node' and 'barin.poly'.
in.save_nodes("barin");
in.save_poly("barin");
@ -187,12 +195,13 @@ int main(int argc, char *argv[])
// do quality mesh generation (q) with a specified quality bound
// (1.414), and apply a maximum volume constraint (a0.1).
tetrahedralize("pq1.414a0.1", &in, &out);
char opt[12] = "pq1.414Aa";
tetrahedralize(opt, &in, &out);
// Output mesh to files 'barout.node', 'barout.ele' and 'barout.face'.
out.save_nodes("barout");
out.save_elements("barout");
out.save_faces("barout");
out.save_mesh2gmsh("barout");
return 0;
}

View File

@ -2503,7 +2503,9 @@ void tetgenio::save_nodes(const char *filebasename)
char outmtrfilename[FILENAMESIZE];
int i, j;
sprintf(outnodefilename, "%s.node", filebasename);
// modified by Yi Zhang on 2023-12-22
//sprintf(outnodefilename, "%s.node", filebasename);
snprintf(outnodefilename, FILENAMESIZE, "%s.node", filebasename);
printf("Saving nodes to %s\n", outnodefilename);
fout = fopen(outnodefilename, "w");
fprintf(fout, "%d %d %d %d\n", numberofpoints, mesh_dim,
@ -2529,7 +2531,9 @@ void tetgenio::save_nodes(const char *filebasename)
// If the point metrics exist, output them to a .mtr file.
if ((numberofpointmtrs > 0) && (pointmtrlist != (REAL *) NULL)) {
sprintf(outmtrfilename, "%s.mtr", filebasename);
// modified by Yi Zhang on 2023-12-22
//sprintf(outmtrfilename, "%s.mtr", filebasename);
snprintf(outmtrfilename, FILENAMESIZE, "%s.mtr", filebasename);
printf("Saving metrics to %s\n", outmtrfilename);
fout = fopen(outmtrfilename, "w");
fprintf(fout, "%d %d\n", numberofpoints, numberofpointmtrs);
@ -2555,7 +2559,9 @@ void tetgenio::save_elements(const char* filebasename)
char outelefilename[FILENAMESIZE];
int i, j;
sprintf(outelefilename, "%s.ele", filebasename);
// modified by Yi Zhang on 2023-12-22
//sprintf(outelefilename, "%s.ele", filebasename);
snprintf(outelefilename, FILENAMESIZE, "%s.ele", filebasename);
printf("Saving elements to %s\n", outelefilename);
fout = fopen(outelefilename, "w");
if (mesh_dim == 3) {
@ -2602,7 +2608,9 @@ void tetgenio::save_faces(const char* filebasename)
char outfacefilename[FILENAMESIZE];
int i;
sprintf(outfacefilename, "%s.face", filebasename);
// modified by Yi Zhang on 2023-12-22
//sprintf(outfacefilename, "%s.face", filebasename);
snprintf(outfacefilename, FILENAMESIZE, "%s.face", filebasename);
printf("Saving faces to %s\n", outfacefilename);
fout = fopen(outfacefilename, "w");
fprintf(fout, "%d %d\n", numberoftrifaces,
@ -2631,7 +2639,9 @@ void tetgenio::save_edges(char* filebasename)
char outedgefilename[FILENAMESIZE];
int i;
sprintf(outedgefilename, "%s.edge", filebasename);
// modified by Yi Zhang on 2023-12-22
//sprintf(outedgefilename, "%s.edge", filebasename);
snprintf(outedgefilename, FILENAMESIZE, "%s.edge", filebasename);
printf("Saving edges to %s\n", outedgefilename);
fout = fopen(outedgefilename, "w");
fprintf(fout, "%d %d\n", numberofedges, edgemarkerlist != NULL ? 1 : 0);
@ -2659,7 +2669,9 @@ void tetgenio::save_neighbors(char* filebasename)
char outneighborfilename[FILENAMESIZE];
int i;
sprintf(outneighborfilename, "%s.neigh", filebasename);
// modified by Yi Zhang on 2023-12-22
//sprintf(outneighborfilename, "%s.neigh", filebasename);
snprintf(outneighborfilename, FILENAMESIZE, "%s.neigh", filebasename);
printf("Saving neighbors to %s\n", outneighborfilename);
fout = fopen(outneighborfilename, "w");
fprintf(fout, "%d %d\n", numberoftetrahedra, mesh_dim + 1);
@ -2694,7 +2706,9 @@ void tetgenio::save_poly(const char *filebasename)
char outpolyfilename[FILENAMESIZE];
int i, j, k;
sprintf(outpolyfilename, "%s.poly", filebasename);
// modified by Yi Zhang on 2023-12-22
//sprintf(outpolyfilename, "%s.poly", filebasename);
snprintf(outpolyfilename, FILENAMESIZE, "%s.poly", filebasename);
printf("Saving poly to %s\n", outpolyfilename);
fout = fopen(outpolyfilename, "w");
@ -2792,7 +2806,9 @@ void tetgenio::save_faces2smesh(char* filebasename)
char outsmeshfilename[FILENAMESIZE];
int i, j;
sprintf(outsmeshfilename, "%s.smesh", filebasename);
// modified by Yi Zhang on 2023-12-22
//sprintf(outsmeshfilename, "%s.smesh", filebasename);
snprintf(outsmeshfilename, FILENAMESIZE, "%s.smesh", filebasename);
printf("Saving faces to %s\n", outsmeshfilename);
fout = fopen(outsmeshfilename, "w");
@ -2824,6 +2840,93 @@ void tetgenio::save_faces2smesh(char* filebasename)
fclose(fout);
}
//============================================================================//
// //
// save_mesh2gmsh() Save mesh to a .msh file. //
// //
//============================================================================//
void tetgenio::save_mesh2gmsh(const char *filebasename)
{
FILE *fout;
char outnodefilename[FILENAMESIZE];
char outmtrfilename[FILENAMESIZE];
int i, j;
if (numberofcorners != 4)
{
printf(" Write Gmsh not implemented for order 2 elements \n");
return;
}
// modified by Yi Zhang on 2023-12-22
//sprintf(outnodefilename, "%s.node", filebasename);
snprintf(outnodefilename, FILENAMESIZE, "%s.msh", filebasename);
printf("Saving mesh to %s\n", outnodefilename);
fout = fopen(outnodefilename, "w");
fprintf(fout, "$MeshFormat\n2.2 0 8\n$EndMeshFormat\n");
fprintf(fout, "$Nodes\n");
fprintf(fout, "%d\n", numberofpoints);
for (i = 0; i < numberofpoints; i++)
{
fprintf(fout, "%d %.16g %.16g %.16g\n", i + firstnumber,
pointlist[i * 3], pointlist[i * 3 + 1], pointlist[i * 3 + 2]);
}
fprintf(fout, "$EndNodes\n");
fprintf(fout, "$Elements\n");
fprintf(fout, "%d\n", numberoftetrahedra + numberoftrifaces);
int fac_tag = 0;
if (trifacemarkerlist != NULL) fac_tag = 1;
for (i = 0; i < numberoftrifaces; i++) {
fprintf(fout, "%d 2 %d", i + firstnumber, fac_tag);
if (trifacemarkerlist != NULL) {
fprintf(fout, " %d", trifacemarkerlist[i]);
}
fprintf(fout, " %d %d %d\n", trifacelist[i * 3], trifacelist[i * 3 + 1], trifacelist[i * 3 + 2]);
}
int st_number = numberoftrifaces + firstnumber;
for (i = 0; i < numberoftetrahedra; i++) {
fprintf(fout, "%d 4 %d", i + st_number, numberoftetrahedronattributes);
for (j = 0; j < numberoftetrahedronattributes; j++) {
fprintf(fout, " %g", tetrahedronattributelist[i * numberoftetrahedronattributes + j]);
}
for (j = 0; j < numberofcorners; j++) {
fprintf(fout, " %d", tetrahedronlist[i * numberofcorners + j]);
}
fprintf(fout, "\n");
}
fprintf(fout, "$EndElements\n");
if (trifacemarkerlist != NULL) {
fprintf(fout, "$ElementData\n1\n\"Face Tag\"\n1\n0\n3\n0\n1\n");
fprintf(fout, "%d\n", numberoftrifaces);
for (i = 0; i < numberoftrifaces; i++) {
fprintf(fout, "%d %d\n", i + firstnumber, trifacemarkerlist[i]);
}
fprintf(fout, "$EndElementData\n");
}
for (j = 0; j < numberoftetrahedronattributes; j++) {
//fprintf(fout, "$ElementData\n1\n\"Element Tag\"\n1\n0\n3\n0\n1\n");
fprintf(fout, "$ElementData\n1\n\"Element Tag");
fprintf(fout, " %d\"\n1\n0\n3\n0\n1\n", j+1);
fprintf(fout, "%d\n", numberoftetrahedra);
for (i = 0; i < numberoftetrahedra; i++) {
fprintf(fout, "%d %g\n", i + st_number, tetrahedronattributelist[i * numberoftetrahedronattributes + j]);
}
fprintf(fout, "$EndElementData\n");
}
fclose(fout);
}
//============================================================================//
// //
// readline() Read a nonempty line from a file. //
@ -2964,7 +3067,7 @@ char* tetgenio::findnextnumber(char *string)
void tetgenbehavior::syntax()
{
printf(" tetgen [-pYrq_Aa_miO_S_T_XMwcdzfenvgkJBNEFICQVh] input_file\n");
printf(" tetgen [-pYrq_Aa_miO_S_T_XMwcdzfenvgGkJBNEFICQVh] input_file\n"); // Modified by Yi Zhang
printf(" -p Tetrahedralizes a piecewise linear complex (PLC).\n");
printf(" -Y Preserves the input surface mesh (does not modify it).\n");
printf(" -r Reconstructs a previously generated mesh.\n");
@ -2987,6 +3090,7 @@ void tetgenbehavior::syntax()
printf(" -e Outputs all edges to .edge file.\n");
printf(" -n Outputs tetrahedra neighbors to .neigh file.\n");
printf(" -g Outputs mesh to .mesh file for viewing by Medit.\n");
printf(" -G Outputs mesh to .msh file for viewing by Gmsh.\n"); // Modified by Yi Zhang
printf(" -k Outputs mesh to .vtk file for viewing by Paraview.\n");
printf(" -J No jettison of unused vertices from output .node file.\n");
printf(" -B Suppresses output of boundary information.\n");
@ -3011,10 +3115,10 @@ void tetgenbehavior::usage()
printf("TetGen\n");
printf("A Quality Tetrahedral Mesh Generator and 3D Delaunay ");
printf("Triangulator\n");
printf("Version 1.6\n");
printf("August, 2020\n");
printf("Version 1.6.0_1\n");
printf("December, 2023\n");
printf("\n");
printf("Copyright (C) 2002 - 2020\n");
printf("Copyright (C) 2023\n");
printf("\n");
printf("What Can TetGen Do?\n");
printf("\n");
@ -3056,7 +3160,11 @@ void tetgenbehavior::usage()
printf("have volume\n of 0.1 or less, and writes the mesh to ");
printf("object.1.node, object.1.ele,\n object.1.face, and object.1.edge\n");
printf("\n");
printf("Please send bugs/comments to Hang Si <si@wias-berlin.de>\n");
printf("Please send bugs/comments to Hang Si <si@wias-berlin.de>\n\n");
printf("Updates:\n");
printf("(1) This version is modified to support outputs of Gmsh .msh file.\n");
printf("(2) Fixed a bug for outputing VTK files when the first node index is zero.\n");
printf("Please send corresponding bugs/comments to Yi Zhang <yizhang-geo@zju.edu.cn>\n");
terminatetetgen(NULL, 0);
}
@ -3423,6 +3531,8 @@ bool tetgenbehavior::parse_commandline(int argc, char **argv)
neighout++;
} else if (argv[i][j] == 'g') {
meditview = 1;
} else if (argv[i][j] == 'G') { // modified by Yi Zhang
gmshview = 1; // modified by Yi Zhang
} else if (argv[i][j] == 'k') {
if (argv[i][j + 1] == '2') { // -k2
vtksurfview = 1;
@ -3782,7 +3892,9 @@ bool tetgenbehavior::parse_commandline(int argc, char **argv)
workstring[increment] = '%';
workstring[increment + 1] = 'd';
workstring[increment + 2] = '\0';
sprintf(outfilename, workstring, meshnumber + 1);
// modified by Yi Zhang on 2023-12-22
//sprintf(outfilename, workstring, meshnumber + 1);
snprintf(outfilename, 1024, workstring, meshnumber + 1);
}
// Additional input file name has the end ".a".
strcpy(addinfilename, infilename);
@ -32989,13 +33101,17 @@ void tetgenmesh::qualitystatistics()
shortest, longest);
printf(" Smallest asp.ratio: %13.5g | Largest asp.ratio: %13.5g\n",
smallestratio, biggestratio);
sprintf(sbuf, "%.17g", biggestfaangle);
// modified by Yi Zhang on 2023-12-22
//sprintf(sbuf, "%.17g", biggestfaangle);
snprintf(sbuf, 128, "%.17g", biggestfaangle);
if (strlen(sbuf) > 8) {
sbuf[8] = '\0';
}
printf(" Smallest facangle: %14.5g | Largest facangle: %s\n",
smallestfaangle, sbuf);
sprintf(sbuf, "%.17g", biggestdiangle);
// modified by Yi Zhang on 2023-12-22
//sprintf(sbuf, "%.17g", biggestdiangle);
snprintf(sbuf, 128, "%.17g", biggestdiangle);
if (strlen(sbuf) > 8) {
sbuf[8] = '\0';
}
@ -35790,6 +35906,181 @@ void tetgenmesh::outmesh2medit(char* mfilename)
//============================================================================//
// //
// outmesh2gmsh() Write mesh to a .msh file, which can be read and //
// rendered by Gmsh (an open source 3D finite element mesh //
// generator with a built-in CAD engine and post-processor).//
// //
// You can specify a filename (without suffix) in 'mfilename'. If you don't //
// supply a filename (let mfilename be NULL), the default name stored in //
// 'tetgenbehavior' will be used. The output file will have the suffix .msh. //
// //
//============================================================================//
void tetgenmesh::outmesh2gmsh(char* mfilename)
{
FILE *outfile;
char mefilename[FILENAMESIZE];
tetrahedron* tetptr;
face faceloop;
point ptloop, p1, p2, p3, p4;
int pointnumber;
int marker;
if (b->order == 2) {
printf(" Write Gmsh not implemented for order 2 elements \n");
return;
}
if (mfilename != (char *) NULL && mfilename[0] != '\0') {
strcpy(mefilename, mfilename);
} else if (b->outfilename[0] != '\0') {
strcpy(mefilename, b->outfilename);
} else {
strcpy(mefilename, "unnamed");
}
strcat(mefilename, ".msh");
if (!b->quiet) {
printf("Writing %s.\n", mefilename);
}
outfile = fopen(mefilename, "w");
if (outfile == (FILE *) NULL) {
printf("File I/O Error: Cannot create file %s.\n", mefilename);
return;
}
fprintf(outfile, "$MeshFormat\n2.2 0 8\n$EndMeshFormat\n");
fprintf(outfile, "$Nodes\n");
fprintf(outfile, "%ld\n", points->items);
points->traversalinit();
ptloop = pointtraverse();
pointnumber = 1;
while (ptloop != (point) NULL) {
// Point coordinates.
fprintf(outfile, "%d %.17g %.17g %.17g\n", pointnumber, ptloop[0], ptloop[1], ptloop[2]);
setpointmark(ptloop, pointnumber);
ptloop = pointtraverse();
pointnumber++;
}
fprintf(outfile, "$EndNodes\n");
long ntets = tetrahedrons->items - hullsize;
long nfaces = subfaces->items;
fprintf(outfile, "$Elements\n");
fprintf(outfile, "%ld\n", ntets + nfaces);
int *face_marks = new int [nfaces];
double *ele_marks = new double [numelemattrib * ntets];
triface abuttingtet;
int t1ver;
subfaces->traversalinit();
faceloop.sh = shellfacetraverse(subfaces);
int facidx = 1;
while (faceloop.sh != (shellface *) NULL) {
stpivot(faceloop, abuttingtet);
// If there is a tetrahedron containing this subface, orient it so
// that the normal of this face points to inside of the volume by
// right-hand rule.
if (abuttingtet.tet != NULL) {
if (ishulltet(abuttingtet)) {
fsymself(abuttingtet);
}
}
if (abuttingtet.tet != NULL) {
p1 = org (abuttingtet);
p2 = dest(abuttingtet);
p3 = apex(abuttingtet);
} else {
// A dangling subfacet.
p1 = sorg(faceloop);
p2 = sdest(faceloop);
p3 = sapex(faceloop);
}
if (!b->nobound) {
marker = shellmark(faceloop);
face_marks[facidx-1] = marker;
}
fprintf(outfile, "%d 2 1 %d %d %d %d\n",
facidx, marker, pointmark(p1), pointmark(p2), pointmark(p3));
facidx++;
faceloop.sh = shellfacetraverse(subfaces);
}
tetrahedrons->traversalinit();
tetptr = tetrahedrontraverse();
int tetnumber = facidx;
int tetcount = 0;
while (tetptr != (tetrahedron *) NULL) {
if (!b->reversetetori) {
p1 = (point) tetptr[4];
p2 = (point) tetptr[5];
} else {
p1 = (point) tetptr[5];
p2 = (point) tetptr[4];
}
p3 = (point) tetptr[6];
p4 = (point) tetptr[7];
fprintf(outfile, "%d 4 %d", tetnumber, numelemattrib);
for (int i = 0; i < numelemattrib; i++) {
ele_marks[tetcount * numelemattrib + i] = elemattribute(tetptr, i);
fprintf(outfile, " %.17g", elemattribute(tetptr, i));
}
fprintf(outfile, " %d %d %d %d\n",
pointmark(p1), pointmark(p2),
pointmark(p3), pointmark(p4));
// Remember the index of this element (for counting edges).
setelemindex(tetptr, tetnumber);
tetptr = tetrahedrontraverse();
tetnumber++;
tetcount++;
}
fprintf(outfile, "$EndElements\n");
for (int i = 0; i < nfaces; i++)
{
fprintf(outfile, "$ElementData\n1\n\"Face Tag\"\n1\n0\n3\n0\n1\n");
fprintf(outfile, "%ld\n", nfaces);
for (i = 0; i < nfaces; i++) {
fprintf(outfile, "%d %d\n", i + 1, face_marks[i]);
}
fprintf(outfile, "$EndElementData\n");
}
tetnumber = nfaces + 1;
for (int j = 0; j < numelemattrib; j++) {
fprintf(outfile, "$ElementData\n1\n\"Element Tag");
fprintf(outfile, " %d\"\n1\n0\n3\n0\n1\n", j+1);
fprintf(outfile, "%ld\n", ntets);
for (int i = 0; i < ntets; i++) {
fprintf(outfile, "%d %g\n", i + tetnumber, ele_marks[i * numelemattrib + j]);
}
fprintf(outfile, "$EndElementData\n");
}
fclose(outfile);
delete[] face_marks;
delete[] ele_marks;
}
//============================================================================//
// //
@ -35820,7 +36111,9 @@ void tetgenmesh::outmesh2vtk(char* ofilename, int mesh_idx)
if (ofilename != (char *) NULL && ofilename[0] != '\0') {
//strcpy(vtkfilename, ofilename);
sprintf(vtkfilename, "%s.%d.vtk", ofilename, mesh_idx);
// modified by Yi Zhang on 2023-12-22
//sprintf(vtkfilename, "%s.%d.vtk", ofilename, mesh_idx);
snprintf(vtkfilename, FILENAMESIZE, "%s.%d.vtk", ofilename, mesh_idx);
} else if (b->outfilename[0] != '\0') {
strcpy(vtkfilename, b->outfilename);
strcat(vtkfilename, ".vtk");
@ -35863,6 +36156,7 @@ void tetgenmesh::outmesh2vtk(char* ofilename, int mesh_idx)
tetrahedrons->traversalinit();
tptr = tetrahedrontraverse();
//elementnumber = firstindex; // in->firstnumber;
int first_id = 1;
while (tptr != (tetrahedron *) NULL) {
if (!b->reversetetori) {
p1 = (point) tptr[4];
@ -35873,10 +36167,12 @@ void tetgenmesh::outmesh2vtk(char* ofilename, int mesh_idx)
}
p3 = (point) tptr[6];
p4 = (point) tptr[7];
n1 = pointmark(p1) - in->firstnumber;
n2 = pointmark(p2) - in->firstnumber;
n3 = pointmark(p3) - in->firstnumber;
n4 = pointmark(p4) - in->firstnumber;
// modified by Yi Zhang
// VTK's node index allways starts with zero
n1 = pointmark(p1) - first_id; //in->firstnumber;
n2 = pointmark(p2) - first_id; //in->firstnumber;
n3 = pointmark(p3) - first_id; //in->firstnumber;
n4 = pointmark(p4) - first_id; //in->firstnumber;
fprintf(outfile, "%d %4d %4d %4d %4d\n", nnodes, n1, n2, n3, n4);
tptr = tetrahedrontraverse();
}
@ -35929,7 +36225,9 @@ void tetgenmesh::out_surfmesh_vtk(char* ofilename, int mesh_idx)
if (ofilename != (char *) NULL && ofilename[0] != '\0') {
//strcpy(vtkfilename, ofilename);
sprintf(vtkfilename, "%s.%d.vtk", ofilename, mesh_idx);
// modified by Yi Zhang on 2023-12-22
//sprintf(vtkfilename, "%s.%d.vtk", ofilename, mesh_idx);
snprintf(vtkfilename, FILENAMESIZE, "%s.%d.vtk", ofilename, mesh_idx);
} else if (b->outfilename[0] != '\0') {
strcpy(vtkfilename, b->outfilename);
strcat(vtkfilename, ".surf.vtk");
@ -35972,6 +36270,7 @@ void tetgenmesh::out_surfmesh_vtk(char* ofilename, int mesh_idx)
subfaces->traversalinit();
faceloop.sh = shellfacetraverse(subfaces);
//facenumber = firstindex; // in->firstnumber;
int first_id = 1;
while (faceloop.sh != (shellface *) NULL) {
stpivot(faceloop, abuttingtet);
// If there is a tetrahedron containing this subface, orient it so
@ -35993,9 +36292,11 @@ void tetgenmesh::out_surfmesh_vtk(char* ofilename, int mesh_idx)
tapex = sapex(faceloop);
}
n1 = pointmark(torg) - in->firstnumber;
n2 = pointmark(tdest) - in->firstnumber;
n3 = pointmark(tapex) - in->firstnumber;
// modified by Yi Zhang
// VTK's node index allways starts with zero
n1 = pointmark(torg) - first_id; //in->firstnumber;
n2 = pointmark(tdest) - first_id; //in->firstnumber;
n3 = pointmark(tapex) - first_id; //in->firstnumber;
fprintf(outfile, "%d %4d %4d %4d\n", nnodes, n1, n2, n3);
//facenumber++;
@ -36452,6 +36753,10 @@ void tetrahedralize(tetgenbehavior *b, tetgenio *in, tetgenio *out,
m.outmesh2medit(b->outfilename);
}
// modified by Yi Zhang
if (!out && b->gmshview) {
m.outmesh2gmsh(b->outfilename);
}
if (!out && b->vtkview) {
m.outmesh2vtk(NULL, 0); // b->outfilename

View File

@ -45,6 +45,18 @@
// //
//============================================================================//
//============================================================================//
// Version 1.6.0_1 //
// December 22, 2023 //
// //
// Copyright (C) 2023 //
// //
// Yi Zhang //
// School of Earth Sciences, Zhejiang University //
// yizhang-geo@zju.edu.cn //
// //
// Modified based on v1.6.0 to support Gmsh outputs //
//============================================================================//
#ifndef tetgenH
#define tetgenH
@ -359,6 +371,7 @@ public:
void save_neighbors(char*);
void save_poly(const char*);
void save_faces2smesh(char*);
void save_mesh2gmsh(const char*);
// Read line and parse string functions.
char *readline(char* string, FILE* infile, int *linenumber);
@ -645,6 +658,7 @@ public:
int neighout; // '-n', 0.
int voroout; // '-v', 0.
int meditview; // '-g', 0.
int gmshview; // '-G', 0. // Modified by Yi Zhang
int vtkview; // '-k', 0.
int vtksurfview; // '-k', 0.
int nobound; // '-B', 0.
@ -765,6 +779,7 @@ public:
neighout = 0;
voroout = 0;
meditview = 0;
gmshview = 0; // Modified by Yi Zhang
vtkview = 0;
vtksurfview = 0;
nobound = 0;
@ -2230,6 +2245,7 @@ public:
void outvoronoi(tetgenio*);
void outsmesh(char*);
void outmesh2medit(char*);
void outmesh2gmsh(char*);
void outmesh2vtk(char*, int);
void out_surfmesh_vtk(char*, int);
void out_intersected_facets();

4710
v1.6/predicates.cxx Normal file

File diff suppressed because it is too large Load Diff

198
v1.6/tetcall.cxx Normal file
View File

@ -0,0 +1,198 @@
///////////////////////////////////////////////////////////////////////////////
// //
// tetcall.cxx //
// //
// An example of how to call TetGen from another program by using the data //
// type "tetgenio" and function "tetrahedralize()" of TetGen libaray. //
// //
// In order to run this example, you need the library of TetGen, you can get //
// the source code as well as the user's manul of TetGen from: //
// //
// http://tetgen.berlios.de/index.html //
// //
// Section 2 of the user's manual contains the information of how to compile //
// TetGen into a libaray. //
// //
// The geometry used in this example (illustrated in Section 3.3 .1, Figure //
// 12 of the user's manual) is a rectangluar bar consists of 8 points and 6 //
// facets (which are all rectangles). In additional, there are two boundary //
// markers defined on its facets. //
// //
// This code illustrates the following basic steps: //
// - at first create an input object "in", and set data of the geometry //
// into it. //
// - then call function "tetrahedralize()" to create a quality mesh of the //
// geometry with output in another object "out". //
// In addition, It outputs the geometry in the object "in" into two files //
// (barin.node and barin.poly), and outputs the mesh in the object "out" //
// into three files (barout.node, barout.ele, and barout.face). These files //
// can be visualized by TetView. //
// //
// To compile this code into an executable program, do the following steps: //
// - compile TetGen into a library named "libtet.a" (see Section 2.1 of //
// the user's manula for compiling); //
// - Save this file into the same directory in which you have the files //
// "tetgen.h" and "libtet.a"; //
// - compile it using the following command: //
// //
// g++ -o test tetcall.cxx -L./ -ltet //
// //
// which will result an executable program named "test". //
// //
// Please send your quesions, comments to Hang Si <si@wias-berlin.de> //
// //
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
// //
// main() Create and refine a mesh using TetGen library. //
// //
///////////////////////////////////////////////////////////////////////////////
#include "../lib/tetgen.h" // Defined tetgenio, tetrahedralize().
int main(int argc, char *argv[])
{
tetgenio in, out;
tetgenio::facet *f;
tetgenio::polygon *p;
int i;
// All indices start from 1.
in.firstnumber = 1;
in.numberofpoints = 8;
in.pointlist = new REAL[in.numberofpoints * 3];
in.pointlist[0] = 0; // node 1.
in.pointlist[1] = 0;
in.pointlist[2] = 0;
in.pointlist[3] = 2; // node 2.
in.pointlist[4] = 0;
in.pointlist[5] = 0;
in.pointlist[6] = 2; // node 3.
in.pointlist[7] = 2;
in.pointlist[8] = 0;
in.pointlist[9] = 0; // node 4.
in.pointlist[10] = 2;
in.pointlist[11] = 0;
// Set node 5, 6, 7, 8.
for (i = 4; i < 8; i++) {
in.pointlist[i * 3] = in.pointlist[(i - 4) * 3];
in.pointlist[i * 3 + 1] = in.pointlist[(i - 4) * 3 + 1];
in.pointlist[i * 3 + 2] = 12;
}
in.numberoffacets = 6;
in.facetlist = new tetgenio::facet[in.numberoffacets];
in.facetmarkerlist = new int[in.numberoffacets];
// Facet 1. The leftmost facet.
f = &in.facetlist[0];
f->numberofpolygons = 1;
f->polygonlist = new tetgenio::polygon[f->numberofpolygons];
f->numberofholes = 0;
f->holelist = NULL;
p = &f->polygonlist[0];
p->numberofvertices = 4;
p->vertexlist = new int[p->numberofvertices];
p->vertexlist[0] = 1;
p->vertexlist[1] = 2;
p->vertexlist[2] = 3;
p->vertexlist[3] = 4;
// Facet 2. The rightmost facet.
f = &in.facetlist[1];
f->numberofpolygons = 1;
f->polygonlist = new tetgenio::polygon[f->numberofpolygons];
f->numberofholes = 0;
f->holelist = NULL;
p = &f->polygonlist[0];
p->numberofvertices = 4;
p->vertexlist = new int[p->numberofvertices];
p->vertexlist[0] = 5;
p->vertexlist[1] = 6;
p->vertexlist[2] = 7;
p->vertexlist[3] = 8;
// Facet 3. The bottom facet.
f = &in.facetlist[2];
f->numberofpolygons = 1;
f->polygonlist = new tetgenio::polygon[f->numberofpolygons];
f->numberofholes = 0;
f->holelist = NULL;
p = &f->polygonlist[0];
p->numberofvertices = 4;
p->vertexlist = new int[p->numberofvertices];
p->vertexlist[0] = 1;
p->vertexlist[1] = 5;
p->vertexlist[2] = 6;
p->vertexlist[3] = 2;
// Facet 4. The back facet.
f = &in.facetlist[3];
f->numberofpolygons = 1;
f->polygonlist = new tetgenio::polygon[f->numberofpolygons];
f->numberofholes = 0;
f->holelist = NULL;
p = &f->polygonlist[0];
p->numberofvertices = 4;
p->vertexlist = new int[p->numberofvertices];
p->vertexlist[0] = 2;
p->vertexlist[1] = 6;
p->vertexlist[2] = 7;
p->vertexlist[3] = 3;
// Facet 5. The top facet.
f = &in.facetlist[4];
f->numberofpolygons = 1;
f->polygonlist = new tetgenio::polygon[f->numberofpolygons];
f->numberofholes = 0;
f->holelist = NULL;
p = &f->polygonlist[0];
p->numberofvertices = 4;
p->vertexlist = new int[p->numberofvertices];
p->vertexlist[0] = 3;
p->vertexlist[1] = 7;
p->vertexlist[2] = 8;
p->vertexlist[3] = 4;
// Facet 6. The front facet.
f = &in.facetlist[5];
f->numberofpolygons = 1;
f->polygonlist = new tetgenio::polygon[f->numberofpolygons];
f->numberofholes = 0;
f->holelist = NULL;
p = &f->polygonlist[0];
p->numberofvertices = 4;
p->vertexlist = new int[p->numberofvertices];
p->vertexlist[0] = 4;
p->vertexlist[1] = 8;
p->vertexlist[2] = 5;
p->vertexlist[3] = 1;
// Set 'in.facetmarkerlist'
in.facetmarkerlist[0] = -1;
in.facetmarkerlist[1] = -2;
in.facetmarkerlist[2] = 0;
in.facetmarkerlist[3] = 0;
in.facetmarkerlist[4] = 0;
in.facetmarkerlist[5] = 0;
// Output the PLC to files 'barin.node' and 'barin.poly'.
in.save_nodes("barin");
in.save_poly("barin");
// Tetrahedralize the PLC. Switches are chosen to read a PLC (p),
// do quality mesh generation (q) with a specified quality bound
// (1.414), and apply a maximum volume constraint (a0.1).
tetrahedralize("pq1.414a0.1", &in, &out);
// Output mesh to files 'barout.node', 'barout.ele' and 'barout.face'.
out.save_nodes("barout");
out.save_elements("barout");
out.save_faces("barout");
return 0;
}

36567
v1.6/tetgen.cxx Normal file

File diff suppressed because it is too large Load Diff

3613
v1.6/tetgen.h Normal file

File diff suppressed because it is too large Load Diff