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. Please see the documentation of TetGen for compiling and using TetGen.
It is available at the following link: It is available at the following link:
@ -21,4 +21,12 @@ For more information on this product, contact :
BEFORE INTALLING OR USING TetGen(R) READ the BEFORE INTALLING OR USING TetGen(R) READ the
GENERAL LICENSE TERMS AND CONDITIONS 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]; char outmtrfilename[FILENAMESIZE];
int i, j; 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); printf("Saving nodes to %s\n", outnodefilename);
fout = fopen(outnodefilename, "w"); fout = fopen(outnodefilename, "w");
fprintf(fout, "%d %d %d %d\n", numberofpoints, mesh_dim, 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 the point metrics exist, output them to a .mtr file.
if ((numberofpointmtrs > 0) && (pointmtrlist != (REAL *) NULL)) { 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); printf("Saving metrics to %s\n", outmtrfilename);
fout = fopen(outmtrfilename, "w"); fout = fopen(outmtrfilename, "w");
fprintf(fout, "%d %d\n", numberofpoints, numberofpointmtrs); fprintf(fout, "%d %d\n", numberofpoints, numberofpointmtrs);
@ -2555,7 +2559,9 @@ void tetgenio::save_elements(const char* filebasename)
char outelefilename[FILENAMESIZE]; char outelefilename[FILENAMESIZE];
int i, j; 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); printf("Saving elements to %s\n", outelefilename);
fout = fopen(outelefilename, "w"); fout = fopen(outelefilename, "w");
if (mesh_dim == 3) { if (mesh_dim == 3) {
@ -2602,7 +2608,9 @@ void tetgenio::save_faces(const char* filebasename)
char outfacefilename[FILENAMESIZE]; char outfacefilename[FILENAMESIZE];
int i; 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); printf("Saving faces to %s\n", outfacefilename);
fout = fopen(outfacefilename, "w"); fout = fopen(outfacefilename, "w");
fprintf(fout, "%d %d\n", numberoftrifaces, fprintf(fout, "%d %d\n", numberoftrifaces,
@ -2631,7 +2639,9 @@ void tetgenio::save_edges(char* filebasename)
char outedgefilename[FILENAMESIZE]; char outedgefilename[FILENAMESIZE];
int i; 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); printf("Saving edges to %s\n", outedgefilename);
fout = fopen(outedgefilename, "w"); fout = fopen(outedgefilename, "w");
fprintf(fout, "%d %d\n", numberofedges, edgemarkerlist != NULL ? 1 : 0); fprintf(fout, "%d %d\n", numberofedges, edgemarkerlist != NULL ? 1 : 0);
@ -2659,7 +2669,9 @@ void tetgenio::save_neighbors(char* filebasename)
char outneighborfilename[FILENAMESIZE]; char outneighborfilename[FILENAMESIZE];
int i; 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); printf("Saving neighbors to %s\n", outneighborfilename);
fout = fopen(outneighborfilename, "w"); fout = fopen(outneighborfilename, "w");
fprintf(fout, "%d %d\n", numberoftetrahedra, mesh_dim + 1); fprintf(fout, "%d %d\n", numberoftetrahedra, mesh_dim + 1);
@ -2694,7 +2706,9 @@ void tetgenio::save_poly(const char *filebasename)
char outpolyfilename[FILENAMESIZE]; char outpolyfilename[FILENAMESIZE];
int i, j, k; 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); printf("Saving poly to %s\n", outpolyfilename);
fout = fopen(outpolyfilename, "w"); fout = fopen(outpolyfilename, "w");
@ -2792,7 +2806,9 @@ void tetgenio::save_faces2smesh(char* filebasename)
char outsmeshfilename[FILENAMESIZE]; char outsmeshfilename[FILENAMESIZE];
int i, j; 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); printf("Saving faces to %s\n", outsmeshfilename);
fout = fopen(outsmeshfilename, "w"); fout = fopen(outsmeshfilename, "w");
@ -2824,6 +2840,93 @@ void tetgenio::save_faces2smesh(char* filebasename)
fclose(fout); 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. // // readline() Read a nonempty line from a file. //
@ -2964,7 +3067,7 @@ char* tetgenio::findnextnumber(char *string)
void tetgenbehavior::syntax() 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(" -p Tetrahedralizes a piecewise linear complex (PLC).\n");
printf(" -Y Preserves the input surface mesh (does not modify it).\n"); printf(" -Y Preserves the input surface mesh (does not modify it).\n");
printf(" -r Reconstructs a previously generated mesh.\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(" -e Outputs all edges to .edge file.\n");
printf(" -n Outputs tetrahedra neighbors to .neigh 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 .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(" -k Outputs mesh to .vtk file for viewing by Paraview.\n");
printf(" -J No jettison of unused vertices from output .node file.\n"); printf(" -J No jettison of unused vertices from output .node file.\n");
printf(" -B Suppresses output of boundary information.\n"); printf(" -B Suppresses output of boundary information.\n");
@ -3011,10 +3115,10 @@ void tetgenbehavior::usage()
printf("TetGen\n"); printf("TetGen\n");
printf("A Quality Tetrahedral Mesh Generator and 3D Delaunay "); printf("A Quality Tetrahedral Mesh Generator and 3D Delaunay ");
printf("Triangulator\n"); printf("Triangulator\n");
printf("Version 1.6\n"); printf("Version 1.6.0_1\n");
printf("August, 2020\n"); printf("December, 2023\n");
printf("\n"); printf("\n");
printf("Copyright (C) 2002 - 2020\n"); printf("Copyright (C) 2023\n");
printf("\n"); printf("\n");
printf("What Can TetGen Do?\n"); printf("What Can TetGen Do?\n");
printf("\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("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("object.1.node, object.1.ele,\n object.1.face, and object.1.edge\n");
printf("\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); terminatetetgen(NULL, 0);
} }
@ -3423,6 +3531,8 @@ bool tetgenbehavior::parse_commandline(int argc, char **argv)
neighout++; neighout++;
} else if (argv[i][j] == 'g') { } else if (argv[i][j] == 'g') {
meditview = 1; meditview = 1;
} else if (argv[i][j] == 'G') { // modified by Yi Zhang
gmshview = 1; // modified by Yi Zhang
} else if (argv[i][j] == 'k') { } else if (argv[i][j] == 'k') {
if (argv[i][j + 1] == '2') { // -k2 if (argv[i][j + 1] == '2') { // -k2
vtksurfview = 1; vtksurfview = 1;
@ -3782,7 +3892,9 @@ bool tetgenbehavior::parse_commandline(int argc, char **argv)
workstring[increment] = '%'; workstring[increment] = '%';
workstring[increment + 1] = 'd'; workstring[increment + 1] = 'd';
workstring[increment + 2] = '\0'; 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". // Additional input file name has the end ".a".
strcpy(addinfilename, infilename); strcpy(addinfilename, infilename);
@ -32989,13 +33101,17 @@ void tetgenmesh::qualitystatistics()
shortest, longest); shortest, longest);
printf(" Smallest asp.ratio: %13.5g | Largest asp.ratio: %13.5g\n", printf(" Smallest asp.ratio: %13.5g | Largest asp.ratio: %13.5g\n",
smallestratio, biggestratio); 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) { if (strlen(sbuf) > 8) {
sbuf[8] = '\0'; sbuf[8] = '\0';
} }
printf(" Smallest facangle: %14.5g | Largest facangle: %s\n", printf(" Smallest facangle: %14.5g | Largest facangle: %s\n",
smallestfaangle, sbuf); 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) { if (strlen(sbuf) > 8) {
sbuf[8] = '\0'; 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') { if (ofilename != (char *) NULL && ofilename[0] != '\0') {
//strcpy(vtkfilename, ofilename); //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') { } else if (b->outfilename[0] != '\0') {
strcpy(vtkfilename, b->outfilename); strcpy(vtkfilename, b->outfilename);
strcat(vtkfilename, ".vtk"); strcat(vtkfilename, ".vtk");
@ -35863,6 +36156,7 @@ void tetgenmesh::outmesh2vtk(char* ofilename, int mesh_idx)
tetrahedrons->traversalinit(); tetrahedrons->traversalinit();
tptr = tetrahedrontraverse(); tptr = tetrahedrontraverse();
//elementnumber = firstindex; // in->firstnumber; //elementnumber = firstindex; // in->firstnumber;
int first_id = 1;
while (tptr != (tetrahedron *) NULL) { while (tptr != (tetrahedron *) NULL) {
if (!b->reversetetori) { if (!b->reversetetori) {
p1 = (point) tptr[4]; p1 = (point) tptr[4];
@ -35873,10 +36167,12 @@ void tetgenmesh::outmesh2vtk(char* ofilename, int mesh_idx)
} }
p3 = (point) tptr[6]; p3 = (point) tptr[6];
p4 = (point) tptr[7]; p4 = (point) tptr[7];
n1 = pointmark(p1) - in->firstnumber; // modified by Yi Zhang
n2 = pointmark(p2) - in->firstnumber; // VTK's node index allways starts with zero
n3 = pointmark(p3) - in->firstnumber; n1 = pointmark(p1) - first_id; //in->firstnumber;
n4 = pointmark(p4) - 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); fprintf(outfile, "%d %4d %4d %4d %4d\n", nnodes, n1, n2, n3, n4);
tptr = tetrahedrontraverse(); tptr = tetrahedrontraverse();
} }
@ -35929,7 +36225,9 @@ void tetgenmesh::out_surfmesh_vtk(char* ofilename, int mesh_idx)
if (ofilename != (char *) NULL && ofilename[0] != '\0') { if (ofilename != (char *) NULL && ofilename[0] != '\0') {
//strcpy(vtkfilename, ofilename); //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') { } else if (b->outfilename[0] != '\0') {
strcpy(vtkfilename, b->outfilename); strcpy(vtkfilename, b->outfilename);
strcat(vtkfilename, ".surf.vtk"); strcat(vtkfilename, ".surf.vtk");
@ -35972,6 +36270,7 @@ void tetgenmesh::out_surfmesh_vtk(char* ofilename, int mesh_idx)
subfaces->traversalinit(); subfaces->traversalinit();
faceloop.sh = shellfacetraverse(subfaces); faceloop.sh = shellfacetraverse(subfaces);
//facenumber = firstindex; // in->firstnumber; //facenumber = firstindex; // in->firstnumber;
int first_id = 1;
while (faceloop.sh != (shellface *) NULL) { while (faceloop.sh != (shellface *) NULL) {
stpivot(faceloop, abuttingtet); stpivot(faceloop, abuttingtet);
// If there is a tetrahedron containing this subface, orient it so // 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); tapex = sapex(faceloop);
} }
n1 = pointmark(torg) - in->firstnumber; // modified by Yi Zhang
n2 = pointmark(tdest) - in->firstnumber; // VTK's node index allways starts with zero
n3 = pointmark(tapex) - in->firstnumber; 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); fprintf(outfile, "%d %4d %4d %4d\n", nnodes, n1, n2, n3);
//facenumber++; //facenumber++;
@ -36452,6 +36753,10 @@ void tetrahedralize(tetgenbehavior *b, tetgenio *in, tetgenio *out,
m.outmesh2medit(b->outfilename); m.outmesh2medit(b->outfilename);
} }
// modified by Yi Zhang
if (!out && b->gmshview) {
m.outmesh2gmsh(b->outfilename);
}
if (!out && b->vtkview) { if (!out && b->vtkview) {
m.outmesh2vtk(NULL, 0); // b->outfilename 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 #ifndef tetgenH
#define tetgenH #define tetgenH
@ -359,6 +371,7 @@ public:
void save_neighbors(char*); void save_neighbors(char*);
void save_poly(const char*); void save_poly(const char*);
void save_faces2smesh(char*); void save_faces2smesh(char*);
void save_mesh2gmsh(const char*);
// Read line and parse string functions. // Read line and parse string functions.
char *readline(char* string, FILE* infile, int *linenumber); char *readline(char* string, FILE* infile, int *linenumber);
@ -645,6 +658,7 @@ public:
int neighout; // '-n', 0. int neighout; // '-n', 0.
int voroout; // '-v', 0. int voroout; // '-v', 0.
int meditview; // '-g', 0. int meditview; // '-g', 0.
int gmshview; // '-G', 0. // Modified by Yi Zhang
int vtkview; // '-k', 0. int vtkview; // '-k', 0.
int vtksurfview; // '-k', 0. int vtksurfview; // '-k', 0.
int nobound; // '-B', 0. int nobound; // '-B', 0.
@ -765,6 +779,7 @@ public:
neighout = 0; neighout = 0;
voroout = 0; voroout = 0;
meditview = 0; meditview = 0;
gmshview = 0; // Modified by Yi Zhang
vtkview = 0; vtkview = 0;
vtksurfview = 0; vtksurfview = 0;
nobound = 0; nobound = 0;
@ -2230,6 +2245,7 @@ public:
void outvoronoi(tetgenio*); void outvoronoi(tetgenio*);
void outsmesh(char*); void outsmesh(char*);
void outmesh2medit(char*); void outmesh2medit(char*);
void outmesh2gmsh(char*);
void outmesh2vtk(char*, int); void outmesh2vtk(char*, int);
void out_surfmesh_vtk(char*, int); void out_surfmesh_vtk(char*, int);
void out_intersected_facets(); void out_intersected_facets();

View File

@ -179,6 +179,14 @@ int main(int argc, char *argv[])
in.facetmarkerlist[4] = 0; in.facetmarkerlist[4] = 0;
in.facetmarkerlist[5] = 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'. // Output the PLC to files 'barin.node' and 'barin.poly'.
in.save_nodes("barin"); in.save_nodes("barin");
in.save_poly("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 // do quality mesh generation (q) with a specified quality bound
// (1.414), and apply a maximum volume constraint (a0.1). // (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'. // Output mesh to files 'barout.node', 'barout.ele' and 'barout.face'.
out.save_nodes("barout"); out.save_nodes("barout");
out.save_elements("barout"); out.save_elements("barout");
out.save_faces("barout"); out.save_faces("barout");
out.save_mesh2gmsh("barout");
return 0; return 0;
} }

View File

@ -2503,7 +2503,9 @@ void tetgenio::save_nodes(const char *filebasename)
char outmtrfilename[FILENAMESIZE]; char outmtrfilename[FILENAMESIZE];
int i, j; 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); printf("Saving nodes to %s\n", outnodefilename);
fout = fopen(outnodefilename, "w"); fout = fopen(outnodefilename, "w");
fprintf(fout, "%d %d %d %d\n", numberofpoints, mesh_dim, 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 the point metrics exist, output them to a .mtr file.
if ((numberofpointmtrs > 0) && (pointmtrlist != (REAL *) NULL)) { 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); printf("Saving metrics to %s\n", outmtrfilename);
fout = fopen(outmtrfilename, "w"); fout = fopen(outmtrfilename, "w");
fprintf(fout, "%d %d\n", numberofpoints, numberofpointmtrs); fprintf(fout, "%d %d\n", numberofpoints, numberofpointmtrs);
@ -2555,7 +2559,9 @@ void tetgenio::save_elements(const char* filebasename)
char outelefilename[FILENAMESIZE]; char outelefilename[FILENAMESIZE];
int i, j; 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); printf("Saving elements to %s\n", outelefilename);
fout = fopen(outelefilename, "w"); fout = fopen(outelefilename, "w");
if (mesh_dim == 3) { if (mesh_dim == 3) {
@ -2602,7 +2608,9 @@ void tetgenio::save_faces(const char* filebasename)
char outfacefilename[FILENAMESIZE]; char outfacefilename[FILENAMESIZE];
int i; 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); printf("Saving faces to %s\n", outfacefilename);
fout = fopen(outfacefilename, "w"); fout = fopen(outfacefilename, "w");
fprintf(fout, "%d %d\n", numberoftrifaces, fprintf(fout, "%d %d\n", numberoftrifaces,
@ -2631,7 +2639,9 @@ void tetgenio::save_edges(char* filebasename)
char outedgefilename[FILENAMESIZE]; char outedgefilename[FILENAMESIZE];
int i; 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); printf("Saving edges to %s\n", outedgefilename);
fout = fopen(outedgefilename, "w"); fout = fopen(outedgefilename, "w");
fprintf(fout, "%d %d\n", numberofedges, edgemarkerlist != NULL ? 1 : 0); fprintf(fout, "%d %d\n", numberofedges, edgemarkerlist != NULL ? 1 : 0);
@ -2659,7 +2669,9 @@ void tetgenio::save_neighbors(char* filebasename)
char outneighborfilename[FILENAMESIZE]; char outneighborfilename[FILENAMESIZE];
int i; 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); printf("Saving neighbors to %s\n", outneighborfilename);
fout = fopen(outneighborfilename, "w"); fout = fopen(outneighborfilename, "w");
fprintf(fout, "%d %d\n", numberoftetrahedra, mesh_dim + 1); fprintf(fout, "%d %d\n", numberoftetrahedra, mesh_dim + 1);
@ -2694,7 +2706,9 @@ void tetgenio::save_poly(const char *filebasename)
char outpolyfilename[FILENAMESIZE]; char outpolyfilename[FILENAMESIZE];
int i, j, k; 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); printf("Saving poly to %s\n", outpolyfilename);
fout = fopen(outpolyfilename, "w"); fout = fopen(outpolyfilename, "w");
@ -2792,7 +2806,9 @@ void tetgenio::save_faces2smesh(char* filebasename)
char outsmeshfilename[FILENAMESIZE]; char outsmeshfilename[FILENAMESIZE];
int i, j; 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); printf("Saving faces to %s\n", outsmeshfilename);
fout = fopen(outsmeshfilename, "w"); fout = fopen(outsmeshfilename, "w");
@ -2824,6 +2840,93 @@ void tetgenio::save_faces2smesh(char* filebasename)
fclose(fout); 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. // // readline() Read a nonempty line from a file. //
@ -2964,7 +3067,7 @@ char* tetgenio::findnextnumber(char *string)
void tetgenbehavior::syntax() 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(" -p Tetrahedralizes a piecewise linear complex (PLC).\n");
printf(" -Y Preserves the input surface mesh (does not modify it).\n"); printf(" -Y Preserves the input surface mesh (does not modify it).\n");
printf(" -r Reconstructs a previously generated mesh.\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(" -e Outputs all edges to .edge file.\n");
printf(" -n Outputs tetrahedra neighbors to .neigh 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 .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(" -k Outputs mesh to .vtk file for viewing by Paraview.\n");
printf(" -J No jettison of unused vertices from output .node file.\n"); printf(" -J No jettison of unused vertices from output .node file.\n");
printf(" -B Suppresses output of boundary information.\n"); printf(" -B Suppresses output of boundary information.\n");
@ -3011,10 +3115,10 @@ void tetgenbehavior::usage()
printf("TetGen\n"); printf("TetGen\n");
printf("A Quality Tetrahedral Mesh Generator and 3D Delaunay "); printf("A Quality Tetrahedral Mesh Generator and 3D Delaunay ");
printf("Triangulator\n"); printf("Triangulator\n");
printf("Version 1.6\n"); printf("Version 1.6.0_1\n");
printf("August, 2020\n"); printf("December, 2023\n");
printf("\n"); printf("\n");
printf("Copyright (C) 2002 - 2020\n"); printf("Copyright (C) 2023\n");
printf("\n"); printf("\n");
printf("What Can TetGen Do?\n"); printf("What Can TetGen Do?\n");
printf("\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("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("object.1.node, object.1.ele,\n object.1.face, and object.1.edge\n");
printf("\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); terminatetetgen(NULL, 0);
} }
@ -3423,6 +3531,8 @@ bool tetgenbehavior::parse_commandline(int argc, char **argv)
neighout++; neighout++;
} else if (argv[i][j] == 'g') { } else if (argv[i][j] == 'g') {
meditview = 1; meditview = 1;
} else if (argv[i][j] == 'G') { // modified by Yi Zhang
gmshview = 1; // modified by Yi Zhang
} else if (argv[i][j] == 'k') { } else if (argv[i][j] == 'k') {
if (argv[i][j + 1] == '2') { // -k2 if (argv[i][j + 1] == '2') { // -k2
vtksurfview = 1; vtksurfview = 1;
@ -3782,7 +3892,9 @@ bool tetgenbehavior::parse_commandline(int argc, char **argv)
workstring[increment] = '%'; workstring[increment] = '%';
workstring[increment + 1] = 'd'; workstring[increment + 1] = 'd';
workstring[increment + 2] = '\0'; 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". // Additional input file name has the end ".a".
strcpy(addinfilename, infilename); strcpy(addinfilename, infilename);
@ -32989,13 +33101,17 @@ void tetgenmesh::qualitystatistics()
shortest, longest); shortest, longest);
printf(" Smallest asp.ratio: %13.5g | Largest asp.ratio: %13.5g\n", printf(" Smallest asp.ratio: %13.5g | Largest asp.ratio: %13.5g\n",
smallestratio, biggestratio); 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) { if (strlen(sbuf) > 8) {
sbuf[8] = '\0'; sbuf[8] = '\0';
} }
printf(" Smallest facangle: %14.5g | Largest facangle: %s\n", printf(" Smallest facangle: %14.5g | Largest facangle: %s\n",
smallestfaangle, sbuf); 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) { if (strlen(sbuf) > 8) {
sbuf[8] = '\0'; 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') { if (ofilename != (char *) NULL && ofilename[0] != '\0') {
//strcpy(vtkfilename, ofilename); //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') { } else if (b->outfilename[0] != '\0') {
strcpy(vtkfilename, b->outfilename); strcpy(vtkfilename, b->outfilename);
strcat(vtkfilename, ".vtk"); strcat(vtkfilename, ".vtk");
@ -35863,6 +36156,7 @@ void tetgenmesh::outmesh2vtk(char* ofilename, int mesh_idx)
tetrahedrons->traversalinit(); tetrahedrons->traversalinit();
tptr = tetrahedrontraverse(); tptr = tetrahedrontraverse();
//elementnumber = firstindex; // in->firstnumber; //elementnumber = firstindex; // in->firstnumber;
int first_id = 1;
while (tptr != (tetrahedron *) NULL) { while (tptr != (tetrahedron *) NULL) {
if (!b->reversetetori) { if (!b->reversetetori) {
p1 = (point) tptr[4]; p1 = (point) tptr[4];
@ -35873,10 +36167,12 @@ void tetgenmesh::outmesh2vtk(char* ofilename, int mesh_idx)
} }
p3 = (point) tptr[6]; p3 = (point) tptr[6];
p4 = (point) tptr[7]; p4 = (point) tptr[7];
n1 = pointmark(p1) - in->firstnumber; // modified by Yi Zhang
n2 = pointmark(p2) - in->firstnumber; // VTK's node index allways starts with zero
n3 = pointmark(p3) - in->firstnumber; n1 = pointmark(p1) - first_id; //in->firstnumber;
n4 = pointmark(p4) - 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); fprintf(outfile, "%d %4d %4d %4d %4d\n", nnodes, n1, n2, n3, n4);
tptr = tetrahedrontraverse(); tptr = tetrahedrontraverse();
} }
@ -35929,7 +36225,9 @@ void tetgenmesh::out_surfmesh_vtk(char* ofilename, int mesh_idx)
if (ofilename != (char *) NULL && ofilename[0] != '\0') { if (ofilename != (char *) NULL && ofilename[0] != '\0') {
//strcpy(vtkfilename, ofilename); //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') { } else if (b->outfilename[0] != '\0') {
strcpy(vtkfilename, b->outfilename); strcpy(vtkfilename, b->outfilename);
strcat(vtkfilename, ".surf.vtk"); strcat(vtkfilename, ".surf.vtk");
@ -35972,6 +36270,7 @@ void tetgenmesh::out_surfmesh_vtk(char* ofilename, int mesh_idx)
subfaces->traversalinit(); subfaces->traversalinit();
faceloop.sh = shellfacetraverse(subfaces); faceloop.sh = shellfacetraverse(subfaces);
//facenumber = firstindex; // in->firstnumber; //facenumber = firstindex; // in->firstnumber;
int first_id = 1;
while (faceloop.sh != (shellface *) NULL) { while (faceloop.sh != (shellface *) NULL) {
stpivot(faceloop, abuttingtet); stpivot(faceloop, abuttingtet);
// If there is a tetrahedron containing this subface, orient it so // 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); tapex = sapex(faceloop);
} }
n1 = pointmark(torg) - in->firstnumber; // modified by Yi Zhang
n2 = pointmark(tdest) - in->firstnumber; // VTK's node index allways starts with zero
n3 = pointmark(tapex) - in->firstnumber; 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); fprintf(outfile, "%d %4d %4d %4d\n", nnodes, n1, n2, n3);
//facenumber++; //facenumber++;
@ -36452,6 +36753,10 @@ void tetrahedralize(tetgenbehavior *b, tetgenio *in, tetgenio *out,
m.outmesh2medit(b->outfilename); m.outmesh2medit(b->outfilename);
} }
// modified by Yi Zhang
if (!out && b->gmshview) {
m.outmesh2gmsh(b->outfilename);
}
if (!out && b->vtkview) { if (!out && b->vtkview) {
m.outmesh2vtk(NULL, 0); // b->outfilename 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 #ifndef tetgenH
#define tetgenH #define tetgenH
@ -52,7 +64,7 @@
// To compile TetGen as a library instead of an executable program, define // To compile TetGen as a library instead of an executable program, define
// the TETLIBRARY symbol. // the TETLIBRARY symbol.
// #define TETLIBRARY //#define TETLIBRARY
// TetGen default uses the double-precision (64 bit) for a real number. // TetGen default uses the double-precision (64 bit) for a real number.
@ -359,6 +371,7 @@ public:
void save_neighbors(char*); void save_neighbors(char*);
void save_poly(const char*); void save_poly(const char*);
void save_faces2smesh(char*); void save_faces2smesh(char*);
void save_mesh2gmsh(const char*);
// Read line and parse string functions. // Read line and parse string functions.
char *readline(char* string, FILE* infile, int *linenumber); char *readline(char* string, FILE* infile, int *linenumber);
@ -645,6 +658,7 @@ public:
int neighout; // '-n', 0. int neighout; // '-n', 0.
int voroout; // '-v', 0. int voroout; // '-v', 0.
int meditview; // '-g', 0. int meditview; // '-g', 0.
int gmshview; // '-G', 0. // Modified by Yi Zhang
int vtkview; // '-k', 0. int vtkview; // '-k', 0.
int vtksurfview; // '-k', 0. int vtksurfview; // '-k', 0.
int nobound; // '-B', 0. int nobound; // '-B', 0.
@ -765,6 +779,7 @@ public:
neighout = 0; neighout = 0;
voroout = 0; voroout = 0;
meditview = 0; meditview = 0;
gmshview = 0; // Modified by Yi Zhang
vtkview = 0; vtkview = 0;
vtksurfview = 0; vtksurfview = 0;
nobound = 0; nobound = 0;
@ -2230,6 +2245,7 @@ public:
void outvoronoi(tetgenio*); void outvoronoi(tetgenio*);
void outsmesh(char*); void outsmesh(char*);
void outmesh2medit(char*); void outmesh2medit(char*);
void outmesh2gmsh(char*);
void outmesh2vtk(char*, int); void outmesh2vtk(char*, int);
void out_surfmesh_vtk(char*, int); void out_surfmesh_vtk(char*, int);
void out_intersected_facets(); 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