Skip to content
Snippets Groups Projects
Commit afd418a8 authored by Christophe Geuzaine's avatar Christophe Geuzaine
Browse files

No commit message

No commit message
parent f4e613f8
No related branches found
No related tags found
No related merge requests found
Showing
with 0 additions and 28831 deletions
# Gmsh - Copyright (C) 1997-2012 C. Geuzaine, J.-F. Remacle
#
# See the LICENSE.txt file for license information. Please report all
# bugs and problems to <gmsh@geuz.org>.
set(SRC
behavior.cxx
constrain.cxx
delaunay.cxx
flip.cxx
geom.cxx
io.cxx
main.cxx
memorypool.cxx
meshio.cxx
meshstat.cxx
predicates.cxx
refine.cxx
surface.cxx
)
file(GLOB_RECURSE HDR RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} *.h)
append_gmsh_src(contrib/TetgenNew "${SRC};${HDR}")
TetGen License
--------------
The software (TetGen) is licensed under the terms of the MIT license
with the following exceptions:
Distribution of modified versions of this code is permissible UNDER
THE CONDITION THAT THIS CODE AND ANY MODIFICATIONS MADE TO IT IN THE
SAME SOURCE FILES tetgen.h AND tetgen.cxx REMAIN UNDER COPYRIGHT OF
THE ORIGINAL AUTHOR, BOTH SOURCE AND OBJECT CODE ARE MADE FREELY
AVAILABLE WITHOUT CHARGE, AND CLEAR NOTICE IS GIVEN OF THE
MODIFICATIONS.
Distribution of this code for any commercial purpose is permissible
ONLY BY DIRECT ARRANGEMENT WITH THE COPYRIGHT OWNER.
The full license text is reproduced below.
This means that TetGen is no free software, but for private, research,
and educational purposes it can be used at absolutely no cost and
without further arrangements.
For details, see http://tetgen.berlios.de
==============================================================================
TetGen
A Quality Tetrahedral Mesh Generator and 3D Delaunay Triangulator
Version 1.4 (Released on January 14, 2006).
Copyright 2002, 2004, 2005, 2006
Hang Si
Rathausstr. 9, 10178 Berlin, Germany
si@wias-berlin.de
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
Distribution of modified versions of this code is permissible UNDER
THE CONDITION THAT THIS CODE AND ANY MODIFICATIONS MADE TO IT IN THE
SAME SOURCE FILES tetgen.h AND tetgen.cxx REMAIN UNDER COPYRIGHT OF
THE ORIGINAL AUTHOR, BOTH SOURCE AND OBJECT CODE ARE MADE FREELY
AVAILABLE WITHOUT CHARGE, AND CLEAR NOTICE IS GIVEN OF THE
MODIFICATIONS.
Distribution of this code for any commercial purpose is permissible
ONLY BY DIRECT ARRANGEMENT WITH THE COPYRIGHT OWNER.
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
==============================================================================
\ No newline at end of file
This is an EXPERIMENTAL version of TetGen provided by Hang Si for Gmsh
Please see the documentation of TetGen (available at the following link) for
compiling and using TetGen.
http://tetgen.berlios.de/index.html
TetGen may be freely copied, modified, and redistributed under the
copyright notices stated in the file LICENSE.
Please send bugs/comments to Hang Si <si@wias-berlin.de>
Thank you and enjoy!
Hang Si
#ifndef behaviorCXX
#define behaviorCXX
#include "tetgen.h"
static REAL PI = 3.14159265358979323846264338327950288419716939937510582;
///////////////////////////////////////////////////////////////////////////////
// //
// tetgenbehavior() Initialize veriables of 'tetgenbehavior'. //
// //
///////////////////////////////////////////////////////////////////////////////
tetgenbehavior::tetgenbehavior()
{
// Initialize command line switches.
plc = 0;
quality = 0;
refine = 0;
coarse = 0;
metric = 0;
minratio = 2.0;
goodratio = 0.0;
minangle = 20.0;
goodangle = 0.0;
maxdihedral = 165.0;
mindihedral = 5.0;
varvolume = 0;
fixedvolume = 0;
maxvolume = -1.0;
regionattrib = 0;
bowyerwatson = 1;
convexity = 0;
insertaddpoints = 0;
diagnose = 0;
conformdel = 0;
zeroindex = 0;
facesout = 0;
edgesout = 0;
neighout = 0;
voroout = 0;
meditview = 0;
gidview = 0;
geomview = 0;
order = 1;
nojettison = 0;
nobound = 0;
nonodewritten = 0;
noelewritten = 0;
nofacewritten = 0;
noiterationnum = 0;
nobisect = 0;
steinerleft = -1l;
nomerge = 0;
docheck = 0;
quiet = 0;
verbose = 0;
useshelles = 0;
epsilon = 1.0e-8;
object = NONE;
// Initialize strings
commandline[0] = '\0';
infilename[0] = '\0';
outfilename[0] = '\0';
addinfilename[0] = '\0';
bgmeshfilename[0] = '\0';
}
///////////////////////////////////////////////////////////////////////////////
// //
// versioninfo() Print the version information of TetGen. //
// //
///////////////////////////////////////////////////////////////////////////////
void tetgenbehavior::versioninfo()
{
printf("Develop Version (Started on August 9, 2008).\n");
printf("\n");
printf("Copyright (C) 2002 - 2008\n");
printf("Hang Si\n");
printf("Mohrenstr. 39, 10117 Berlin, Germany\n");
printf("si@wias-berlin.de\n");
}
///////////////////////////////////////////////////////////////////////////////
// //
// syntax() Print list of command line switches and exit the program. //
// //
///////////////////////////////////////////////////////////////////////////////
void tetgenbehavior::syntax()
{
printf(" tetgen [-prq_Ra_AiMYS_T_dzo_fenvgGOJBNEFICQVh] input_file\n");
printf(" -p Tetrahedralizes a piecewise linear complex (PLC).\n");
printf(" -r Reconstructs a previously generated mesh.\n");
printf(" -q Quality mesh generation (adding new mesh points to ");
printf("improve mesh quality).\n");
printf(" -R Mesh coarsening (deleting redundant mesh points).\n");
printf(" -a Applies a maximum tetrahedron volume constraint.\n");
printf(" -A Assigns attributes to identify tetrahedra in different ");
printf("regions.\n");
printf(" -i Inserts a list of additional points into mesh.\n");
printf(" -M Does not merge coplanar facets.\n");
printf(" -Y Suppresses boundary facets/segments splitting.\n");
printf(" -S Specifies maximum number of added points.\n");
printf(" -T Sets a tolerance for coplanar test (default 1e-8).\n");
printf(" -d Detects self-intersections of facets of the PLC.\n");
printf(" -z Numbers all output items starting from zero.\n");
printf(" -o2 Generates second-order subparametric elements.\n");
printf(" -f Outputs all faces to .face file.");
printf("file.\n");
printf(" -e Outputs all edges to .edge file.\n");
printf(" -n Outputs tetrahedra neighbors to .neigh file.\n");
printf(" -v Outputs Voronoi diagram to files.\n");
printf(" -g Outputs mesh to .mesh file for viewing by Medit.\n");
printf(" -G Outputs mesh to .msh file for viewing by Gid.\n");
printf(" -O Outputs mesh to .off file for viewing by Geomview.\n");
printf(" -J No jettison of unused vertices from output .node file.\n");
printf(" -B Suppresses output of boundary information.\n");
printf(" -N Suppresses output of .node file.\n");
printf(" -E Suppresses output of .ele file.\n");
printf(" -F Suppresses output of .face file.\n");
printf(" -I Suppresses mesh iteration numbers.\n");
printf(" -C Checks the consistency of the final mesh.\n");
printf(" -Q Quiet: No terminal output except errors.\n");
printf(" -V Verbose: Detailed information, more terminal output.\n");
printf(" -h Help: A brief instruction for using TetGen.\n");
}
///////////////////////////////////////////////////////////////////////////////
// //
// usage() Print a brief instruction for using TetGen. //
// //
///////////////////////////////////////////////////////////////////////////////
void tetgenbehavior::usage()
{
printf("TetGen\n");
printf("A Quality Tetrahedral Mesh Generator and 3D Delaunay ");
printf("Triangulator\n");
versioninfo();
printf("\n");
printf("What Can TetGen Do?\n");
printf("\n");
printf(" TetGen generates exact Delaunay tetrahedralizations, exact\n");
printf(" constrained Delaunay tetrahedralizations, and quality ");
printf("tetrahedral\n meshes. The latter are nicely graded and whose ");
printf("tetrahedra have\n radius-edge ratio bounded, thus are suitable ");
printf("for finite element and\n finite volume analysis.\n");
printf("\n");
printf("Command Line Syntax:\n");
printf("\n");
printf(" Below is the command line syntax of TetGen with a list of ");
printf("short\n");
printf(" descriptions. Underscores indicate that numbers may optionally\n");
printf(" follow certain switches. Do not leave any space between a ");
printf("switch\n");
printf(" and its numeric parameter. \'input_file\' contains input data\n");
printf(" depending on the switches you supplied which may be a ");
printf(" piecewise\n");
printf(" linear complex or a list of nodes. File formats and detailed\n");
printf(" description of command line switches are found in user's ");
printf("manual.\n");
printf("\n");
syntax();
printf("\n");
printf("Examples of How to Use TetGen:\n");
printf("\n");
printf(" \'tetgen object\' reads vertices from object.node, and writes ");
printf("their\n Delaunay tetrahedralization to object.1.node and ");
printf("object.1.ele.\n");
printf("\n");
printf(" \'tetgen -p object\' reads a PLC from object.poly or object.");
printf("smesh (and\n possibly object.node) and writes its constrained ");
printf("Delaunay\n tetrahedralization to object.1.node, object.1.ele and ");
printf("object.1.face.\n");
printf("\n");
printf(" \'tetgen -pq1.414a.1 object\' reads a PLC from object.poly or\n");
printf(" object.smesh (and possibly object.node), generates a mesh ");
printf("whose\n tetrahedra have radius-edge ratio smaller than 1.414 and ");
printf("have volume\n of 0.1 or less, and writes the mesh to ");
printf("object.1.node, object.1.ele\n and object.1.face.\n");
printf("\n");
printf("Please send bugs/comments to Hang Si <si@wias-berlin.de>\n");
}
///////////////////////////////////////////////////////////////////////////////
// //
// parse_commandline() Read the command line, identify switches, and set //
// up options and file names. //
// //
// 'argc' and 'argv' are the same parameters passed to the function main() //
// of a C/C++ program. They together represent the command line user invoked //
// from an environment in which TetGen is running. //
// //
// When TetGen is invoked from an environment. 'argc' is nonzero, switches //
// and input filename should be supplied as zero-terminated strings in //
// argv[0] through argv[argc - 1] and argv[0] shall be the name used to //
// invoke TetGen, i.e. "tetgen". Switches are previously started with a //
// dash '-' to identify them from the input filename. //
// //
// When TetGen is called from within another program. 'argc' is set to zero. //
// switches are given in one zero-terminated string (no previous dash is //
// required.), and 'argv' is a pointer points to this string. No input //
// filename is required (usually the input data has been directly created by //
// user in the 'tetgenio' structure). A default filename 'tetgen-tmpfile' //
// will be created for debugging output purpose. //
// //
///////////////////////////////////////////////////////////////////////////////
bool tetgenbehavior::parse_commandline(int argc, char **argv)
{
int startindex;
int increment;
int meshnumber;
int scount;
int i, j, k;
char workstring[1024];
// First determine the input style of the switches.
if (argc == 0) {
startindex = 0; // Switches are given without a dash.
argc = 1; // For running the following for-loop once.
commandline[0] = '\0';
} else {
startindex = 1;
strcpy(commandline, argv[0]);
strcat(commandline, " ");
}
// Rcount used to count the number of '-R' be used.
scount = 0;
for (i = startindex; i < argc; i++) {
// Remember the command line switches.
strcat(commandline, argv[i]);
strcat(commandline, " ");
if (startindex == 1) {
// Is this string a filename?
if (argv[i][0] != '-') {
strncpy(infilename, argv[i], 1024 - 1);
infilename[1024 - 1] = '\0';
// Go to the next string directly.
continue;
}
}
// Parse the individual switch from the string.
for (j = startindex; argv[i][j] != '\0'; j++) {
if (argv[i][j] == 'p') {
plc = 1;
} else if (argv[i][j] == 'r') {
refine = 1;
} else if (argv[i][j] == 'R') {
coarse = 1;
} else if (argv[i][j] == 'q') {
quality++;
if (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) ||
(argv[i][j + 1] == '.')) {
k = 0;
while (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) ||
(argv[i][j + 1] == '.')) {
j++;
workstring[k] = argv[i][j];
k++;
}
workstring[k] = '\0';
if (quality == 1) {
minratio = (REAL) strtod(workstring, (char **) NULL);
} else if (quality == 2) {
mindihedral = (REAL) strtod(workstring, (char **) NULL);
} else if (quality == 3) {
maxdihedral = (REAL) strtod(workstring, (char **) NULL);
}
}
} else if (argv[i][j] == 'm') {
metric++;
} else if (argv[i][j] == 'a') {
if (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) ||
(argv[i][j + 1] == '.')) {
fixedvolume = 1;
k = 0;
while (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) ||
(argv[i][j + 1] == '.') || (argv[i][j + 1] == 'e') ||
(argv[i][j + 1] == '-') || (argv[i][j + 1] == '+')) {
j++;
workstring[k] = argv[i][j];
k++;
}
workstring[k] = '\0';
maxvolume = (REAL) strtod(workstring, (char **) NULL);
} else {
varvolume = 1;
}
} else if (argv[i][j] == 'A') {
regionattrib++;
} else if (argv[i][j] == 'b') {
bowyerwatson = 0;
} else if (argv[i][j] == 'c') {
convexity++;
} else if (argv[i][j] == 'i') {
insertaddpoints = 1;
} else if (argv[i][j] == 'd') {
diagnose = 1;
} else if (argv[i][j] == 'z') {
zeroindex = 1;
} else if (argv[i][j] == 'f') {
facesout = 1;
} else if (argv[i][j] == 'e') {
edgesout++;
} else if (argv[i][j] == 'n') {
neighout++;
} else if (argv[i][j] == 'v') {
voroout = 1;
} else if (argv[i][j] == 'g') {
meditview = 1;
} else if (argv[i][j] == 'G') {
gidview = 1;
} else if (argv[i][j] == 'O') {
geomview = 1;
} else if (argv[i][j] == 'M') {
nomerge = 1;
} else if (argv[i][j] == 'Y') {
nobisect++;
} else if (argv[i][j] == 'J') {
nojettison = 1;
} else if (argv[i][j] == 'B') {
nobound = 1;
} else if (argv[i][j] == 'N') {
nonodewritten = 1;
} else if (argv[i][j] == 'E') {
noelewritten = 1;
if (argv[i][j + 1] == '2') {
j++;
noelewritten = 2;
}
} else if (argv[i][j] == 'F') {
nofacewritten = 1;
} else if (argv[i][j] == 'I') {
noiterationnum = 1;
} else if (argv[i][j] == 'o') {
if ((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) {
k = 0;
while ((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) {
j++;
workstring[k] = argv[i][j];
k++;
}
workstring[k] = '\0';
order = (int) strtol(workstring, (char **) NULL, 0);
}
} else if (argv[i][j] == 'S') {
if (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) ||
(argv[i][j + 1] == '.')) {
k = 0;
while (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) ||
(argv[i][j + 1] == '.') || (argv[i][j + 1] == 'e') ||
(argv[i][j + 1] == '-') || (argv[i][j + 1] == '+')) {
j++;
workstring[k] = argv[i][j];
k++;
}
workstring[k] = '\0';
steinerleft = (int) strtol(workstring, (char **) NULL, 0);
}
} else if (argv[i][j] == 'D') {
conformdel++;
} else if (argv[i][j] == 'T') {
if (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) ||
(argv[i][j + 1] == '.')) {
k = 0;
while (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) ||
(argv[i][j + 1] == '.') || (argv[i][j + 1] == 'e') ||
(argv[i][j + 1] == '-') || (argv[i][j + 1] == '+')) {
j++;
workstring[k] = argv[i][j];
k++;
}
workstring[k] = '\0';
epsilon = (REAL) strtod(workstring, (char **) NULL);
}
} else if (argv[i][j] == 'C') {
docheck++;
} else if (argv[i][j] == 'Q') {
quiet = 1;
} else if (argv[i][j] == 'V') {
verbose++;
// } else if (argv[i][j] == 'v') {
// versioninfo();
// terminatetetgen(0);
} else if ((argv[i][j] == 'h') || (argv[i][j] == 'H') ||
(argv[i][j] == '?')) {
usage();
terminatetetgen(0);
} else {
printf("Warning: Unknown switch -%c.\n", argv[i][j]);
}
}
}
if (startindex == 0) {
// Set a temporary filename for debugging output.
strcpy(infilename, "tetgen-tmpfile");
} else {
if (infilename[0] == '\0') {
// No input file name. Print the syntax and exit.
syntax();
terminatetetgen(0);
}
// Recognize the object from file extension if it is available.
if (!strcmp(&infilename[strlen(infilename) - 5], ".node")) {
infilename[strlen(infilename) - 5] = '\0';
object = NODES;
} else if (!strcmp(&infilename[strlen(infilename) - 5], ".poly")) {
infilename[strlen(infilename) - 5] = '\0';
object = POLY;
plc = 1;
} else if (!strcmp(&infilename[strlen(infilename) - 6], ".smesh")) {
infilename[strlen(infilename) - 6] = '\0';
object = POLY;
plc = 1;
} else if (!strcmp(&infilename[strlen(infilename) - 4], ".off")) {
infilename[strlen(infilename) - 4] = '\0';
object = OFF;
plc = 1;
} else if (!strcmp(&infilename[strlen(infilename) - 4], ".ply")) {
infilename[strlen(infilename) - 4] = '\0';
object = PLY;
plc = 1;
} else if (!strcmp(&infilename[strlen(infilename) - 4], ".stl")) {
infilename[strlen(infilename) - 4] = '\0';
object = STL;
plc = 1;
} else if (!strcmp(&infilename[strlen(infilename) - 5], ".mesh")) {
infilename[strlen(infilename) - 5] = '\0';
object = MEDIT;
plc = 1;
} else if (!strcmp(&infilename[strlen(infilename) - 4], ".vtk")) {
infilename[strlen(infilename) - 4] = '\0';
object = VTK;
plc = 1;
} else if (!strcmp(&infilename[strlen(infilename) - 4], ".ele")) {
infilename[strlen(infilename) - 4] = '\0';
object = MESH;
refine = 1;
}
}
plc = plc || diagnose;
useshelles = plc || refine || coarse || quality;
goodratio = minratio;
goodratio *= goodratio;
// Detect improper combinations of switches.
if (plc && refine) {
printf("Error: Switch -r cannot use together with -p.\n");
return false;
}
if (refine && (plc || noiterationnum)) {
printf("Error: Switches %s cannot use together with -r.\n",
"-p, -d, and -I");
return false;
}
if (diagnose && (quality || insertaddpoints || (order == 2) || neighout
|| docheck)) {
printf("Error: Switches %s cannot use together with -d.\n",
"-q, -i, -o2, -n, and -C");
return false;
}
// Be careful not to allocate space for element area constraints that
// will never be assigned any value (other than the default -1.0).
if (!refine && !plc) {
varvolume = 0;
}
// Be careful not to add an extra attribute to each element unless the
// input supports it (PLC in, but not refining a preexisting mesh).
if (refine || !plc) {
regionattrib = 0;
}
// If '-a' or '-aa' is in use, enable '-q' option too.
if (fixedvolume || varvolume) {
if (quality == 0) {
quality = 1;
}
}
// Calculate the goodangle for testing bad subfaces.
goodangle = cos(minangle * PI / 180.0);
goodangle *= goodangle;
increment = 0;
strcpy(workstring, infilename);
j = 1;
while (workstring[j] != '\0') {
if ((workstring[j] == '.') && (workstring[j + 1] != '\0')) {
increment = j + 1;
}
j++;
}
meshnumber = 0;
if (increment > 0) {
j = increment;
do {
if ((workstring[j] >= '0') && (workstring[j] <= '9')) {
meshnumber = meshnumber * 10 + (int) (workstring[j] - '0');
} else {
increment = 0;
}
j++;
} while (workstring[j] != '\0');
}
if (noiterationnum) {
strcpy(outfilename, infilename);
} else if (increment == 0) {
strcpy(outfilename, infilename);
strcat(outfilename, ".1");
} else {
workstring[increment] = '%';
workstring[increment + 1] = 'd';
workstring[increment + 2] = '\0';
sprintf(outfilename, workstring, meshnumber + 1);
}
// Additional input file name has the end ".a".
strcpy(addinfilename, infilename);
strcat(addinfilename, ".a");
// Background filename has the form "*.b.ele", "*.b.node", ...
strcpy(bgmeshfilename, infilename);
strcat(bgmeshfilename, ".b");
return true;
}
#endif // ifndef behaviorCXX
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
#ifndef mainCXX
#define mainCXX
#include "tetgen.h"
///////////////////////////////////////////////////////////////////////////////
// //
// test_tri_tri() Triangle-triangle intersection tests. //
// //
///////////////////////////////////////////////////////////////////////////////
void test_tri_tri(tetgenbehavior *b, tetgenio *in)
{
tetgenmesh m;
tetgenmesh::face s1, s2;
tetgenmesh::point U[3], V[3], T1[3], T2[3];
tetgenmesh::intersection dir;
int types[2], pos[4];
int i, j;
m.b = b;
m.in = in;
exactinit();
m.initializepools();
m.transfernodes();
m.meshsurface();
m.subfacepool->traversalinit();
s1.sh = m.shellfacetraverse(m.subfacepool);
s2.sh = m.shellfacetraverse(m.subfacepool);
V[0] = (tetgenmesh::point) s1.sh[3]; // P
V[1] = (tetgenmesh::point) s1.sh[4]; // Q
V[2] = (tetgenmesh::point) s1.sh[5]; // R
U[0] = (tetgenmesh::point) s2.sh[3]; // A
U[1] = (tetgenmesh::point) s2.sh[4]; // B
U[2] = (tetgenmesh::point) s2.sh[5]; // C
// The permuations of {0, 1, 2}
int perm[6][3] = {
{0, 1, 2},
{2, 0, 1},
{1, 2, 0},
{1, 0, 2},
{2, 1, 0},
{0, 2, 1}};
b->epsilon = 0;
b->verbose = 3;
for (j = 0; j < 36; j++) {
// Get the permuation of the vertices.
T1[0] = U[perm[j/6][0]];
T1[1] = U[perm[j/6][1]];
T1[2] = U[perm[j/6][2]];
T2[0] = V[perm[j%6][0]];
T2[1] = V[perm[j%6][1]];
T2[2] = V[perm[j%6][2]];
i = m.tri_tri_test(T1[0], T1[1], T1[2], T2[0], T2[1], T2[2], NULL, 1,
types, pos);
if (i == 0) {
printf(" [%d] DISJOINT.\n", j);
continue;
}
// Report the intersection types and positions.
for (i = 0; i < 2; i++) {
dir = (enum tetgenmesh::intersection) types[i];
switch (dir) {
case tetgenmesh::DISJOINT:
printf(" [%d] DISJOINT\n", j); break;
case tetgenmesh::SHAREVERT:
printf(" [%d] SHAREVERT %d %d\n", j, pos[i*2], pos[i*2+1]); break;
case tetgenmesh::SHAREEDGE:
printf(" [%d] SHAREEDGE %d %d\n", j, pos[i*2], pos[i*2+1]); break;
case tetgenmesh::SHAREFACE:
printf(" [%d] SHAREFACE\n", j); break;
case tetgenmesh::TOUCHEDGE:
printf(" [%d] TOUCHEDGE %d %d\n", j, pos[i*2], pos[i*2+1]); break;
case tetgenmesh::TOUCHFACE:
printf(" [%d] TOUCHFACE %d %d\n", j, pos[i*2], pos[i*2+1]); break;
case tetgenmesh::ACROSSVERT:
printf(" [%d] ACROSSVERT %d %d\n", j, pos[i*2], pos[i*2+1]); break;
case tetgenmesh::ACROSSEDGE:
printf(" [%d] ACROSSEDGE %d %d\n", j, pos[i*2], pos[i*2+1]); break;
case tetgenmesh::ACROSSFACE:
printf(" [%d] ACROSSFACE %d %d\n", j, pos[i*2], pos[i*2+1]); break;
case tetgenmesh::ACROSSTET:
printf(" [%d] ACROSSTET\n", j); break;
case tetgenmesh::TRIEDGEINT:
printf(" [%d] TRIEDGEINT %d %d\n", j, pos[i*2], pos[i*2+1]); break;
case tetgenmesh::EDGETRIINT:
printf(" [%d] EDGETRIINT %d %d\n", j, pos[i*2], pos[i*2+1]); break;
}
}
}
}
///////////////////////////////////////////////////////////////////////////////
// //
// tetrahedralize() The interface for users using TetGen library to //
// generate tetrahedral meshes with all features. //
// //
// The sequence is roughly as follows. Many of these steps can be skipped, //
// depending on the command line switches. //
// //
// - Initialize constants and parse the command line. //
// - Read the vertices from a file and either //
// - tetrahedralize them (no -r), or //
// - read an old mesh from files and reconstruct it (-r). //
// - Insert the PLC segments and facets (-p). //
// - Read the holes (-p), regional attributes (-pA), and regional volume //
// constraints (-pa). Carve the holes and concavities, and spread the //
// regional attributes and volume constraints. //
// - Enforce the constraints on minimum quality bound (-q) and maximum //
// volume (-a). Also enforce the conforming Delaunay property (-q and -a). //
// - Promote the mesh's linear tetrahedra to higher order elements (-o). //
// - Write the output files and print the statistics. //
// - Check the consistency and Delaunay property of the mesh (-C). //
// //
///////////////////////////////////////////////////////////////////////////////
void tetrahedralize(tetgenbehavior *b, tetgenio *in, tetgenio *out,
tetgenio *addin, tetgenio *bgmin)
{
tetgenmesh m;
// Variables for timing the performance of TetGen (defined in time.h).
clock_t tv[17];
tv[0] = clock();
m.b = b;
m.in = in;
exactinit();
m.initializepools();
m.transfernodes();
tv[1] = clock();
if (b->refine) {
// m.reconstructmesh();
} else {
m.incrementaldelaunay();
}
tv[2] = clock();
if (!b->quiet) {
if (b->refine) {
printf("Mesh reconstruction seconds:");
} else {
printf("Delaunay seconds:");
}
printf(" %g\n", (tv[2] - tv[1]) / (REAL) CLOCKS_PER_SEC);
}
if (b->plc) { // if has -p option
m.meshsurface();
}
tv[3] = clock();
if (!b->quiet) {
if (b->plc) {
printf("Surface meshing seconds: %g\n",
(tv[3] - tv[2]) / (REAL) CLOCKS_PER_SEC);
}
}
if (b->plc) { // if has -p option
m.formskeleton();
}
tv[4] = clock();
if (!b->quiet) {
if (b->plc) {
if (b->diagnose != 1) {
printf("Boundary recovery ");
} else {
printf("Intersection ");
}
printf("seconds: %g\n", (tv[4] - tv[3]) / (REAL) CLOCKS_PER_SEC);
}
}
if (b->quality) {
m.enforcequality();
}
tv[5] = clock();
if (!b->quiet) {
if (b->quality) {
printf("Quality seconds: %g\n", (tv[5] - tv[4])/(REAL) CLOCKS_PER_SEC);
}
}
if (b->plc) {
if (b->convexity == 0) { // if has no -c option.
m.carveholes();
}
}
tv[6] = clock();
if (!b->quiet) {
if (b->plc) {
if (b->convexity == 0) { // if has no -c option.
printf("Holes and region seconds: %g\n",
(tv[6] - tv[5]) / (REAL) CLOCKS_PER_SEC);
}
}
}
printf("\n");
if (out != (tetgenio *) NULL) {
out->firstnumber = in->firstnumber;
out->mesh_dim = in->mesh_dim;
}
if (b->nonodewritten || b->noiterationnum) {
if (!b->quiet) {
printf("NOT writing a .node file.\n");
}
} else {
m.outnodes(out);
}
if (b->noelewritten == 1) {
if (!b->quiet) {
printf("NOT writing an .ele file.\n");
}
m.numberedges();
} else {
m.outelements(out);
}
if (b->nofacewritten) {
if (!b->quiet) {
printf("NOT writing an .face file.\n");
}
if (b->plc || b->refine) {
m.numbersubedges();
}
} else {
if (b->facesout) {
if (m.tetrahedronpool->items > 0l) {
m.outfaces(out); // Output all faces.
}
if (b->plc || b->refine) {
m.numberedges();
}
} else {
if (b->plc || b->refine) {
if (m.subfacepool->items > 0l) {
m.outsubfaces(out); // Output boundary faces.
}
} else {
if (m.tetrahedronpool->items > 0l) {
m.outhullfaces(out); // Output convex hull faces.
}
}
}
}
if (b->edgesout) {
if (b->edgesout > 1) {
m.outedges(out); // -ee, output all mesh edges.
} else {
m.outsubsegments(out); // -e, only output subsegments.
}
}
if (b->neighout) {
m.outneighbors(out);
}
if (b->voroout) {
// m.outvoronoi(out);
}
tv[6] = clock();
if (!b->quiet) {
printf("\nOutput seconds: %g\n",
(tv[6] - tv[5]) / (REAL) CLOCKS_PER_SEC);
printf("Total running seconds: %g\n\n",
(tv[6] - tv[0]) / (REAL) CLOCKS_PER_SEC);
}
if (b->docheck) {
if (b->plc) {
if (m.checkshells(1) > 0) assert(0);
if (m.checksegments() > 0) assert(0);
}
if (m.checkdelaunay(b->plc) > 0) assert(0);
}
if (!b->quiet) {
m.statistics();
}
}
#ifndef TETLIBRARY
///////////////////////////////////////////////////////////////////////////////
// //
// main() The entrance for running TetGen from command line. //
// //
///////////////////////////////////////////////////////////////////////////////
int main(int argc, char *argv[])
#else // with TETLIBRARY
///////////////////////////////////////////////////////////////////////////////
// //
// tetrahedralize() The entrance for calling TetGen from another program. //
// //
///////////////////////////////////////////////////////////////////////////////
void tetrahedralize(char *switches, tetgenio *in, tetgenio *out,
tetgenio *addin, tetgenio *bgmin)
#endif // not TETLIBRARY
{
tetgenbehavior b;
#ifndef TETLIBRARY
tetgenio in, addin, bgmin;
if (!b.parse_commandline(argc, argv)) {
terminatetetgen(1);
}
if (b.refine) {
if (!in.load_tetmesh(b.infilename)) {
terminatetetgen(1);
}
} else {
if (!in.load_plc(b.infilename, (int) b.object)) {
terminatetetgen(1);
}
}
if (b.insertaddpoints) {
if (!addin.load_node(b.addinfilename)) {
addin.numberofpoints = 0l;
}
}
if (b.metric) {
if (!bgmin.load_tetmesh(b.bgmeshfilename)) {
bgmin.numberoftetrahedra = 0l;
}
}
// FOR DEBUG -S1 option.
if (b.steinerleft > 0) {
test_tri_tri(&b, &in);
terminatetetgen(0);
}
if (bgmin.numberoftetrahedra > 0l) {
tetrahedralize(&b, &in, NULL, &addin, &bgmin);
} else {
tetrahedralize(&b, &in, NULL, &addin, NULL);
}
return 0;
#else // with TETLIBRARY
if (!b.parse_commandline(switches)) {
terminatetetgen(1);
}
tetrahedralize(&b, in, out, addin, bgmin);
#endif // not TETLIBRARY
}
#endif // #ifndef mainCXX
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
#ifndef refineCXX
#define refineCXX
#include "tetgen.h"
///////////////////////////////////////////////////////////////////////////////
// //
// checkedge4encroach() Check a subsegment to see if it is encroached. //
// //
// If 'testpt' != NULL, only test if the segment is encroached by this point.//
// Otherwise, test all apexes of faces containing this segment. //
// //
// If 'enqflag' > 0, add the segment into list (badsegpool) if it is encroa- //
// ched. //
// //
///////////////////////////////////////////////////////////////////////////////
bool tetgenmesh::checkedge4encroach(face& seg, point testpt, int enqflag)
{
badface *encseg;
triface neightet, spintet;
point pa, pb, pc, encpt;
REAL midpt[3], r, d, diff;
int encroached;
int i;
seg.shver = 0;
pa = sorg(seg);
pb = sdest(seg);
for (i = 0; i < 3; i++) {
midpt[i] = 0.5 * (pa[i] + pb[i]);
}
r = DIST(midpt, pa);
encroached = 0;
encpt = NULL;
if (testpt == NULL) {
// Check all apexes of faces containing [pa, pb].
stpivot(seg, neightet); // sstpivot(seg, neightet);
spintet = neightet;
while (1) {
pc = apex(spintet);
if (pc != dummypoint) {
d = DIST(midpt, pc);
diff = fabs(r - d);
if ((diff / r) < b->epsilon) {
// testpt is on the diametric ball of [pa, pb].
encroached = 0;
} else {
encroached = (d < r ? 1 : 0);
}
if (encroached) {
encpt = pc; // pc is encroached [pa. pb].
break;
}
}
fnextself(spintet);
if (spintet.tet == neightet.tet) break;
}
} else {
d = DIST(midpt, testpt);
diff = fabs(r - d);
if ((diff / r) < b->epsilon) {
// testpt is on the diametric ball of [pa, pb].
encroached = 0;
} else {
encroached = (d < r ? 1 : 0);
if (encroached) {
encpt = testpt;
}
}
}
if (encroached && enqflag) {
if (b->verbose > 1) {
printf(" Queuing encroaching segment (%d, %d) ref (%d).\n",
pointmark(pa), pointmark(pb), pointmark(encpt));
}
encseg = (badface *) badsegpool->alloc();
encseg->ss = seg;
encseg->forg = pa;
encseg->fdest = pb;
encseg->foppo = encpt; // The encroaching point.
smarktest(seg); // Flag it to avoid multiple testing.
}
return encroached > 0;
}
///////////////////////////////////////////////////////////////////////////////
// //
// repairencsegs() Repair all queued encroached subsegments. //
// //
// Encroached segments are repaired by inserting a vertex inside them. Each //
// newly inserted vertex may encroach other segments, or makeing them non- //
// Delaunay, these segments are also repaired. //
// //
///////////////////////////////////////////////////////////////////////////////
void tetgenmesh::repairencsegs()
{
badface *encloop;
triface searchtet;
face splitsh;
point newpt, refpt;
point pa, pb;
while ((badsegpool->items > 0) && (b->steinerleft != 0)) {
badsegpool->traversalinit();
encloop = badfacetraverse(badsegpool);
while ((encloop != NULL) && (b->steinerleft != 0)) {
// assert(smarktested(encloop->ss));
sunmarktest(encloop->ss);
// Check if it is still the same segment when it is tested.
pa = sorg(encloop->ss);
pb = sdest(encloop->ss);
if ((encloop->forg == pa) && (encloop->fdest == pb)) {
refpt = encloop->foppo;
if ((refpt == NULL) || getpointtype(refpt) == DEADVERTEX) {
// Check if this segment can be split.
assert(0); // Not handled yet.
}
// Create a new point in the segment.
makepoint(&newpt);
// getsegmentsplitpoint2(&(encloop->ss), refpt, newpt);
getsegmentsplitpoint3(&(encloop->ss), refpt, newpt);
setpointtype(newpt, STEINERVERTEX);
// Decrease the number of allocated Steiner points (-S option).
if (b->steinerleft != -1) {
b->steinerleft--;
}
// Get an adjacent tet for point location.
stpivot(encloop->ss, searchtet);
// Split the segment by newpt. Two new subsegments and new subfaces
// are queued in subsegstack and subfacstack for recovery.
spivot(encloop->ss, splitsh);
sinsertvertex(newpt, &splitsh, &(encloop->ss), true, false);
// Insert newpt into the DT. Since the mesh may be a CDT, always
// set visflag be true. Some existing egments and subfaces may be
// non-Delaunay due to this new vertex, they will be removed from
// the mesh, and are queued in subsegstack and subfacstack for
// recovery.
// Newly encroached segments, subfaces, and badly-shaped tets are
// queued in badsegpool, badsubpool, and badtetpool, resp.
insertvertex(newpt, &searchtet, true, true, false, false);
// Recover missing subsegments.
assert(subsegstack->objects > 0);
delaunizesegments();
// Recover missing subfaces.
assert(subfacstack->objects > 0);
constrainedfacets();
}
// Deallocate the badface.
badfacedealloc(badsegpool, encloop);
// Get the next badface.
encloop = badfacetraverse(badsegpool);
} // while (encloop != NULL)
} // while (badsegpool->items > 0)
}
///////////////////////////////////////////////////////////////////////////////
// //
// enforcequality() Create quality conforming Delaunay mesh. //
// //
///////////////////////////////////////////////////////////////////////////////
void tetgenmesh::enforcequality()
{
face shloop;
REAL bakeps;
long bakptcount;
if (!b->quiet) {
printf("Conforming Delaunay meshing.\n");
}
bakeps = b->epsilon; // Bakup the epsilon.
b->epsilon = 0;
// Initialize the pool for storing encroched segments.
badsegpool = new memorypool(sizeof(badface), SUBPERBLOCK, POINTER, 0);
// Initialize arrays.
tg_crosstets = new arraypool(sizeof(triface), 10);
tg_topnewtets = new arraypool(sizeof(triface), 10);
tg_botnewtets = new arraypool(sizeof(triface), 10);
tg_topfaces = new arraypool(sizeof(triface), 10);
tg_botfaces = new arraypool(sizeof(triface), 10);
tg_midfaces = new arraypool(sizeof(triface), 10);
tg_toppoints = new arraypool(sizeof(point), 8);
tg_botpoints = new arraypool(sizeof(point), 8);
tg_facpoints = new arraypool(sizeof(point), 8);
tg_facfaces = new arraypool(sizeof(face), 10);
tg_topshells = new arraypool(sizeof(face), 10);
tg_botshells = new arraypool(sizeof(face), 10);
// Find all encroached segments.
subsegpool->traversalinit();
shloop.sh = shellfacetraverse(subsegpool);
while (shloop.sh != NULL) {
checkedge4encroach(shloop, NULL, 1);
shloop.sh = shellfacetraverse(subsegpool);
}
if (b->verbose && (badsegpool->items > 0)) {
printf(" Splitting encroached segments.\n");
}
bakptcount = pointpool->items;
// Fix encroached segments.
repairencsegs();
// At this point, no segments should be encroached.
if (b->verbose && ((pointpool->items - bakptcount) > 0)) {
printf(" %ld Steiner points.\n", pointpool->items - bakptcount);
}
// Delete arrays.
delete tg_crosstets;
delete tg_topnewtets;
delete tg_botnewtets;
delete tg_topfaces;
delete tg_botfaces;
delete tg_midfaces;
delete tg_toppoints;
delete tg_botpoints;
delete tg_facpoints;
delete tg_facfaces;
delete tg_topshells;
delete tg_botshells;
delete badsegpool;
b->epsilon = bakeps; // Restore the epsilon.
}
#endif // #ifndef refineCXX
This diff is collapsed.
This diff is collapsed.
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment