Nektar++
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
Public Member Functions | Public Attributes | Private Member Functions | Private Attributes | Friends | List of all members
Nektar::NekMeshUtils::DelaunayTriangle Class Reference

#include <Triangle.h>

Collaboration diagram for Nektar::NekMeshUtils::DelaunayTriangle:
Collaboration graph
[legend]

Public Member Functions

void triangulate (char *)
 
void trifree (void *memptr)
 

Public Attributes

struct triangulateio in out
 

Private Member Functions

int triunsuitable (vertex triorg, vertex tridest, vertex triapex, double area)
 
void triexit (int status)
 
voidtrimalloc (int size)
 
void internalerror ()
 
void parsecommandline (int argc, char **argv, struct behavior *b)
 
void poolzero (struct memorypool *pool)
 
void poolrestart (struct memorypool *pool)
 
void pooldeinit (struct memorypool *pool)
 
voidpoolalloc (struct memorypool *pool)
 
void pooldealloc (struct memorypool *pool, void *dyingitem)
 
void traversalinit (struct memorypool *pool)
 
voidtraverse (struct memorypool *pool)
 
void initializevertexpool (struct mesh *m, struct behavior *b)
 
void initializetrisubpools (struct mesh *m, struct behavior *b)
 
void triangledealloc (struct mesh *m, triangle *dyingtriangle)
 
triangletriangletraverse (struct mesh *m)
 
void subsegdealloc (struct mesh *m, subseg *dyingsubseg)
 
subsegsubsegtraverse (struct mesh *m)
 
void vertexdealloc (struct mesh *m, vertex dyingvertex)
 
vertex vertextraverse (struct mesh *m)
 
void badsubsegdealloc (struct mesh *m, struct badsubseg *dyingseg)
 
struct badsubsegbadsubsegtraverse (struct mesh *m)
 
vertex getvertex (struct mesh *m, struct behavior *b, int number)
 
void triangledeinit (struct mesh *m, struct behavior *b)
 
void maketriangle (struct mesh *m, struct behavior *b, struct otri *newotri)
 
void makesubseg (struct mesh *m, struct osub *newsubseg)
 
void exactinit ()
 
int scale_expansion_zeroelimTRI (int elen, double *e, double b, double *h)
 
double estimateTRI (int elen, double *e)
 
double counterclockwise (struct mesh *m, struct behavior *b, vertex pa, vertex pb, vertex pc)
 
double counterclockwiseadapt (vertex pa, vertex pb, vertex pc, double detsum)
 
void poolinit (struct memorypool *pool, int bytecount, int itemcount, int firstitemcount, int alignment)
 
void dummyinit (struct mesh *m, struct behavior *b, int trianglebytes, int subsegbytes)
 
double incircleadaptTRI (vertex pa, vertex pb, vertex pc, vertex pd, double permanent)
 
double incircle (struct mesh *m, struct behavior *b, vertex pa, vertex pb, vertex pc, vertex pd)
 
void triangleinit (struct mesh *m)
 
unsigned long randomnation (unsigned int choices)
 
struct badtriangdequeuebadtriang (struct mesh *m)
 
void testtriangle (struct mesh *m, struct behavior *b, struct otri *testtri)
 
void makevertexmap (struct mesh *m, struct behavior *b)
 
void flip (struct mesh *m, struct behavior *b, struct otri *flipedge)
 
void unflip (struct mesh *m, struct behavior *b, struct otri *flipedge)
 
int fast_expansion_sum_zeroelimTRI (int elen, double *e, int flen, double *f, double *h)
 
double orient3dadapt (vertex pa, vertex pb, vertex pc, vertex pd, double aheight, double bheight, double cheight, double dheight, double permanent)
 
double orient3d (struct mesh *m, struct behavior *b, vertex pa, vertex pb, vertex pc, vertex pd, double aheight, double bheight, double cheight, double dheight)
 
double nonregular (struct mesh *m, struct behavior *b, vertex pa, vertex pb, vertex pc, vertex pd)
 
void findcircumcenter (struct mesh *m, struct behavior *b, vertex torg, vertex tdest, vertex tapex, vertex circumcenter, double *xi, double *eta, int offcenter)
 
void enqueuebadtriang (struct mesh *m, struct behavior *b, struct badtriang *badtri)
 
void enqueuebadtri (struct mesh *m, struct behavior *b, struct otri *enqtri, double minedge, vertex enqapex, vertex enqorg, vertex enqdest)
 
int checkseg4encroach (struct mesh *m, struct behavior *b, struct osub *testsubseg)
 
enum locateresult preciselocate (struct mesh *m, struct behavior *b, vertex searchpoint, struct otri *searchtri, int stopatsubsegment)
 
enum locateresult locate (struct mesh *m, struct behavior *b, vertex searchpoint, struct otri *searchtri)
 
void insertsubseg (struct mesh *m, struct behavior *b, struct otri *tri, int subsegmark)
 
enum insertvertexresult insertvertex (struct mesh *m, struct behavior *b, vertex newvertex, struct otri *searchtri, struct osub *splitseg, int segmentflaws, int triflaws)
 
void triangulatepolygon (struct mesh *m, struct behavior *b, struct otri *firstedge, struct otri *lastedge, int edgecount, int doflip, int triflaws)
 
void deletevertex (struct mesh *m, struct behavior *b, struct otri *deltri)
 
void undovertex (struct mesh *m, struct behavior *b)
 
void vertexsort (vertex *sortarray, unsigned int arraysize)
 
void vertexmedian (vertex *sortarray, int arraysize, int median, int axis)
 
void alternateaxes (vertex *sortarray, int arraysize, int axis)
 
long removeghosts (struct mesh *m, struct behavior *b, struct otri *startghost)
 
long divconqdelaunay (struct mesh *m, struct behavior *b)
 
long delaunay (struct mesh *m, struct behavior *b)
 
void mergehulls (struct mesh *m, struct behavior *b, struct otri *farleft, struct otri *innerleft, struct otri *innerright, struct otri *farright, int axis)
 
void divconqrecurse (struct mesh *m, struct behavior *b, vertex *sortarray, int vertices, int axis, struct otri *farleft, struct otri *farright)
 
enum finddirectionresult finddirection (struct mesh *m, struct behavior *b, struct otri *searchtri, vertex searchpoint)
 
void segmentintersection (struct mesh *m, struct behavior *b, struct otri *splittri, struct osub *splitsubseg, vertex endpoint2)
 
int scoutsegment (struct mesh *m, struct behavior *b, struct otri *searchtri, vertex endpoint2, int newmark)
 
void conformingedge (struct mesh *m, struct behavior *b, vertex endpoint1, vertex endpoint2, int newmark)
 
void delaunayfixup (struct mesh *m, struct behavior *b, struct otri *fixuptri, int leftside)
 
void constrainededge (struct mesh *m, struct behavior *b, struct otri *starttri, vertex endpoint2, int newmark)
 
void insertsegment (struct mesh *m, struct behavior *b, vertex endpoint1, vertex endpoint2, int newmark)
 
void markhull (struct mesh *m, struct behavior *b)
 
void formskeleton (struct mesh *m, struct behavior *b, int *segmentlist, int *segmentmarkerlist, int numberofsegments)
 
void infecthull (struct mesh *m, struct behavior *b)
 
void plague (struct mesh *m, struct behavior *b)
 
void regionplague (struct mesh *m, struct behavior *b, double attribute, double area)
 
void carveholes (struct mesh *m, struct behavior *b, double *holelist, int holes, double *regionlist, int regions)
 
void tallyencs (struct mesh *m, struct behavior *b)
 
void precisionerror ()
 
void splitencsegs (struct mesh *m, struct behavior *b, int triflaws)
 
void tallyfaces (struct mesh *m, struct behavior *b)
 
void splittriangle (struct mesh *m, struct behavior *b, struct badtriang *badtri)
 
void enforcequality (struct mesh *m, struct behavior *b)
 
void transfernodes (struct mesh *m, struct behavior *b, double *pointlist, double *pointattriblist, int *pointmarkerlist, int numberofpoints, int numberofpointattribs)
 
void writenodes (struct mesh *m, struct behavior *b, double **pointlist, double **pointattriblist, int **pointmarkerlist)
 
void numbernodes (struct mesh *m, struct behavior *b)
 
void writeelements (struct mesh *m, struct behavior *b, int **trianglelist, double **triangleattriblist)
 
void writepoly (struct mesh *m, struct behavior *b, int **segmentlist, int **segmentmarkerlist)
 

Private Attributes

double splitter
 
double epsilon
 
double resulterrbound
 
double ccwerrboundA
 
double ccwerrboundB
 
double ccwerrboundC
 
double iccerrboundA
 
double iccerrboundB
 
double iccerrboundC
 
double o3derrboundA
 
double o3derrboundB
 
double o3derrboundC
 
unsigned long randomseed
 
int plus1mod3 [3]
 
int minus1mod3 [3]
 

Friends

class MemoryManager< DelaunayTriangle >
 

Detailed Description

Definition at line 951 of file Triangle/Triangle.h.

Member Function Documentation

void Nektar::NekMeshUtils::DelaunayTriangle::alternateaxes ( vertex sortarray,
int  arraysize,
int  axis 
)
private

Definition at line 5726 of file Triangle/Triangle.cpp.

References vertexmedian().

Referenced by divconqdelaunay().

5727 {
5728  int divider;
5729 
5730  divider = arraysize >> 1;
5731  if (arraysize <= 3)
5732  {
5733  /* Recursive base case: subsets of two or three vertices will be */
5734  /* handled specially, and should always be sorted by x-coordinate. */
5735  axis = 0;
5736  }
5737  /* Partition with a horizontal or vertical cut. */
5738  vertexmedian(sortarray, arraysize, divider, axis);
5739  /* Recursively partition the subsets with a cross cut. */
5740  if (arraysize - divider >= 2)
5741  {
5742  if (divider >= 2)
5743  {
5744  alternateaxes(sortarray, divider, 1 - axis);
5745  }
5746  alternateaxes(&sortarray[divider], arraysize - divider, 1 - axis);
5747  }
5748 }
void alternateaxes(vertex *sortarray, int arraysize, int axis)
void vertexmedian(vertex *sortarray, int arraysize, int median, int axis)
void Nektar::NekMeshUtils::DelaunayTriangle::badsubsegdealloc ( struct mesh m,
struct badsubseg dyingseg 
)
private

Definition at line 1150 of file Triangle/Triangle.cpp.

References Nektar::NekMeshUtils::mesh::badsubsegs, pooldealloc(), and Nektar::NekMeshUtils::badsubseg::subsegorg.

Referenced by splitencsegs().

1151 {
1152  /* Set subsegment's origin to NULL. This makes it possible to detect dead
1153  */
1154  /* badsubsegs when traversing the list of all badsubsegs . */
1155  dyingseg->subsegorg = (vertex)NULL;
1156  pooldealloc(&m->badsubsegs, (void *)dyingseg);
1157 }
void pooldealloc(struct memorypool *pool, void *dyingitem)
struct badsubseg * Nektar::NekMeshUtils::DelaunayTriangle::badsubsegtraverse ( struct mesh m)
private

Definition at line 1165 of file Triangle/Triangle.cpp.

References Nektar::NekMeshUtils::mesh::badsubsegs, Nektar::NekMeshUtils::badsubseg::subsegorg, and traverse().

Referenced by splitencsegs().

1166 {
1167  struct badsubseg *newseg;
1168 
1169  do
1170  {
1171  newseg = (struct badsubseg *)traverse(&m->badsubsegs);
1172  if (newseg == (struct badsubseg *)NULL)
1173  {
1174  return (struct badsubseg *)NULL;
1175  }
1176  } while (newseg->subsegorg == (vertex)NULL); /* Skip dead ones. */
1177  return newseg;
1178 }
void * traverse(struct memorypool *pool)
void Nektar::NekMeshUtils::DelaunayTriangle::carveholes ( struct mesh m,
struct behavior b,
double *  holelist,
int  holes,
double *  regionlist,
int  regions 
)
private

Definition at line 7763 of file Triangle/Triangle.cpp.

References counterclockwise(), deadtri, dest, Nektar::NekMeshUtils::mesh::dummytri, infect, infected, infecthull(), Nektar::NekMeshUtils::memorypool::items, locate(), org, Nektar::NekMeshUtils::otri::orient, otricopy, Nektar::NekMeshUtils::OUTSIDE, plague(), poolalloc(), pooldeinit(), poolinit(), regionplague(), symself, Nektar::NekMeshUtils::otri::tri, trifree(), trimalloc(), Nektar::NekMeshUtils::mesh::viri, VIRUSPERBLOCK, Nektar::NekMeshUtils::mesh::xmax, Nektar::NekMeshUtils::mesh::xmin, Nektar::NekMeshUtils::mesh::ymax, and Nektar::NekMeshUtils::mesh::ymin.

Referenced by triangulate().

7769 {
7770  struct otri searchtri;
7771  struct otri *regiontris;
7772  triangle **holetri;
7773  triangle **regiontri;
7774  vertex searchorg, searchdest;
7775  enum locateresult intersect;
7776  int i;
7777  triangle ptr; /* Temporary variable used by sym(). */
7778 
7779  if (regions > 0)
7780  {
7781  /* Allocate storage for the triangles in which region points fall. */
7782  regiontris =
7783  (struct otri *)trimalloc(regions * (int)sizeof(struct otri));
7784  }
7785  else
7786  {
7787  regiontris = (struct otri *)NULL;
7788  }
7789 
7790 
7791  /* Initialize a pool of viri to be used for holes, concavities, */
7792  /* regional attributes, and/or regional area constraints. */
7793  poolinit(&m->viri, sizeof(triangle *), VIRUSPERBLOCK, VIRUSPERBLOCK, 0);
7794 
7795  /* Mark as infected any unprotected triangles on the boundary. */
7796  /* This is one way by which concavities are created. */
7797  infecthull(m, b);
7798 
7799  if (holes > 0)
7800  {
7801  /* Infect each triangle in which a hole lies. */
7802  for (i = 0; i < 2 * holes; i += 2)
7803  {
7804  /* Ignore holes that aren't within the bounds of the mesh. */
7805  if ((holelist[i] >= m->xmin) && (holelist[i] <= m->xmax) &&
7806  (holelist[i + 1] >= m->ymin) && (holelist[i + 1] <= m->ymax))
7807  {
7808  /* Start searching from some triangle on the outer boundary. */
7809  searchtri.tri = m->dummytri;
7810  searchtri.orient = 0;
7811  symself(searchtri);
7812  /* Ensure that the hole is to the left of this boundary edge; */
7813  /* otherwise, locate() will falsely report that the hole */
7814  /* falls within the starting triangle. */
7815  org(searchtri, searchorg);
7816  dest(searchtri, searchdest);
7817  if (counterclockwise(
7818  m, b, searchorg, searchdest, &holelist[i]) > 0.0)
7819  {
7820  /* Find a triangle that contains the hole. */
7821  intersect = locate(m, b, &holelist[i], &searchtri);
7822  if ((intersect != OUTSIDE) && (!infected(searchtri)))
7823  {
7824  /* Infect the triangle. This is done by marking the
7825  * triangle */
7826  /* as infected and including the triangle in the virus
7827  * pool. */
7828  infect(searchtri);
7829  holetri = (triangle **)poolalloc(&m->viri);
7830  *holetri = searchtri.tri;
7831  }
7832  }
7833  }
7834  }
7835  }
7836 
7837  /* Now, we have to find all the regions BEFORE we carve the holes, because
7838  */
7839  /* locate() won't work when the triangulation is no longer convex. */
7840  /* (Incidentally, this is the reason why regional attributes and area */
7841  /* constraints can't be used when refining a preexisting mesh, which */
7842  /* might not be convex; they can only be used with a freshly */
7843  /* triangulated PSLG.) */
7844  if (regions > 0)
7845  {
7846  /* Find the starting triangle for each region. */
7847  for (i = 0; i < regions; i++)
7848  {
7849  regiontris[i].tri = m->dummytri;
7850  /* Ignore region points that aren't within the bounds of the mesh.
7851  */
7852  if ((regionlist[4 * i] >= m->xmin) &&
7853  (regionlist[4 * i] <= m->xmax) &&
7854  (regionlist[4 * i + 1] >= m->ymin) &&
7855  (regionlist[4 * i + 1] <= m->ymax))
7856  {
7857  /* Start searching from some triangle on the outer boundary. */
7858  searchtri.tri = m->dummytri;
7859  searchtri.orient = 0;
7860  symself(searchtri);
7861  /* Ensure that the region point is to the left of this boundary
7862  */
7863  /* edge; otherwise, locate() will falsely report that the */
7864  /* region point falls within the starting triangle. */
7865  org(searchtri, searchorg);
7866  dest(searchtri, searchdest);
7867  if (counterclockwise(
7868  m, b, searchorg, searchdest, &regionlist[4 * i]) > 0.0)
7869  {
7870  /* Find a triangle that contains the region point. */
7871  intersect = locate(m, b, &regionlist[4 * i], &searchtri);
7872  if ((intersect != OUTSIDE) && (!infected(searchtri)))
7873  {
7874  /* Record the triangle for processing after the */
7875  /* holes have been carved. */
7876  otricopy(searchtri, regiontris[i]);
7877  }
7878  }
7879  }
7880  }
7881  }
7882 
7883  if (m->viri.items > 0)
7884  {
7885  /* Carve the holes and concavities. */
7886  plague(m, b);
7887  }
7888  /* The virus pool should be empty now. */
7889 
7890  if (regions > 0)
7891  {
7892  for (i = 0; i < regions; i++)
7893  {
7894  if (regiontris[i].tri != m->dummytri)
7895  {
7896  /* Make sure the triangle under consideration still exists. */
7897  /* It may have been eaten by the virus. */
7898  if (!deadtri(regiontris[i].tri))
7899  {
7900  /* Put one triangle in the virus pool. */
7901  infect(regiontris[i]);
7902  regiontri = (triangle **)poolalloc(&m->viri);
7903  *regiontri = regiontris[i].tri;
7904  /* Apply one region's attribute and/or area constraint. */
7905  regionplague(
7906  m, b, regionlist[4 * i + 2], regionlist[4 * i + 3]);
7907  /* The virus pool should be empty now. */
7908  }
7909  }
7910  }
7911  }
7912 
7913 
7914  pooldeinit(&m->viri);
7915 
7916  if (regions > 0)
7917  {
7918  trifree((void *)regiontris);
7919  }
7920 }
void pooldeinit(struct memorypool *pool)
#define VIRUSPERBLOCK
void * poolalloc(struct memorypool *pool)
void poolinit(struct memorypool *pool, int bytecount, int itemcount, int firstitemcount, int alignment)
#define infected(otri)
#define symself(otri)
double counterclockwise(struct mesh *m, struct behavior *b, vertex pa, vertex pb, vertex pc)
void plague(struct mesh *m, struct behavior *b)
#define infect(otri)
void infecthull(struct mesh *m, struct behavior *b)
#define otricopy(otri1, otri2)
#define dest(otri, vertexptr)
#define deadtri(tria)
enum locateresult locate(struct mesh *m, struct behavior *b, vertex searchpoint, struct otri *searchtri)
#define org(otri, vertexptr)
void regionplague(struct mesh *m, struct behavior *b, double attribute, double area)
int Nektar::NekMeshUtils::DelaunayTriangle::checkseg4encroach ( struct mesh m,
struct behavior b,
struct osub testsubseg 
)
private

Definition at line 3605 of file Triangle/Triangle.cpp.

References apex, Nektar::NekMeshUtils::mesh::badsubsegs, Nektar::NekMeshUtils::mesh::dummytri, Nektar::NekMeshUtils::badsubseg::encsubseg, Nektar::NekMeshUtils::behavior::goodangle, Nektar::NekMeshUtils::behavior::nobisect, poolalloc(), sdest, sencode, sorg, ssym, stpivot, Nektar::NekMeshUtils::badsubseg::subsegdest, Nektar::NekMeshUtils::badsubseg::subsegorg, and Nektar::NekMeshUtils::otri::tri.

Referenced by insertvertex(), splitencsegs(), and tallyencs().

3608 {
3609  struct otri neighbortri;
3610  struct osub testsym;
3611  struct badsubseg *encroachedseg;
3612  double dotproduct;
3613  int encroached;
3614  int sides;
3615  vertex eorg, edest, eapex;
3616  triangle ptr; /* Temporary variable used by stpivot(). */
3617 
3618  encroached = 0;
3619  sides = 0;
3620 
3621  sorg(*testsubseg, eorg);
3622  sdest(*testsubseg, edest);
3623  /* Check one neighbor of the subsegment. */
3624  stpivot(*testsubseg, neighbortri);
3625  /* Does the neighbor exist, or is this a boundary edge? */
3626  if (neighbortri.tri != m->dummytri)
3627  {
3628  sides++;
3629  /* Find a vertex opposite this subsegment. */
3630  apex(neighbortri, eapex);
3631  /* Check whether the apex is in the diametral lens of the subsegment */
3632  /* (the diametral circle if `conformdel' is set). A dot product */
3633  /* of two sides of the triangle is used to check whether the angle */
3634  /* at the apex is greater than (180 - 2 `minangle') degrees (for */
3635  /* lenses; 90 degrees for diametral circles). */
3636  dotproduct = (eorg[0] - eapex[0]) * (edest[0] - eapex[0]) +
3637  (eorg[1] - eapex[1]) * (edest[1] - eapex[1]);
3638  if (dotproduct < 0.0)
3639  {
3640  if (dotproduct * dotproduct >=
3641  (2.0 * b->goodangle - 1.0) * (2.0 * b->goodangle - 1.0) *
3642  ((eorg[0] - eapex[0]) * (eorg[0] - eapex[0]) +
3643  (eorg[1] - eapex[1]) * (eorg[1] - eapex[1])) *
3644  ((edest[0] - eapex[0]) * (edest[0] - eapex[0]) +
3645  (edest[1] - eapex[1]) * (edest[1] - eapex[1])))
3646  {
3647  encroached = 1;
3648  }
3649  }
3650  }
3651  /* Check the other neighbor of the subsegment. */
3652  ssym(*testsubseg, testsym);
3653  stpivot(testsym, neighbortri);
3654  /* Does the neighbor exist, or is this a boundary edge? */
3655  if (neighbortri.tri != m->dummytri)
3656  {
3657  sides++;
3658  /* Find the other vertex opposite this subsegment. */
3659  apex(neighbortri, eapex);
3660  /* Check whether the apex is in the diametral lens of the subsegment */
3661  /* (or the diametral circle, if `conformdel' is set). */
3662  dotproduct = (eorg[0] - eapex[0]) * (edest[0] - eapex[0]) +
3663  (eorg[1] - eapex[1]) * (edest[1] - eapex[1]);
3664  if (dotproduct < 0.0)
3665  {
3666  if (dotproduct * dotproduct >=
3667  (2.0 * b->goodangle - 1.0) * (2.0 * b->goodangle - 1.0) *
3668  ((eorg[0] - eapex[0]) * (eorg[0] - eapex[0]) +
3669  (eorg[1] - eapex[1]) * (eorg[1] - eapex[1])) *
3670  ((edest[0] - eapex[0]) * (edest[0] - eapex[0]) +
3671  (edest[1] - eapex[1]) * (edest[1] - eapex[1])))
3672  {
3673  encroached += 2;
3674  }
3675  }
3676  }
3677 
3678  if (encroached && (!b->nobisect || ((b->nobisect == 1) && (sides == 2))))
3679  {
3680  /* Add the subsegment to the list of encroached subsegments. */
3681  /* Be sure to get the orientation right. */
3682  encroachedseg = (struct badsubseg *)poolalloc(&m->badsubsegs);
3683  if (encroached == 1)
3684  {
3685  encroachedseg->encsubseg = sencode(*testsubseg);
3686  encroachedseg->subsegorg = eorg;
3687  encroachedseg->subsegdest = edest;
3688  }
3689  else
3690  {
3691  encroachedseg->encsubseg = sencode(testsym);
3692  encroachedseg->subsegorg = edest;
3693  encroachedseg->subsegdest = eorg;
3694  }
3695  }
3696 
3697  return encroached;
3698 }
#define stpivot(osub, otri)
void * poolalloc(struct memorypool *pool)
#define sdest(osub, vertexptr)
#define apex(otri, vertexptr)
#define sorg(osub, vertexptr)
#define sencode(osub)
#define ssym(osub1, osub2)
void Nektar::NekMeshUtils::DelaunayTriangle::conformingedge ( struct mesh m,
struct behavior b,
vertex  endpoint1,
vertex  endpoint2,
int  newmark 
)
private

Definition at line 6784 of file Triangle/Triangle.cpp.

References Nektar::NekMeshUtils::mesh::dummytri, Nektar::NekMeshUtils::DUPLICATEVERTEX, finddirection(), insertvertex(), internalerror(), Nektar::NekMeshUtils::mesh::nextras, org, otricopy, poolalloc(), scoutsegment(), SEGMENTVERTEX, setvertexmark, setvertextype, Nektar::NekMeshUtils::mesh::steinerleft, Nektar::NekMeshUtils::SUCCESSFULVERTEX, Nektar::NekMeshUtils::otri::tri, tspivot, vertexdealloc(), Nektar::NekMeshUtils::mesh::vertices, and Nektar::NekMeshUtils::VIOLATINGVERTEX.

6789 {
6790  struct otri searchtri1, searchtri2;
6791  struct osub brokensubseg;
6792  vertex newvertex;
6793  vertex midvertex1, midvertex2;
6794  enum insertvertexresult success;
6795  int i;
6796  subseg sptr; /* Temporary variable used by tspivot(). */
6797 
6798  /* Create a new vertex to insert in the middle of the segment. */
6799  newvertex = (vertex)poolalloc(&m->vertices);
6800  /* Interpolate coordinates and attributes. */
6801  for (i = 0; i < 2 + m->nextras; i++)
6802  {
6803  newvertex[i] = 0.5 * (endpoint1[i] + endpoint2[i]);
6804  }
6805  setvertexmark(newvertex, newmark);
6806  setvertextype(newvertex, SEGMENTVERTEX);
6807  /* No known triangle to search from. */
6808  searchtri1.tri = m->dummytri;
6809  /* Attempt to insert the new vertex. */
6810  success =
6811  insertvertex(m, b, newvertex, &searchtri1, (struct osub *)NULL, 0, 0);
6812  if (success == DUPLICATEVERTEX)
6813  {
6814 
6815  /* Use the vertex that's already there. */
6816  vertexdealloc(m, newvertex);
6817  org(searchtri1, newvertex);
6818  }
6819  else
6820  {
6821  if (success == VIOLATINGVERTEX)
6822  {
6823 
6824  /* By fluke, we've landed right on another segment. Split it. */
6825  tspivot(searchtri1, brokensubseg);
6826  success =
6827  insertvertex(m, b, newvertex, &searchtri1, &brokensubseg, 0, 0);
6828  if (success != SUCCESSFULVERTEX)
6829  {
6830  printf("Internal error in conformingedge():\n");
6831  printf(" Failure to split a segment.\n");
6832  internalerror();
6833  }
6834  }
6835  /* The vertex has been inserted successfully. */
6836  if (m->steinerleft > 0)
6837  {
6838  m->steinerleft--;
6839  }
6840  }
6841  otricopy(searchtri1, searchtri2);
6842  /* `searchtri1' and `searchtri2' are fastened at their origins to */
6843  /* `newvertex', and will be directed toward `endpoint1' and `endpoint2' */
6844  /* respectively. First, we must get `searchtri2' out of the way so it */
6845  /* won't be invalidated during the insertion of the first half of the */
6846  /* segment. */
6847  finddirection(m, b, &searchtri2, endpoint2);
6848  if (!scoutsegment(m, b, &searchtri1, endpoint1, newmark))
6849  {
6850  /* The origin of searchtri1 may have changed if a collision with an */
6851  /* intervening vertex on the segment occurred. */
6852  org(searchtri1, midvertex1);
6853  conformingedge(m, b, midvertex1, endpoint1, newmark);
6854  }
6855  if (!scoutsegment(m, b, &searchtri2, endpoint2, newmark))
6856  {
6857  /* The origin of searchtri2 may have changed if a collision with an */
6858  /* intervening vertex on the segment occurred. */
6859  org(searchtri2, midvertex2);
6860  conformingedge(m, b, midvertex2, endpoint2, newmark);
6861  }
6862 }
#define SEGMENTVERTEX
void * poolalloc(struct memorypool *pool)
enum insertvertexresult insertvertex(struct mesh *m, struct behavior *b, vertex newvertex, struct otri *searchtri, struct osub *splitseg, int segmentflaws, int triflaws)
#define setvertextype(vx, value)
void vertexdealloc(struct mesh *m, vertex dyingvertex)
enum finddirectionresult finddirection(struct mesh *m, struct behavior *b, struct otri *searchtri, vertex searchpoint)
#define setvertexmark(vx, value)
#define otricopy(otri1, otri2)
#define tspivot(otri, osub)
int scoutsegment(struct mesh *m, struct behavior *b, struct otri *searchtri, vertex endpoint2, int newmark)
#define org(otri, vertexptr)
void conformingedge(struct mesh *m, struct behavior *b, vertex endpoint1, vertex endpoint2, int newmark)
void Nektar::NekMeshUtils::DelaunayTriangle::constrainededge ( struct mesh m,
struct behavior b,
struct otri starttri,
vertex  endpoint2,
int  newmark 
)
private

Definition at line 7024 of file Triangle/Triangle.cpp.

References counterclockwise(), delaunayfixup(), Nektar::NekMeshUtils::mesh::dummysub, flip(), insertsubseg(), lnext, lprevself, oprev, oprevself, org, scoutsegment(), segmentintersection(), Nektar::NekMeshUtils::osub::ss, and tspivot.

Referenced by insertsegment().

7029 {
7030  struct otri fixuptri, fixuptri2;
7031  struct osub crosssubseg;
7032  vertex endpoint1;
7033  vertex farvertex;
7034  double area;
7035  int collision;
7036  int done;
7037  triangle ptr; /* Temporary variable used by sym() and oprev(). */
7038  subseg sptr; /* Temporary variable used by tspivot(). */
7039 
7040  org(*starttri, endpoint1);
7041  lnext(*starttri, fixuptri);
7042  flip(m, b, &fixuptri);
7043  /* `collision' indicates whether we have found a vertex directly */
7044  /* between endpoint1 and endpoint2. */
7045  collision = 0;
7046  done = 0;
7047  do
7048  {
7049  org(fixuptri, farvertex);
7050  /* `farvertex' is the extreme point of the polygon we are "digging" */
7051  /* to get from endpoint1 to endpoint2. */
7052  if ((farvertex[0] == endpoint2[0]) && (farvertex[1] == endpoint2[1]))
7053  {
7054  oprev(fixuptri, fixuptri2);
7055  /* Enforce the Delaunay condition around endpoint2. */
7056  delaunayfixup(m, b, &fixuptri, 0);
7057  delaunayfixup(m, b, &fixuptri2, 1);
7058  done = 1;
7059  }
7060  else
7061  {
7062  /* Check whether farvertex is to the left or right of the segment */
7063  /* being inserted, to decide which edge of fixuptri to dig */
7064  /* through next. */
7065  area = counterclockwise(m, b, endpoint1, endpoint2, farvertex);
7066  if (area == 0.0)
7067  {
7068  /* We've collided with a vertex between endpoint1 and endpoint2.
7069  */
7070  collision = 1;
7071  oprev(fixuptri, fixuptri2);
7072  /* Enforce the Delaunay condition around farvertex. */
7073  delaunayfixup(m, b, &fixuptri, 0);
7074  delaunayfixup(m, b, &fixuptri2, 1);
7075  done = 1;
7076  }
7077  else
7078  {
7079  if (area > 0.0)
7080  { /* farvertex is to the left of the segment. */
7081  oprev(fixuptri, fixuptri2);
7082  /* Enforce the Delaunay condition around farvertex, on the
7083  */
7084  /* left side of the segment only. */
7085  delaunayfixup(m, b, &fixuptri2, 1);
7086  /* Flip the edge that crosses the segment. After the edge
7087  * is */
7088  /* flipped, one of its endpoints is the fan vertex, and
7089  * the */
7090  /* destination of fixuptri is the fan vertex. */
7091  lprevself(fixuptri);
7092  }
7093  else
7094  { /* farvertex is to the right of the segment. */
7095  delaunayfixup(m, b, &fixuptri, 0);
7096  /* Flip the edge that crosses the segment. After the edge
7097  * is */
7098  /* flipped, one of its endpoints is the fan vertex, and
7099  * the */
7100  /* destination of fixuptri is the fan vertex. */
7101  oprevself(fixuptri);
7102  }
7103  /* Check for two intersecting segments. */
7104  tspivot(fixuptri, crosssubseg);
7105  if (crosssubseg.ss == m->dummysub)
7106  {
7107  flip(m,
7108  b,
7109  &fixuptri); /* May create inverted triangle at left. */
7110  }
7111  else
7112  {
7113  /* We've collided with a segment between endpoint1 and
7114  * endpoint2. */
7115  collision = 1;
7116  /* Insert a vertex at the intersection. */
7118  m, b, &fixuptri, &crosssubseg, endpoint2);
7119  done = 1;
7120  }
7121  }
7122  }
7123  } while (!done);
7124  /* Insert a subsegment to make the segment permanent. */
7125  insertsubseg(m, b, &fixuptri, newmark);
7126  /* If there was a collision with an interceding vertex, install another */
7127  /* segment connecting that vertex with endpoint2. */
7128  if (collision)
7129  {
7130  /* Insert the remainder of the segment. */
7131  if (!scoutsegment(m, b, &fixuptri, endpoint2, newmark))
7132  {
7133  constrainededge(m, b, &fixuptri, endpoint2, newmark);
7134  }
7135  }
7136 }
void segmentintersection(struct mesh *m, struct behavior *b, struct otri *splittri, struct osub *splitsubseg, vertex endpoint2)
void flip(struct mesh *m, struct behavior *b, struct otri *flipedge)
void insertsubseg(struct mesh *m, struct behavior *b, struct otri *tri, int subsegmark)
void delaunayfixup(struct mesh *m, struct behavior *b, struct otri *fixuptri, int leftside)
double counterclockwise(struct mesh *m, struct behavior *b, vertex pa, vertex pb, vertex pc)
#define lprevself(otri)
#define oprev(otri1, otri2)
void constrainededge(struct mesh *m, struct behavior *b, struct otri *starttri, vertex endpoint2, int newmark)
#define oprevself(otri)
#define tspivot(otri, osub)
#define lnext(otri1, otri2)
int scoutsegment(struct mesh *m, struct behavior *b, struct otri *searchtri, vertex endpoint2, int newmark)
#define org(otri, vertexptr)
double Nektar::NekMeshUtils::DelaunayTriangle::counterclockwise ( struct mesh m,
struct behavior b,
vertex  pa,
vertex  pb,
vertex  pc 
)
private

Definition at line 1797 of file Triangle/Triangle.cpp.

References ccwerrboundA, Nektar::NekMeshUtils::mesh::counterclockcount, and counterclockwiseadapt().

Referenced by carveholes(), constrainededge(), delaunayfixup(), divconqrecurse(), findcircumcenter(), finddirection(), insertvertex(), locate(), mergehulls(), preciselocate(), and splitencsegs().

1799 {
1800  double detleft, detright, det;
1801  double detsum, errbound;
1802 
1803  m->counterclockcount++;
1804 
1805  detleft = (pa[0] - pc[0]) * (pb[1] - pc[1]);
1806  detright = (pa[1] - pc[1]) * (pb[0] - pc[0]);
1807  det = detleft - detright;
1808 
1809  if (detleft > 0.0)
1810  {
1811  if (detright <= 0.0)
1812  {
1813  return det;
1814  }
1815  else
1816  {
1817  detsum = detleft + detright;
1818  }
1819  }
1820  else if (detleft < 0.0)
1821  {
1822  if (detright >= 0.0)
1823  {
1824  return det;
1825  }
1826  else
1827  {
1828  detsum = -detleft - detright;
1829  }
1830  }
1831  else
1832  {
1833  return det;
1834  }
1835 
1836  errbound = ccwerrboundA * detsum;
1837  if ((det >= errbound) || (-det >= errbound))
1838  {
1839  return det;
1840  }
1841 
1842  return counterclockwiseadapt(pa, pb, pc, detsum);
1843 }
double counterclockwiseadapt(vertex pa, vertex pb, vertex pc, double detsum)
double Nektar::NekMeshUtils::DelaunayTriangle::counterclockwiseadapt ( vertex  pa,
vertex  pb,
vertex  pc,
double  detsum 
)
private

Definition at line 1715 of file Triangle/Triangle.cpp.

References Absolute, ccwerrboundB, ccwerrboundC, estimateTRI(), fast_expansion_sum_zeroelimTRI(), resulterrbound, Two_Diff_Tail, Two_Product, and Two_Two_Diff.

Referenced by counterclockwise().

1716 {
1717  double acx, acy, bcx, bcy;
1718  double acxtail, acytail, bcxtail, bcytail;
1719  double detleft, detright;
1720  double detlefttail, detrighttail;
1721  double det, errbound;
1722  double B[4], C1[8], C2[12], D[16];
1723  double B3;
1724  int C1length, C2length, Dlength;
1725  double u[4];
1726  double u3;
1727  double s1, t1;
1728  double s0, t0;
1729 
1730  double bvirt;
1731  double avirt, bround, around;
1732  double c;
1733  double abig;
1734  double ahi, alo, bhi, blo;
1735  double err1, err2, err3;
1736  double _i, _j;
1737  double _0;
1738 
1739  acx = (double)(pa[0] - pc[0]);
1740  bcx = (double)(pb[0] - pc[0]);
1741  acy = (double)(pa[1] - pc[1]);
1742  bcy = (double)(pb[1] - pc[1]);
1743 
1744  Two_Product(acx, bcy, detleft, detlefttail);
1745  Two_Product(acy, bcx, detright, detrighttail);
1746 
1747  Two_Two_Diff(
1748  detleft, detlefttail, detright, detrighttail, B3, B[2], B[1], B[0]);
1749  B[3] = B3;
1750 
1751  det = estimateTRI(4, B);
1752  errbound = ccwerrboundB * detsum;
1753  if ((det >= errbound) || (-det >= errbound))
1754  {
1755  return det;
1756  }
1757 
1758  Two_Diff_Tail(pa[0], pc[0], acx, acxtail);
1759  Two_Diff_Tail(pb[0], pc[0], bcx, bcxtail);
1760  Two_Diff_Tail(pa[1], pc[1], acy, acytail);
1761  Two_Diff_Tail(pb[1], pc[1], bcy, bcytail);
1762 
1763  if ((acxtail == 0.0) && (acytail == 0.0) && (bcxtail == 0.0) &&
1764  (bcytail == 0.0))
1765  {
1766  return det;
1767  }
1768 
1769  errbound = ccwerrboundC * detsum + resulterrbound * Absolute(det);
1770  det += (acx * bcytail + bcy * acxtail) - (acy * bcxtail + bcx * acytail);
1771  if ((det >= errbound) || (-det >= errbound))
1772  {
1773  return det;
1774  }
1775 
1776  Two_Product(acxtail, bcy, s1, s0);
1777  Two_Product(acytail, bcx, t1, t0);
1778  Two_Two_Diff(s1, s0, t1, t0, u3, u[2], u[1], u[0]);
1779  u[3] = u3;
1780  C1length = fast_expansion_sum_zeroelimTRI(4, B, 4, u, C1);
1781 
1782  Two_Product(acx, bcytail, s1, s0);
1783  Two_Product(acy, bcxtail, t1, t0);
1784  Two_Two_Diff(s1, s0, t1, t0, u3, u[2], u[1], u[0]);
1785  u[3] = u3;
1786  C2length = fast_expansion_sum_zeroelimTRI(C1length, C1, 4, u, C2);
1787 
1788  Two_Product(acxtail, bcytail, s1, s0);
1789  Two_Product(acytail, bcxtail, t1, t0);
1790  Two_Two_Diff(s1, s0, t1, t0, u3, u[2], u[1], u[0]);
1791  u[3] = u3;
1792  Dlength = fast_expansion_sum_zeroelimTRI(C2length, C2, 4, u, D);
1793 
1794  return (D[Dlength - 1]);
1795 }
#define Absolute(a)
#define Two_Diff_Tail(a, b, x, y)
int fast_expansion_sum_zeroelimTRI(int elen, double *e, int flen, double *f, double *h)
#define Two_Two_Diff(a1, a0, b1, b0, x3, x2, x1, x0)
#define Two_Product(a, b, x, y)
long Nektar::NekMeshUtils::DelaunayTriangle::delaunay ( struct mesh m,
struct behavior b 
)
private

Definition at line 6425 of file Triangle/Triangle.cpp.

References divconqdelaunay(), Nektar::NekMeshUtils::mesh::eextras, initializetrisubpools(), Nektar::NekMeshUtils::memorypool::items, and Nektar::NekMeshUtils::mesh::triangles.

Referenced by triangulate().

6426 {
6427  long hulledges;
6428 
6429  m->eextras = 0;
6430  initializetrisubpools(m, b);
6431 
6432  hulledges = divconqdelaunay(m, b);
6433 
6434  if (m->triangles.items == 0)
6435  {
6436  /* The input vertices were all collinear, so there are no triangles. */
6437  return 0l;
6438  }
6439  else
6440  {
6441  return hulledges;
6442  }
6443 }
long divconqdelaunay(struct mesh *m, struct behavior *b)
void initializetrisubpools(struct mesh *m, struct behavior *b)
void Nektar::NekMeshUtils::DelaunayTriangle::delaunayfixup ( struct mesh m,
struct behavior b,
struct otri fixuptri,
int  leftside 
)
private

Definition at line 6902 of file Triangle/Triangle.cpp.

References apex, counterclockwise(), dest, Nektar::NekMeshUtils::mesh::dummysub, Nektar::NekMeshUtils::mesh::dummytri, flip(), incircle(), lnext, lprevself, org, Nektar::NekMeshUtils::osub::ss, sym, Nektar::NekMeshUtils::otri::tri, and tspivot.

Referenced by constrainededge().

6906 {
6907  struct otri neartri;
6908  struct otri fartri;
6909  struct osub faredge;
6910  vertex nearvertex, leftvertex, rightvertex, farvertex;
6911  triangle ptr; /* Temporary variable used by sym(). */
6912  subseg sptr; /* Temporary variable used by tspivot(). */
6913 
6914  lnext(*fixuptri, neartri);
6915  sym(neartri, fartri);
6916  /* Check if the edge opposite the origin of fixuptri can be flipped. */
6917  if (fartri.tri == m->dummytri)
6918  {
6919  return;
6920  }
6921  tspivot(neartri, faredge);
6922  if (faredge.ss != m->dummysub)
6923  {
6924  return;
6925  }
6926  /* Find all the relevant vertices. */
6927  apex(neartri, nearvertex);
6928  org(neartri, leftvertex);
6929  dest(neartri, rightvertex);
6930  apex(fartri, farvertex);
6931  /* Check whether the previous polygon vertex is a reflex vertex. */
6932  if (leftside)
6933  {
6934  if (counterclockwise(m, b, nearvertex, leftvertex, farvertex) <= 0.0)
6935  {
6936  /* leftvertex is a reflex vertex too. Nothing can */
6937  /* be done until a convex section is found. */
6938  return;
6939  }
6940  }
6941  else
6942  {
6943  if (counterclockwise(m, b, farvertex, rightvertex, nearvertex) <= 0.0)
6944  {
6945  /* rightvertex is a reflex vertex too. Nothing can */
6946  /* be done until a convex section is found. */
6947  return;
6948  }
6949  }
6950  if (counterclockwise(m, b, rightvertex, leftvertex, farvertex) > 0.0)
6951  {
6952  /* fartri is not an inverted triangle, and farvertex is not a reflex */
6953  /* vertex. As there are no reflex vertices, fixuptri isn't an */
6954  /* inverted triangle, either. Hence, test the edge between the */
6955  /* triangles to ensure it is locally Delaunay. */
6956  if (incircle(m, b, leftvertex, farvertex, rightvertex, nearvertex) <=
6957  0.0)
6958  {
6959  return;
6960  }
6961  /* Not locally Delaunay; go on to an edge flip. */
6962  } /* else fartri is inverted; remove it from the stack by flipping. */
6963  flip(m, b, &neartri);
6964  lprevself(*fixuptri); /* Restore the origin of fixuptri after the flip. */
6965  /* Recursively process the two triangles that result from the flip. */
6966  delaunayfixup(m, b, fixuptri, leftside);
6967  delaunayfixup(m, b, &fartri, leftside);
6968 }
double incircle(struct mesh *m, struct behavior *b, vertex pa, vertex pb, vertex pc, vertex pd)
#define sym(otri1, otri2)
void flip(struct mesh *m, struct behavior *b, struct otri *flipedge)
void delaunayfixup(struct mesh *m, struct behavior *b, struct otri *fixuptri, int leftside)
double counterclockwise(struct mesh *m, struct behavior *b, vertex pa, vertex pb, vertex pc)
#define lprevself(otri)
#define apex(otri, vertexptr)
#define tspivot(otri, osub)
#define lnext(otri1, otri2)
#define dest(otri, vertexptr)
#define org(otri, vertexptr)
void Nektar::NekMeshUtils::DelaunayTriangle::deletevertex ( struct mesh m,
struct behavior b,
struct otri deltri 
)
private

Definition at line 5344 of file Triangle/Triangle.cpp.

References bond, dnext, Nektar::NekMeshUtils::mesh::dummysub, lprev, Nektar::NekMeshUtils::behavior::nobisect, onext, onextself, oprev, org, otriequal, setorg, Nektar::NekMeshUtils::osub::ss, sym, testtriangle(), Nektar::NekMeshUtils::otri::tri, triangledealloc(), triangulatepolygon(), tsbond, tspivot, and vertexdealloc().

Referenced by splitencsegs().

5345 {
5346  struct otri countingtri;
5347  struct otri firstedge, lastedge;
5348  struct otri deltriright;
5349  struct otri lefttri, righttri;
5350  struct otri leftcasing, rightcasing;
5351  struct osub leftsubseg, rightsubseg;
5352  vertex delvertex;
5353  vertex neworg;
5354  int edgecount;
5355  triangle ptr; /* Temporary variable used by sym(), onext(), and oprev(). */
5356  subseg sptr; /* Temporary variable used by tspivot(). */
5357 
5358  org(*deltri, delvertex);
5359 
5360  vertexdealloc(m, delvertex);
5361 
5362  /* Count the degree of the vertex being deleted. */
5363  onext(*deltri, countingtri);
5364  edgecount = 1;
5365  while (!otriequal(*deltri, countingtri))
5366  {
5367  edgecount++;
5368  onextself(countingtri);
5369  }
5370 
5371  if (edgecount > 3)
5372  {
5373  /* Triangulate the polygon defined by the union of all triangles */
5374  /* adjacent to the vertex being deleted. Check the quality of */
5375  /* the resulting triangles. */
5376  onext(*deltri, firstedge);
5377  oprev(*deltri, lastedge);
5379  m, b, &firstedge, &lastedge, edgecount, 0, !b->nobisect);
5380  }
5381  /* Splice out two triangles. */
5382  lprev(*deltri, deltriright);
5383  dnext(*deltri, lefttri);
5384  sym(lefttri, leftcasing);
5385  oprev(deltriright, righttri);
5386  sym(righttri, rightcasing);
5387  bond(*deltri, leftcasing);
5388  bond(deltriright, rightcasing);
5389  tspivot(lefttri, leftsubseg);
5390  if (leftsubseg.ss != m->dummysub)
5391  {
5392  tsbond(*deltri, leftsubseg);
5393  }
5394  tspivot(righttri, rightsubseg);
5395  if (rightsubseg.ss != m->dummysub)
5396  {
5397  tsbond(deltriright, rightsubseg);
5398  }
5399 
5400  /* Set the new origin of `deltri' and check its quality. */
5401  org(lefttri, neworg);
5402  setorg(*deltri, neworg);
5403  if (!b->nobisect)
5404  {
5405  testtriangle(m, b, deltri);
5406  }
5407 
5408  /* Delete the two spliced-out triangles. */
5409  triangledealloc(m, lefttri.tri);
5410  triangledealloc(m, righttri.tri);
5411 }
#define onextself(otri)
#define bond(otri1, otri2)
void triangulatepolygon(struct mesh *m, struct behavior *b, struct otri *firstedge, struct otri *lastedge, int edgecount, int doflip, int triflaws)
#define otriequal(otri1, otri2)
void triangledealloc(struct mesh *m, triangle *dyingtriangle)
#define setorg(otri, vertexptr)
#define sym(otri1, otri2)
void testtriangle(struct mesh *m, struct behavior *b, struct otri *testtri)
void vertexdealloc(struct mesh *m, vertex dyingvertex)
#define tsbond(otri, osub)
#define lprev(otri1, otri2)
#define dnext(otri1, otri2)
#define onext(otri1, otri2)
#define oprev(otri1, otri2)
#define tspivot(otri, osub)
#define org(otri, vertexptr)
struct badtriang * Nektar::NekMeshUtils::DelaunayTriangle::dequeuebadtriang ( struct mesh m)
private

Definition at line 3560 of file Triangle/Triangle.cpp.

References Nektar::NekMeshUtils::mesh::firstnonemptyq, Nektar::NekMeshUtils::mesh::nextnonemptyq, Nektar::NekMeshUtils::badtriang::nexttriang, Nektar::NekMeshUtils::mesh::queuefront, and Nektar::NekMeshUtils::mesh::queuetail.

Referenced by enforcequality().

3561 {
3562  struct badtriang *result;
3563 
3564  /* If no queues are nonempty, return NULL. */
3565  if (m->firstnonemptyq < 0)
3566  {
3567  return (struct badtriang *)NULL;
3568  }
3569  /* Find the first triangle of the highest-priority queue. */
3570  result = m->queuefront[m->firstnonemptyq];
3571  /* Remove the triangle from the queue. */
3572  m->queuefront[m->firstnonemptyq] = result->nexttriang;
3573  /* If this queue is now empty, note the new highest-priority */
3574  /* nonempty queue. */
3575  if (result == m->queuetail[m->firstnonemptyq])
3576  {
3577  m->firstnonemptyq = m->nextnonemptyq[m->firstnonemptyq];
3578  }
3579  return result;
3580 }
long Nektar::NekMeshUtils::DelaunayTriangle::divconqdelaunay ( struct mesh m,
struct behavior b 
)
private

Definition at line 6359 of file Triangle/Triangle.cpp.

References alternateaxes(), divconqrecurse(), Nektar::NekMeshUtils::mesh::invertices, removeghosts(), setvertextype, traversalinit(), trifree(), trimalloc(), Nektar::NekMeshUtils::mesh::undeads, UNDEADVERTEX, vertexsort(), vertextraverse(), and Nektar::NekMeshUtils::mesh::vertices.

Referenced by delaunay().

6360 {
6361  vertex *sortarray;
6362  struct otri hullleft, hullright;
6363  int divider;
6364  int i, j;
6365 
6366  /* Allocate an array of pointers to vertices for sorting. */
6367  sortarray = (vertex *)trimalloc(m->invertices * (int)sizeof(vertex));
6368  traversalinit(&m->vertices);
6369  for (i = 0; i < m->invertices; i++)
6370  {
6371  sortarray[i] = vertextraverse(m);
6372  }
6373  /* Sort the vertices. */
6374  vertexsort(sortarray, m->invertices);
6375  /* Discard duplicate vertices, which can really mess up the algorithm. */
6376  i = 0;
6377  for (j = 1; j < m->invertices; j++)
6378  {
6379  if ((sortarray[i][0] == sortarray[j][0]) &&
6380  (sortarray[i][1] == sortarray[j][1]))
6381  {
6382  setvertextype(sortarray[j], UNDEADVERTEX);
6383  m->undeads++;
6384  }
6385  else
6386  {
6387  i++;
6388  sortarray[i] = sortarray[j];
6389  }
6390  }
6391  i++;
6392 
6393  /* Re-sort the array of vertices to accommodate alternating cuts. */
6394  divider = i >> 1;
6395  if (i - divider >= 2)
6396  {
6397  if (divider >= 2)
6398  {
6399  alternateaxes(sortarray, divider, 1);
6400  }
6401  alternateaxes(&sortarray[divider], i - divider, 1);
6402  }
6403 
6404  /* Form the Delaunay triangulation. */
6405  divconqrecurse(m, b, sortarray, i, 0, &hullleft, &hullright);
6406  trifree((void *)sortarray);
6407 
6408  return removeghosts(m, b, &hullleft);
6409 }
void alternateaxes(vertex *sortarray, int arraysize, int axis)
void vertexsort(vertex *sortarray, unsigned int arraysize)
#define UNDEADVERTEX
#define setvertextype(vx, value)
void traversalinit(struct memorypool *pool)
long removeghosts(struct mesh *m, struct behavior *b, struct otri *startghost)
void divconqrecurse(struct mesh *m, struct behavior *b, vertex *sortarray, int vertices, int axis, struct otri *farleft, struct otri *farright)
void Nektar::NekMeshUtils::DelaunayTriangle::divconqrecurse ( struct mesh m,
struct behavior b,
vertex sortarray,
int  vertices,
int  axis,
struct otri farleft,
struct otri farright 
)
private

Definition at line 6145 of file Triangle/Triangle.cpp.

References bond, counterclockwise(), lnext, lnextself, lprev, lprevself, maketriangle(), mergehulls(), otricopy, setapex, setdest, and setorg.

Referenced by divconqdelaunay().

6152 {
6153  struct otri midtri, tri1, tri2, tri3;
6154  struct otri innerleft, innerright;
6155  double area;
6156  int divider;
6157 
6158  if (vertices == 2)
6159  {
6160  /* The triangulation of two vertices is an edge. An edge is */
6161  /* represented by two bounding triangles. */
6162  maketriangle(m, b, farleft);
6163  setorg(*farleft, sortarray[0]);
6164  setdest(*farleft, sortarray[1]);
6165  /* The apex is intentionally left NULL. */
6166  maketriangle(m, b, farright);
6167  setorg(*farright, sortarray[1]);
6168  setdest(*farright, sortarray[0]);
6169  /* The apex is intentionally left NULL. */
6170  bond(*farleft, *farright);
6171  lprevself(*farleft);
6172  lnextself(*farright);
6173  bond(*farleft, *farright);
6174  lprevself(*farleft);
6175  lnextself(*farright);
6176  bond(*farleft, *farright);
6177 
6178  /* Ensure that the origin of `farleft' is sortarray[0]. */
6179  lprev(*farright, *farleft);
6180  return;
6181  }
6182  else if (vertices == 3)
6183  {
6184  /* The triangulation of three vertices is either a triangle (with */
6185  /* three bounding triangles) or two edges (with four bounding */
6186  /* triangles). In either case, four triangles are created. */
6187  maketriangle(m, b, &midtri);
6188  maketriangle(m, b, &tri1);
6189  maketriangle(m, b, &tri2);
6190  maketriangle(m, b, &tri3);
6191  area = counterclockwise(m, b, sortarray[0], sortarray[1], sortarray[2]);
6192  if (area == 0.0)
6193  {
6194  /* Three collinear vertices; the triangulation is two edges. */
6195  setorg(midtri, sortarray[0]);
6196  setdest(midtri, sortarray[1]);
6197  setorg(tri1, sortarray[1]);
6198  setdest(tri1, sortarray[0]);
6199  setorg(tri2, sortarray[2]);
6200  setdest(tri2, sortarray[1]);
6201  setorg(tri3, sortarray[1]);
6202  setdest(tri3, sortarray[2]);
6203  /* All apices are intentionally left NULL. */
6204  bond(midtri, tri1);
6205  bond(tri2, tri3);
6206  lnextself(midtri);
6207  lprevself(tri1);
6208  lnextself(tri2);
6209  lprevself(tri3);
6210  bond(midtri, tri3);
6211  bond(tri1, tri2);
6212  lnextself(midtri);
6213  lprevself(tri1);
6214  lnextself(tri2);
6215  lprevself(tri3);
6216  bond(midtri, tri1);
6217  bond(tri2, tri3);
6218  /* Ensure that the origin of `farleft' is sortarray[0]. */
6219  otricopy(tri1, *farleft);
6220  /* Ensure that the destination of `farright' is sortarray[2]. */
6221  otricopy(tri2, *farright);
6222  }
6223  else
6224  {
6225  /* The three vertices are not collinear; the triangulation is one */
6226  /* triangle, namely `midtri'. */
6227  setorg(midtri, sortarray[0]);
6228  setdest(tri1, sortarray[0]);
6229  setorg(tri3, sortarray[0]);
6230  /* Apices of tri1, tri2, and tri3 are left NULL. */
6231  if (area > 0.0)
6232  {
6233  /* The vertices are in counterclockwise order. */
6234  setdest(midtri, sortarray[1]);
6235  setorg(tri1, sortarray[1]);
6236  setdest(tri2, sortarray[1]);
6237  setapex(midtri, sortarray[2]);
6238  setorg(tri2, sortarray[2]);
6239  setdest(tri3, sortarray[2]);
6240  }
6241  else
6242  {
6243  /* The vertices are in clockwise order. */
6244  setdest(midtri, sortarray[2]);
6245  setorg(tri1, sortarray[2]);
6246  setdest(tri2, sortarray[2]);
6247  setapex(midtri, sortarray[1]);
6248  setorg(tri2, sortarray[1]);
6249  setdest(tri3, sortarray[1]);
6250  }
6251  /* The topology does not depend on how the vertices are ordered. */
6252  bond(midtri, tri1);
6253  lnextself(midtri);
6254  bond(midtri, tri2);
6255  lnextself(midtri);
6256  bond(midtri, tri3);
6257  lprevself(tri1);
6258  lnextself(tri2);
6259  bond(tri1, tri2);
6260  lprevself(tri1);
6261  lprevself(tri3);
6262  bond(tri1, tri3);
6263  lnextself(tri2);
6264  lprevself(tri3);
6265  bond(tri2, tri3);
6266  /* Ensure that the origin of `farleft' is sortarray[0]. */
6267  otricopy(tri1, *farleft);
6268  /* Ensure that the destination of `farright' is sortarray[2]. */
6269  if (area > 0.0)
6270  {
6271  otricopy(tri2, *farright);
6272  }
6273  else
6274  {
6275  lnext(*farleft, *farright);
6276  }
6277  }
6278 
6279  return;
6280  }
6281  else
6282  {
6283  /* Split the vertices in half. */
6284  divider = vertices >> 1;
6285  /* Recursively triangulate each half. */
6286  divconqrecurse(m, b, sortarray, divider, 1 - axis, farleft, &innerleft);
6287  divconqrecurse(m,
6288  b,
6289  &sortarray[divider],
6290  vertices - divider,
6291  1 - axis,
6292  &innerright,
6293  farright);
6294 
6295  /* Merge the two triangulations into one. */
6296  mergehulls(m, b, farleft, &innerleft, &innerright, farright, axis);
6297  }
6298 }
#define setdest(otri, vertexptr)
#define bond(otri1, otri2)
#define setapex(otri, vertexptr)
void maketriangle(struct mesh *m, struct behavior *b, struct otri *newotri)
#define setorg(otri, vertexptr)
#define lprev(otri1, otri2)
#define lnextself(otri)
void mergehulls(struct mesh *m, struct behavior *b, struct otri *farleft, struct otri *innerleft, struct otri *innerright, struct otri *farright, int axis)
void divconqrecurse(struct mesh *m, struct behavior *b, vertex *sortarray, int vertices, int axis, struct otri *farleft, struct otri *farright)
double counterclockwise(struct mesh *m, struct behavior *b, vertex pa, vertex pb, vertex pc)
#define lprevself(otri)
#define otricopy(otri1, otri2)
#define lnext(otri1, otri2)
void Nektar::NekMeshUtils::DelaunayTriangle::dummyinit ( struct mesh m,
struct behavior b,
int  trianglebytes,
int  subsegbytes 
)
private

Definition at line 871 of file Triangle/Triangle.cpp.

References Nektar::NekMeshUtils::memorypool::alignbytes, Nektar::NekMeshUtils::mesh::dummysub, Nektar::NekMeshUtils::mesh::dummysubbase, Nektar::NekMeshUtils::mesh::dummytri, Nektar::NekMeshUtils::mesh::dummytribase, Nektar::NekMeshUtils::mesh::subsegs, Nektar::NekMeshUtils::mesh::triangles, trimalloc(), and Nektar::NekMeshUtils::behavior::usesegments.

Referenced by initializetrisubpools().

875 {
876  unsigned long alignptr;
877 
878  /* Set up `dummytri', the `triangle' that occupies "outer space." */
879  m->dummytribase =
880  (triangle *)trimalloc(trianglebytes + m->triangles.alignbytes);
881  /* Align `dummytri' on a `triangles.alignbytes'-byte boundary. */
882  alignptr = (unsigned long)m->dummytribase;
883  m->dummytri =
884  (triangle *)(alignptr + (unsigned long)m->triangles.alignbytes -
885  (alignptr % (unsigned long)m->triangles.alignbytes));
886  /* Initialize the three adjoining triangles to be "outer space." These */
887  /* will eventually be changed by various bonding operations, but their */
888  /* values don't really matter, as long as they can legally be */
889  /* dereferenced. */
890  m->dummytri[0] = (triangle)m->dummytri;
891  m->dummytri[1] = (triangle)m->dummytri;
892  m->dummytri[2] = (triangle)m->dummytri;
893  /* Three NULL vertices. */
894  m->dummytri[3] = (triangle)NULL;
895  m->dummytri[4] = (triangle)NULL;
896  m->dummytri[5] = (triangle)NULL;
897 
898  if (b->usesegments)
899  {
900  /* Set up `dummysub', the omnipresent subsegment pointed to by any */
901  /* triangle side or subsegment end that isn't attached to a double */
902  /* subsegment. */
903  m->dummysubbase =
904  (subseg *)trimalloc(subsegbytes + m->subsegs.alignbytes);
905  /* Align `dummysub' on a `subsegs.alignbytes'-byte boundary. */
906  alignptr = (unsigned long)m->dummysubbase;
907  m->dummysub =
908  (subseg *)(alignptr + (unsigned long)m->subsegs.alignbytes -
909  (alignptr % (unsigned long)m->subsegs.alignbytes));
910  /* Initialize the two adjoining subsegments to be the omnipresent */
911  /* subsegment. These will eventually be changed by various bonding */
912  /* operations, but their values don't really matter, as long as they
913  */
914  /* can legally be dereferenced. */
915  m->dummysub[0] = (subseg)m->dummysub;
916  m->dummysub[1] = (subseg)m->dummysub;
917  /* Four NULL vertices. */
918  m->dummysub[2] = (subseg)NULL;
919  m->dummysub[3] = (subseg)NULL;
920  m->dummysub[4] = (subseg)NULL;
921  m->dummysub[5] = (subseg)NULL;
922  /* Initialize the two adjoining triangles to be "outer space." */
923  m->dummysub[6] = (subseg)m->dummytri;
924  m->dummysub[7] = (subseg)m->dummytri;
925  /* Set the boundary marker to zero. */
926  *(int *)(m->dummysub + 8) = 0;
927 
928  /* Initialize the three adjoining subsegments of `dummytri' to be */
929  /* the omnipresent subsegment. */
930  m->dummytri[6] = (triangle)m->dummysub;
931  m->dummytri[7] = (triangle)m->dummysub;
932  m->dummytri[8] = (triangle)m->dummysub;
933  }
934 }
void Nektar::NekMeshUtils::DelaunayTriangle::enforcequality ( struct mesh m,
struct behavior b 
)
private

Definition at line 8354 of file Triangle/Triangle.cpp.

References BADSUBSEGPERBLOCK, Nektar::NekMeshUtils::mesh::badsubsegs, Nektar::NekMeshUtils::mesh::badtriangles, BADTRIPERBLOCK, Nektar::NekMeshUtils::mesh::checkquality, dequeuebadtriang(), enqueuebadtriang(), Nektar::NekMeshUtils::mesh::firstnonemptyq, FLIPSTACKERPERBLOCK, Nektar::NekMeshUtils::mesh::flipstackers, Nektar::NekMeshUtils::memorypool::items, Nektar::NekMeshUtils::behavior::minangle, pooldealloc(), poolinit(), Nektar::NekMeshUtils::mesh::queuefront, splitencsegs(), splittriangle(), Nektar::NekMeshUtils::mesh::steinerleft, tallyencs(), tallyfaces(), and Nektar::NekMeshUtils::behavior::usertest.

Referenced by triangulate().

8355 {
8356  struct badtriang *badtri;
8357  int i;
8358 
8359  /* Initialize the pool of encroached subsegments. */
8360  poolinit(&m->badsubsegs,
8361  sizeof(struct badsubseg),
8364  0);
8365 
8366  /* Test all segments to see if they're encroached. */
8367  tallyencs(m, b);
8368 
8369  /* Fix encroached subsegments without noting bad triangles. */
8370  splitencsegs(m, b, 0);
8371  /* At this point, if we haven't run out of Steiner points, the */
8372  /* triangulation should be (conforming) Delaunay. */
8373 
8374  /* Next, we worry about enforcing triangle quality. */
8375  if ((b->minangle > 0.0) || b->usertest)
8376  {
8377  /* Initialize the pool of bad triangles. */
8378  poolinit(&m->badtriangles,
8379  sizeof(struct badtriang),
8382  0);
8383  /* Initialize the queues of bad triangles. */
8384  for (i = 0; i < 4096; i++)
8385  {
8386  m->queuefront[i] = (struct badtriang *)NULL;
8387  }
8388  m->firstnonemptyq = -1;
8389  /* Test all triangles to see if they're bad. */
8390  tallyfaces(m, b);
8391  /* Initialize the pool of recently flipped triangles. */
8392  poolinit(&m->flipstackers,
8393  sizeof(struct flipstacker),
8396  0);
8397  m->checkquality = 1;
8398 
8399  while ((m->badtriangles.items > 0) && (m->steinerleft != 0))
8400  {
8401  /* Fix one bad triangle by inserting a vertex at its circumcenter.
8402  */
8403  badtri = dequeuebadtriang(m);
8404  splittriangle(m, b, badtri);
8405  if (m->badsubsegs.items > 0)
8406  {
8407  /* Put bad triangle back in queue for another try later. */
8408  enqueuebadtriang(m, b, badtri);
8409  /* Fix any encroached subsegments that resulted. */
8410  /* Record any new bad triangles that result. */
8411  splitencsegs(m, b, 1);
8412  }
8413  else
8414  {
8415  /* Return the bad triangle to the pool. */
8416  pooldealloc(&m->badtriangles, (void *)badtri);
8417  }
8418  }
8419  }
8420  /* At this point, if the "-D" switch was selected and we haven't run out */
8421  /* of Steiner points, the triangulation should be (conforming) Delaunay */
8422  /* and have no low-quality triangles. */
8423 
8424 }
struct badtriang * dequeuebadtriang(struct mesh *m)
void tallyencs(struct mesh *m, struct behavior *b)
void poolinit(struct memorypool *pool, int bytecount, int itemcount, int firstitemcount, int alignment)
void enqueuebadtriang(struct mesh *m, struct behavior *b, struct badtriang *badtri)
#define BADTRIPERBLOCK
#define FLIPSTACKERPERBLOCK
void splittriangle(struct mesh *m, struct behavior *b, struct badtriang *badtri)
void splitencsegs(struct mesh *m, struct behavior *b, int triflaws)
void tallyfaces(struct mesh *m, struct behavior *b)
#define BADSUBSEGPERBLOCK
void pooldealloc(struct memorypool *pool, void *dyingitem)
void Nektar::NekMeshUtils::DelaunayTriangle::enqueuebadtri ( struct mesh m,
struct behavior b,
struct otri enqtri,
double  minedge,
vertex  enqapex,
vertex  enqorg,
vertex  enqdest 
)
private

Definition at line 3534 of file Triangle/Triangle.cpp.

References Nektar::NekMeshUtils::mesh::badtriangles, encode, enqueuebadtriang(), Nektar::NekMeshUtils::badtriang::key, poolalloc(), Nektar::NekMeshUtils::badtriang::poortri, Nektar::NekMeshUtils::badtriang::triangapex, Nektar::NekMeshUtils::badtriang::triangdest, and Nektar::NekMeshUtils::badtriang::triangorg.

Referenced by testtriangle().

3541 {
3542  struct badtriang *newbad;
3543 
3544  /* Allocate space for the bad triangle. */
3545  newbad = (struct badtriang *)poolalloc(&m->badtriangles);
3546  newbad->poortri = encode(*enqtri);
3547  newbad->key = minedge;
3548  newbad->triangapex = enqapex;
3549  newbad->triangorg = enqorg;
3550  newbad->triangdest = enqdest;
3551  enqueuebadtriang(m, b, newbad);
3552 }
void * poolalloc(struct memorypool *pool)
void enqueuebadtriang(struct mesh *m, struct behavior *b, struct badtriang *badtri)
#define encode(otri)
void Nektar::NekMeshUtils::DelaunayTriangle::enqueuebadtriang ( struct mesh m,
struct behavior b,
struct badtriang badtri 
)
private

Definition at line 3431 of file Triangle/Triangle.cpp.

References Nektar::NekMeshUtils::mesh::firstnonemptyq, Nektar::NekMeshUtils::badtriang::key, Nektar::NekMeshUtils::mesh::nextnonemptyq, Nektar::NekMeshUtils::badtriang::nexttriang, Nektar::NekMeshUtils::mesh::queuefront, Nektar::NekMeshUtils::mesh::queuetail, and SQUAREROOTTWO.

Referenced by enforcequality(), and enqueuebadtri().

3434 {
3435  double length, multiplier;
3436  int exponent, expincrement;
3437  int queuenumber;
3438  int posexponent;
3439  int i;
3440 
3441  /* Determine the appropriate queue to put the bad triangle into. */
3442  /* Recall that the key is the square of its shortest edge length. */
3443  if (badtri->key >= 1.0)
3444  {
3445  length = badtri->key;
3446  posexponent = 1;
3447  }
3448  else
3449  {
3450  /* `badtri->key' is 2.0 to a negative exponent, so we'll record that */
3451  /* fact and use the reciprocal of `badtri->key', which is > 1.0. */
3452  length = 1.0 / badtri->key;
3453  posexponent = 0;
3454  }
3455  /* `length' is approximately 2.0 to what exponent? The following code */
3456  /* determines the answer in time logarithmic in the exponent. */
3457  exponent = 0;
3458  while (length > 2.0)
3459  {
3460  /* Find an approximation by repeated squaring of two. */
3461  expincrement = 1;
3462  multiplier = 0.5;
3463  while (length * multiplier * multiplier > 1.0)
3464  {
3465  expincrement *= 2;
3466  multiplier *= multiplier;
3467  }
3468  /* Reduce the value of `length', then iterate if necessary. */
3469  exponent += expincrement;
3470  length *= multiplier;
3471  }
3472  /* `length' is approximately squareroot(2.0) to what exponent? */
3473  exponent = 2.0 * exponent + (length > SQUAREROOTTWO);
3474  /* `exponent' is now in the range 0...2047 for IEEE double precision. */
3475  /* Choose a queue in the range 0...4095. The shortest edges have the */
3476  /* highest priority (queue 4095). */
3477  if (posexponent)
3478  {
3479  queuenumber = 2047 - exponent;
3480  }
3481  else
3482  {
3483  queuenumber = 2048 + exponent;
3484  }
3485 
3486  /* Are we inserting into an empty queue? */
3487  if (m->queuefront[queuenumber] == (struct badtriang *)NULL)
3488  {
3489  /* Yes, we are inserting into an empty queue. */
3490  /* Will this become the highest-priority queue? */
3491  if (queuenumber > m->firstnonemptyq)
3492  {
3493  /* Yes, this is the highest-priority queue. */
3494  m->nextnonemptyq[queuenumber] = m->firstnonemptyq;
3495  m->firstnonemptyq = queuenumber;
3496  }
3497  else
3498  {
3499  /* No, this is not the highest-priority queue. */
3500  /* Find the queue with next higher priority. */
3501  i = queuenumber + 1;
3502  while (m->queuefront[i] == (struct badtriang *)NULL)
3503  {
3504  i++;
3505  }
3506  /* Mark the newly nonempty queue as following a higher-priority
3507  * queue. */
3508  m->nextnonemptyq[queuenumber] = m->nextnonemptyq[i];
3509  m->nextnonemptyq[i] = queuenumber;
3510  }
3511  /* Put the bad triangle at the beginning of the (empty) queue. */
3512  m->queuefront[queuenumber] = badtri;
3513  }
3514  else
3515  {
3516  /* Add the bad triangle to the end of an already nonempty queue. */
3517  m->queuetail[queuenumber]->nexttriang = badtri;
3518  }
3519  /* Maintain a pointer to the last triangle of the queue. */
3520  m->queuetail[queuenumber] = badtri;
3521  /* Newly enqueued bad triangle has no successor in the queue. */
3522  badtri->nexttriang = (struct badtriang *)NULL;
3523 }
#define SQUAREROOTTWO
double Nektar::NekMeshUtils::DelaunayTriangle::estimateTRI ( int  elen,
double *  e 
)
private

Definition at line 1682 of file Triangle/Triangle.cpp.

Referenced by counterclockwiseadapt(), incircleadaptTRI(), and orient3dadapt().

1683 {
1684  double Q;
1685  int eindex;
1686 
1687  Q = e[0];
1688  for (eindex = 1; eindex < elen; eindex++)
1689  {
1690  Q += e[eindex];
1691  }
1692  return Q;
1693 }
void Nektar::NekMeshUtils::DelaunayTriangle::exactinit ( )
private

Definition at line 1473 of file Triangle/Triangle.cpp.

References ccwerrboundA, ccwerrboundB, ccwerrboundC, epsilon, iccerrboundA, iccerrboundB, iccerrboundC, o3derrboundA, o3derrboundB, o3derrboundC, resulterrbound, and splitter.

Referenced by triangleinit().

1474 {
1475  double half;
1476  double check, lastcheck;
1477  int every_other;
1478 
1479  every_other = 1;
1480  half = 0.5;
1481  epsilon = 1.0;
1482  splitter = 1.0;
1483  check = 1.0;
1484  /* Repeatedly divide `epsilon' by two until it is too small to add to */
1485  /* one without causing roundoff. (Also check if the sum is equal to */
1486  /* the previous sum, for machines that round up instead of using exact */
1487  /* rounding. Not that these routines will work on such machines.) */
1488  do
1489  {
1490  lastcheck = check;
1491  epsilon *= half;
1492  if (every_other)
1493  {
1494  splitter *= 2.0;
1495  }
1496  every_other = !every_other;
1497  check = 1.0 + epsilon;
1498  } while ((check != 1.0) && (check != lastcheck));
1499  splitter += 1.0;
1500  /* Error bounds for orientation and incircle tests. */
1501  resulterrbound = (3.0 + 8.0 * epsilon) * epsilon;
1502  ccwerrboundA = (3.0 + 16.0 * epsilon) * epsilon;
1503  ccwerrboundB = (2.0 + 12.0 * epsilon) * epsilon;
1504  ccwerrboundC = (9.0 + 64.0 * epsilon) * epsilon * epsilon;
1505  iccerrboundA = (10.0 + 96.0 * epsilon) * epsilon;
1506  iccerrboundB = (4.0 + 48.0 * epsilon) * epsilon;
1507  iccerrboundC = (44.0 + 576.0 * epsilon) * epsilon * epsilon;
1508  o3derrboundA = (7.0 + 56.0 * epsilon) * epsilon;
1509  o3derrboundB = (3.0 + 28.0 * epsilon) * epsilon;
1510  o3derrboundC = (26.0 + 288.0 * epsilon) * epsilon * epsilon;
1511 }
int Nektar::NekMeshUtils::DelaunayTriangle::fast_expansion_sum_zeroelimTRI ( int  elen,
double *  e,
int  flen,
double *  f,
double *  h 
)
private

Definition at line 1527 of file Triangle/Triangle.cpp.

References Fast_Two_Sum, and Two_Sum.

Referenced by counterclockwiseadapt(), incircleadaptTRI(), and orient3dadapt().

1529 {
1530  double Q;
1531  double Qnew;
1532  double hh;
1533  double bvirt;
1534  double avirt, bround, around;
1535  int eindex, findex, hindex;
1536  double enow, fnow;
1537 
1538  enow = e[0];
1539  fnow = f[0];
1540  eindex = findex = 0;
1541  if ((fnow > enow) == (fnow > -enow))
1542  {
1543  Q = enow;
1544  enow = e[++eindex];
1545  }
1546  else
1547  {
1548  Q = fnow;
1549  fnow = f[++findex];
1550  }
1551  hindex = 0;
1552  if ((eindex < elen) && (findex < flen))
1553  {
1554  if ((fnow > enow) == (fnow > -enow))
1555  {
1556  Fast_Two_Sum(enow, Q, Qnew, hh);
1557  enow = e[++eindex];
1558  }
1559  else
1560  {
1561  Fast_Two_Sum(fnow, Q, Qnew, hh);
1562  fnow = f[++findex];
1563  }
1564  Q = Qnew;
1565  if (hh != 0.0)
1566  {
1567  h[hindex++] = hh;
1568  }
1569  while ((eindex < elen) && (findex < flen))
1570  {
1571  if ((fnow > enow) == (fnow > -enow))
1572  {
1573  Two_Sum(Q, enow, Qnew, hh);
1574  enow = e[++eindex];
1575  }
1576  else
1577  {
1578  Two_Sum(Q, fnow, Qnew, hh);
1579  fnow = f[++findex];
1580  }
1581  Q = Qnew;
1582  if (hh != 0.0)
1583  {
1584  h[hindex++] = hh;
1585  }
1586  }
1587  }
1588  while (eindex < elen)
1589  {
1590  Two_Sum(Q, enow, Qnew, hh);
1591  enow = e[++eindex];
1592  Q = Qnew;
1593  if (hh != 0.0)
1594  {
1595  h[hindex++] = hh;
1596  }
1597  }
1598  while (findex < flen)
1599  {
1600  Two_Sum(Q, fnow, Qnew, hh);
1601  fnow = f[++findex];
1602  Q = Qnew;
1603  if (hh != 0.0)
1604  {
1605  h[hindex++] = hh;
1606  }
1607  }
1608  if ((Q != 0.0) || (hindex == 0))
1609  {
1610  h[hindex++] = Q;
1611  }
1612  return hindex;
1613 }
#define Fast_Two_Sum(a, b, x, y)
#define Two_Sum(a, b, x, y)
void Nektar::NekMeshUtils::DelaunayTriangle::findcircumcenter ( struct mesh m,
struct behavior b,
vertex  torg,
vertex  tdest,
vertex  tapex,
vertex  circumcenter,
double *  xi,
double *  eta,
int  offcenter 
)
private

Definition at line 3266 of file Triangle/Triangle.cpp.

References Nektar::NekMeshUtils::mesh::circumcentercount, Nektar::NekMeshUtils::mesh::counterclockcount, counterclockwise(), and Nektar::NekMeshUtils::behavior::offconstant.

Referenced by splittriangle().

3275 {
3276  double xdo, ydo, xao, yao;
3277  double dodist, aodist, dadist;
3278  double denominator;
3279  double dx, dy, dxoff, dyoff;
3280 
3281  m->circumcentercount++;
3282 
3283  /* Compute the circumcenter of the triangle. */
3284  xdo = tdest[0] - torg[0];
3285  ydo = tdest[1] - torg[1];
3286  xao = tapex[0] - torg[0];
3287  yao = tapex[1] - torg[1];
3288  dodist = xdo * xdo + ydo * ydo;
3289  aodist = xao * xao + yao * yao;
3290  dadist = (tdest[0] - tapex[0]) * (tdest[0] - tapex[0]) +
3291  (tdest[1] - tapex[1]) * (tdest[1] - tapex[1]);
3292 
3293  /* Use the counterclockwise() routine to ensure a positive (and */
3294  /* reasonably accurate) result, avoiding any possibility of */
3295  /* division by zero. */
3296  denominator = 0.5 / counterclockwise(m, b, tdest, tapex, torg);
3297  /* Don't count the above as an orientation test. */
3298  m->counterclockcount--;
3299 
3300  dx = (yao * dodist - ydo * aodist) * denominator;
3301  dy = (xdo * aodist - xao * dodist) * denominator;
3302 
3303  /* Find the (squared) length of the triangle's shortest edge. This */
3304  /* serves as a conservative estimateTRI of the insertion radius of the */
3305  /* circumcenter's parent. The estimateTRI is used to ensure that */
3306  /* the algorithm terminates even if very small angles appear in */
3307  /* the input PSLG. */
3308  if ((dodist < aodist) && (dodist < dadist))
3309  {
3310  if (offcenter && (b->offconstant > 0.0))
3311  {
3312  /* Find the position of the off-center, as described by Alper Ungor.
3313  */
3314  dxoff = 0.5 * xdo - b->offconstant * ydo;
3315  dyoff = 0.5 * ydo + b->offconstant * xdo;
3316  /* If the off-center is closer to the origin than the */
3317  /* circumcenter, use the off-center instead. */
3318  if (dxoff * dxoff + dyoff * dyoff < dx * dx + dy * dy)
3319  {
3320  dx = dxoff;
3321  dy = dyoff;
3322  }
3323  }
3324  }
3325  else if (aodist < dadist)
3326  {
3327  if (offcenter && (b->offconstant > 0.0))
3328  {
3329  dxoff = 0.5 * xao + b->offconstant * yao;
3330  dyoff = 0.5 * yao - b->offconstant * xao;
3331  /* If the off-center is closer to the origin than the */
3332  /* circumcenter, use the off-center instead. */
3333  if (dxoff * dxoff + dyoff * dyoff < dx * dx + dy * dy)
3334  {
3335  dx = dxoff;
3336  dy = dyoff;
3337  }
3338  }
3339  }
3340  else
3341  {
3342  if (offcenter && (b->offconstant > 0.0))
3343  {
3344  dxoff = 0.5 * (tapex[0] - tdest[0]) -
3345  b->offconstant * (tapex[1] - tdest[1]);
3346  dyoff = 0.5 * (tapex[1] - tdest[1]) +
3347  b->offconstant * (tapex[0] - tdest[0]);
3348  /* If the off-center is closer to the destination than the */
3349  /* circumcenter, use the off-center instead. */
3350  if (dxoff * dxoff + dyoff * dyoff <
3351  (dx - xdo) * (dx - xdo) + (dy - ydo) * (dy - ydo))
3352  {
3353  dx = xdo + dxoff;
3354  dy = ydo + dyoff;
3355  }
3356  }
3357  }
3358 
3359  circumcenter[0] = torg[0] + dx;
3360  circumcenter[1] = torg[1] + dy;
3361 
3362  /* To interpolate vertex attributes for the new vertex inserted at */
3363  /* the circumcenter, define a coordinate system with a xi-axis, */
3364  /* directed from the triangle's origin to its destination, and */
3365  /* an eta-axis, directed from its origin to its apex. */
3366  /* Calculate the xi and eta coordinates of the circumcenter. */
3367  *xi = (yao * dx - xao * dy) * (2.0 * denominator);
3368  *eta = (xdo * dy - ydo * dx) * (2.0 * denominator);
3369 }
double counterclockwise(struct mesh *m, struct behavior *b, vertex pa, vertex pb, vertex pc)
enum finddirectionresult Nektar::NekMeshUtils::DelaunayTriangle::finddirection ( struct mesh m,
struct behavior b,
struct otri searchtri,
vertex  searchpoint 
)
private

Definition at line 6470 of file Triangle/Triangle.cpp.

References apex, counterclockwise(), dest, Nektar::NekMeshUtils::mesh::dummytri, internalerror(), Nektar::NekMeshUtils::LEFTCOLLINEAR, onext, onextself, oprevself, org, Nektar::NekMeshUtils::RIGHTCOLLINEAR, Nektar::NekMeshUtils::otri::tri, and Nektar::NekMeshUtils::WITHIN.

Referenced by conformingedge(), scoutsegment(), and segmentintersection().

6474 {
6475  struct otri checktri;
6476  vertex startvertex;
6477  vertex leftvertex, rightvertex;
6478  double leftccw, rightccw;
6479  int leftflag, rightflag;
6480  triangle ptr; /* Temporary variable used by onext() and oprev(). */
6481 
6482  org(*searchtri, startvertex);
6483  dest(*searchtri, rightvertex);
6484  apex(*searchtri, leftvertex);
6485  /* Is `searchpoint' to the left? */
6486  leftccw = counterclockwise(m, b, searchpoint, startvertex, leftvertex);
6487  leftflag = leftccw > 0.0;
6488  /* Is `searchpoint' to the right? */
6489  rightccw = counterclockwise(m, b, startvertex, searchpoint, rightvertex);
6490  rightflag = rightccw > 0.0;
6491  if (leftflag && rightflag)
6492  {
6493  /* `searchtri' faces directly away from `searchpoint'. We could go left
6494  */
6495  /* or right. Ask whether it's a triangle or a boundary on the left.
6496  */
6497  onext(*searchtri, checktri);
6498  if (checktri.tri == m->dummytri)
6499  {
6500  leftflag = 0;
6501  }
6502  else
6503  {
6504  rightflag = 0;
6505  }
6506  }
6507  while (leftflag)
6508  {
6509  /* Turn left until satisfied. */
6510  onextself(*searchtri);
6511  if (searchtri->tri == m->dummytri)
6512  {
6513  printf("Internal error in finddirection(): Unable to find a\n");
6514  printf(" triangle leading from (%.12g, %.12g) to",
6515  startvertex[0],
6516  startvertex[1]);
6517  printf(" (%.12g, %.12g).\n", searchpoint[0], searchpoint[1]);
6518  internalerror();
6519  }
6520  apex(*searchtri, leftvertex);
6521  rightccw = leftccw;
6522  leftccw = counterclockwise(m, b, searchpoint, startvertex, leftvertex);
6523  leftflag = leftccw > 0.0;
6524  }
6525  while (rightflag)
6526  {
6527  /* Turn right until satisfied. */
6528  oprevself(*searchtri);
6529  if (searchtri->tri == m->dummytri)
6530  {
6531  printf("Internal error in finddirection(): Unable to find a\n");
6532  printf(" triangle leading from (%.12g, %.12g) to",
6533  startvertex[0],
6534  startvertex[1]);
6535  printf(" (%.12g, %.12g).\n", searchpoint[0], searchpoint[1]);
6536  internalerror();
6537  }
6538  dest(*searchtri, rightvertex);
6539  leftccw = rightccw;
6540  rightccw =
6541  counterclockwise(m, b, startvertex, searchpoint, rightvertex);
6542  rightflag = rightccw > 0.0;
6543  }
6544  if (leftccw == 0.0)
6545  {
6546  return LEFTCOLLINEAR;
6547  }
6548  else if (rightccw == 0.0)
6549  {
6550  return RIGHTCOLLINEAR;
6551  }
6552  else
6553  {
6554  return WITHIN;
6555  }
6556 }
#define onextself(otri)
double counterclockwise(struct mesh *m, struct behavior *b, vertex pa, vertex pb, vertex pc)
#define onext(otri1, otri2)
#define apex(otri, vertexptr)
#define oprevself(otri)
#define dest(otri, vertexptr)
#define org(otri, vertexptr)
void Nektar::NekMeshUtils::DelaunayTriangle::flip ( struct mesh m,
struct behavior b,
struct otri flipedge 
)
private

Definition at line 4406 of file Triangle/Triangle.cpp.

References apex, bond, Nektar::NekMeshUtils::mesh::checksegments, dest, Nektar::NekMeshUtils::mesh::dummysub, lnext, lprev, org, setapex, setdest, setorg, Nektar::NekMeshUtils::osub::ss, sym, tsbond, tsdissolve, and tspivot.

Referenced by constrainededge(), delaunayfixup(), and triangulatepolygon().

4407 {
4408  struct otri botleft, botright;
4409  struct otri topleft, topright;
4410  struct otri top;
4411  struct otri botlcasing, botrcasing;
4412  struct otri toplcasing, toprcasing;
4413  struct osub botlsubseg, botrsubseg;
4414  struct osub toplsubseg, toprsubseg;
4415  vertex leftvertex, rightvertex, botvertex;
4416  vertex farvertex;
4417  triangle ptr; /* Temporary variable used by sym(). */
4418  subseg sptr; /* Temporary variable used by tspivot(). */
4419 
4420  /* Identify the vertices of the quadrilateral. */
4421  org(*flipedge, rightvertex);
4422  dest(*flipedge, leftvertex);
4423  apex(*flipedge, botvertex);
4424  sym(*flipedge, top);
4425  apex(top, farvertex);
4426 
4427  /* Identify the casing of the quadrilateral. */
4428  lprev(top, topleft);
4429  sym(topleft, toplcasing);
4430  lnext(top, topright);
4431  sym(topright, toprcasing);
4432  lnext(*flipedge, botleft);
4433  sym(botleft, botlcasing);
4434  lprev(*flipedge, botright);
4435  sym(botright, botrcasing);
4436  /* Rotate the quadrilateral one-quarter turn counterclockwise. */
4437  bond(topleft, botlcasing);
4438  bond(botleft, botrcasing);
4439  bond(botright, toprcasing);
4440  bond(topright, toplcasing);
4441 
4442  if (m->checksegments)
4443  {
4444  /* Check for subsegments and rebond them to the quadrilateral. */
4445  tspivot(topleft, toplsubseg);
4446  tspivot(botleft, botlsubseg);
4447  tspivot(botright, botrsubseg);
4448  tspivot(topright, toprsubseg);
4449  if (toplsubseg.ss == m->dummysub)
4450  {
4451  tsdissolve(topright);
4452  }
4453  else
4454  {
4455  tsbond(topright, toplsubseg);
4456  }
4457  if (botlsubseg.ss == m->dummysub)
4458  {
4459  tsdissolve(topleft);
4460  }
4461  else
4462  {
4463  tsbond(topleft, botlsubseg);
4464  }
4465  if (botrsubseg.ss == m->dummysub)
4466  {
4467  tsdissolve(botleft);
4468  }
4469  else
4470  {
4471  tsbond(botleft, botrsubseg);
4472  }
4473  if (toprsubseg.ss == m->dummysub)
4474  {
4475  tsdissolve(botright);
4476  }
4477  else
4478  {
4479  tsbond(botright, toprsubseg);
4480  }
4481  }
4482 
4483  /* New vertex assignments for the rotated quadrilateral. */
4484  setorg(*flipedge, farvertex);
4485  setdest(*flipedge, botvertex);
4486  setapex(*flipedge, rightvertex);
4487  setorg(top, botvertex);
4488  setdest(top, farvertex);
4489  setapex(top, leftvertex);
4490 }
#define setdest(otri, vertexptr)
#define bond(otri1, otri2)
#define setapex(otri, vertexptr)
#define tsdissolve(otri)
#define setorg(otri, vertexptr)
#define sym(otri1, otri2)
#define tsbond(otri, osub)
#define lprev(otri1, otri2)
#define apex(otri, vertexptr)
#define tspivot(otri, osub)
#define lnext(otri1, otri2)
#define dest(otri, vertexptr)
#define org(otri, vertexptr)
void Nektar::NekMeshUtils::DelaunayTriangle::formskeleton ( struct mesh m,
struct behavior b,
int *  segmentlist,
int *  segmentmarkerlist,
int  numberofsegments 
)
private

Definition at line 7284 of file Triangle/Triangle.cpp.

References getvertex(), Nektar::NekMeshUtils::mesh::insegments, insertsegment(), Nektar::NekMeshUtils::mesh::invertices, Nektar::NekMeshUtils::memorypool::items, makevertexmap(), markhull(), Nektar::NekMeshUtils::behavior::poly, and Nektar::NekMeshUtils::mesh::triangles.

Referenced by triangulate().

7289 {
7290  char polyfilename[6];
7291  int index;
7292  vertex endpoint1, endpoint2;
7293  int segmentmarkers;
7294  int end1, end2;
7295  int boundmarker;
7296  int i;
7297 
7298  if (b->poly)
7299  {
7300  strcpy(polyfilename, "input");
7301  m->insegments = numberofsegments;
7302  segmentmarkers = segmentmarkerlist != (int *)NULL;
7303  index = 0;
7304  /* If the input vertices are collinear, there is no triangulation, */
7305  /* so don't try to insert segments. */
7306  if (m->triangles.items == 0)
7307  {
7308  return;
7309  }
7310 
7311  /* If segments are to be inserted, compute a mapping */
7312  /* from vertices to triangles. */
7313  if (m->insegments > 0)
7314  {
7315  makevertexmap(m, b);
7316 
7317  }
7318 
7319  boundmarker = 0;
7320  /* Read and insert the segments. */
7321  for (i = 0; i < m->insegments; i++)
7322  {
7323  end1 = segmentlist[index++];
7324  end2 = segmentlist[index++];
7325  if (segmentmarkers)
7326  {
7327  boundmarker = segmentmarkerlist[i];
7328  }
7329  if ((end1 < 0) ||
7330  (end1 >= 0 + m->invertices))
7331  {
7332 
7333  }
7334  else if ((end2 < 0) ||
7335  (end2 >= 0 + m->invertices))
7336  {
7337 
7338  }
7339  else
7340  {
7341  /* Find the vertices numbered `end1' and `end2'. */
7342  endpoint1 = getvertex(m, b, end1);
7343  endpoint2 = getvertex(m, b, end2);
7344  if ((endpoint1[0] == endpoint2[0]) &&
7345  (endpoint1[1] == endpoint2[1]))
7346  {
7347 
7348  }
7349  else
7350  {
7351  insertsegment(m, b, endpoint1, endpoint2, boundmarker);
7352  }
7353  }
7354  }
7355  }
7356  else
7357  {
7358  m->insegments = 0;
7359  }
7360  if (!b->poly)
7361  {
7362  /* Enclose the convex hull with subsegments. */
7363 
7364  markhull(m, b);
7365  }
7366 }
void makevertexmap(struct mesh *m, struct behavior *b)
void insertsegment(struct mesh *m, struct behavior *b, vertex endpoint1, vertex endpoint2, int newmark)
vertex getvertex(struct mesh *m, struct behavior *b, int number)
void markhull(struct mesh *m, struct behavior *b)
vertex Nektar::NekMeshUtils::DelaunayTriangle::getvertex ( struct mesh m,
struct behavior b,
int  number 
)
private

Definition at line 1192 of file Triangle/Triangle.cpp.

References Nektar::NekMeshUtils::memorypool::alignbytes, Nektar::NekMeshUtils::memorypool::firstblock, Nektar::NekMeshUtils::memorypool::itembytes, Nektar::NekMeshUtils::memorypool::itemsfirstblock, Nektar::NekMeshUtils::memorypool::itemsperblock, and Nektar::NekMeshUtils::mesh::vertices.

Referenced by formskeleton().

1193 {
1194  void **getblock;
1195  char *foundvertex;
1196  unsigned long alignptr;
1197  int current;
1198 
1199  getblock = m->vertices.firstblock;
1200  current = 0;
1201 
1202  /* Find the right block. */
1203  if (current + m->vertices.itemsfirstblock <= number)
1204  {
1205  getblock = (void **)*getblock;
1206  current += m->vertices.itemsfirstblock;
1207  while (current + m->vertices.itemsperblock <= number)
1208  {
1209  getblock = (void **)*getblock;
1210  current += m->vertices.itemsperblock;
1211  }
1212  }
1213 
1214  /* Now find the right vertex. */
1215  alignptr = (unsigned long)(getblock + 1);
1216  foundvertex = (char *)(alignptr + (unsigned long)m->vertices.alignbytes -
1217  (alignptr % (unsigned long)m->vertices.alignbytes));
1218  return (vertex)(foundvertex + m->vertices.itembytes * (number - current));
1219 }
double Nektar::NekMeshUtils::DelaunayTriangle::incircle ( struct mesh m,
struct behavior b,
vertex  pa,
vertex  pb,
vertex  pc,
vertex  pd 
)
private

Definition at line 2531 of file Triangle/Triangle.cpp.

References Absolute, iccerrboundA, incircleadaptTRI(), and Nektar::NekMeshUtils::mesh::incirclecount.

Referenced by delaunayfixup(), insertvertex(), mergehulls(), nonregular(), and triangulatepolygon().

2537 {
2538  double adx, bdx, cdx, ady, bdy, cdy;
2539  double bdxcdy, cdxbdy, cdxady, adxcdy, adxbdy, bdxady;
2540  double alift, blift, clift;
2541  double det;
2542  double permanent, errbound;
2543 
2544  m->incirclecount++;
2545 
2546  adx = pa[0] - pd[0];
2547  bdx = pb[0] - pd[0];
2548  cdx = pc[0] - pd[0];
2549  ady = pa[1] - pd[1];
2550  bdy = pb[1] - pd[1];
2551  cdy = pc[1] - pd[1];
2552 
2553  bdxcdy = bdx * cdy;
2554  cdxbdy = cdx * bdy;
2555  alift = adx * adx + ady * ady;
2556 
2557  cdxady = cdx * ady;
2558  adxcdy = adx * cdy;
2559  blift = bdx * bdx + bdy * bdy;
2560 
2561  adxbdy = adx * bdy;
2562  bdxady = bdx * ady;
2563  clift = cdx * cdx + cdy * cdy;
2564 
2565  det = alift * (bdxcdy - cdxbdy) + blift * (cdxady - adxcdy) +
2566  clift * (adxbdy - bdxady);
2567 
2568  permanent = (Absolute(bdxcdy) + Absolute(cdxbdy)) * alift +
2569  (Absolute(cdxady) + Absolute(adxcdy)) * blift +
2570  (Absolute(adxbdy) + Absolute(bdxady)) * clift;
2571  errbound = iccerrboundA * permanent;
2572  if ((det > errbound) || (-det > errbound))
2573  {
2574  return det;
2575  }
2576 
2577  return incircleadaptTRI(pa, pb, pc, pd, permanent);
2578 }
#define Absolute(a)
double incircleadaptTRI(vertex pa, vertex pb, vertex pc, vertex pd, double permanent)
double Nektar::NekMeshUtils::DelaunayTriangle::incircleadaptTRI ( vertex  pa,
vertex  pb,
vertex  pc,
vertex  pd,
double  permanent 
)
private

Definition at line 1864 of file Triangle/Triangle.cpp.

References Absolute, estimateTRI(), fast_expansion_sum_zeroelimTRI(), iccerrboundB, iccerrboundC, Nektar::negate(), resulterrbound, scale_expansion_zeroelimTRI(), Square, Two_Diff_Tail, Two_Product, Two_Two_Diff, and Two_Two_Sum.

Referenced by incircle().

1866 {
1867  double adx, bdx, cdx, ady, bdy, cdy;
1868  double det, errbound;
1869 
1870  double bdxcdy1, cdxbdy1, cdxady1, adxcdy1, adxbdy1, bdxady1;
1871  double bdxcdy0, cdxbdy0, cdxady0, adxcdy0, adxbdy0, bdxady0;
1872  double bc[4], ca[4], ab[4];
1873  double bc3, ca3, ab3;
1874  double axbc[8], axxbc[16], aybc[8], ayybc[16], adet[32];
1875  int axbclen, axxbclen, aybclen, ayybclen, alen;
1876  double bxca[8], bxxca[16], byca[8], byyca[16], bdet[32];
1877  int bxcalen, bxxcalen, bycalen, byycalen, blen;
1878  double cxab[8], cxxab[16], cyab[8], cyyab[16], cdet[32];
1879  int cxablen, cxxablen, cyablen, cyyablen, clen;
1880  double abdet[64];
1881  int ablen;
1882  double fin1[1152], fin2[1152];
1883  double *finnow, *finother, *finswap;
1884  int finlength;
1885 
1886  double adxtail, bdxtail, cdxtail, adytail, bdytail, cdytail;
1887  double adxadx1, adyady1, bdxbdx1, bdybdy1, cdxcdx1, cdycdy1;
1888  double adxadx0, adyady0, bdxbdx0, bdybdy0, cdxcdx0, cdycdy0;
1889  double aa[4], bb[4], cc[4];
1890  double aa3, bb3, cc3;
1891  double ti1, tj1;
1892  double ti0, tj0;
1893  double u[4], v[4];
1894  double u3, v3;
1895  double temp8[8], temp16a[16], temp16b[16], temp16c[16];
1896  double temp32a[32], temp32b[32], temp48[48], temp64[64];
1897  int temp8len, temp16alen, temp16blen, temp16clen;
1898  int temp32alen, temp32blen, temp48len, temp64len;
1899  double axtbb[8], axtcc[8], aytbb[8], aytcc[8];
1900  int axtbblen, axtcclen, aytbblen, aytcclen;
1901  double bxtaa[8], bxtcc[8], bytaa[8], bytcc[8];
1902  int bxtaalen, bxtcclen, bytaalen, bytcclen;
1903  double cxtaa[8], cxtbb[8], cytaa[8], cytbb[8];
1904  int cxtaalen, cxtbblen, cytaalen, cytbblen;
1905  double axtbc[8], aytbc[8], bxtca[8], bytca[8], cxtab[8], cytab[8];
1906  int axtbclen, aytbclen, bxtcalen, bytcalen, cxtablen, cytablen;
1907  double axtbct[16], aytbct[16], bxtcat[16], bytcat[16], cxtabt[16],
1908  cytabt[16];
1909  int axtbctlen, aytbctlen, bxtcatlen, bytcatlen, cxtabtlen, cytabtlen;
1910  double axtbctt[8], aytbctt[8], bxtcatt[8];
1911  double bytcatt[8], cxtabtt[8], cytabtt[8];
1912  int axtbcttlen, aytbcttlen, bxtcattlen, bytcattlen, cxtabttlen, cytabttlen;
1913  double abt[8], bct[8], cat[8];
1914  int abtlen, bctlen, catlen;
1915  double abtt[4], bctt[4], catt[4];
1916  int abttlen, bcttlen, cattlen;
1917  double abtt3, bctt3, catt3;
1918  double negate;
1919 
1920  double bvirt;
1921  double avirt, bround, around;
1922  double c;
1923  double abig;
1924  double ahi, alo, bhi, blo;
1925  double err1, err2, err3;
1926  double _i, _j;
1927  double _0;
1928 
1929  adx = (double)(pa[0] - pd[0]);
1930  bdx = (double)(pb[0] - pd[0]);
1931  cdx = (double)(pc[0] - pd[0]);
1932  ady = (double)(pa[1] - pd[1]);
1933  bdy = (double)(pb[1] - pd[1]);
1934  cdy = (double)(pc[1] - pd[1]);
1935 
1936  Two_Product(bdx, cdy, bdxcdy1, bdxcdy0);
1937  Two_Product(cdx, bdy, cdxbdy1, cdxbdy0);
1938  Two_Two_Diff(bdxcdy1, bdxcdy0, cdxbdy1, cdxbdy0, bc3, bc[2], bc[1], bc[0]);
1939  bc[3] = bc3;
1940  axbclen = scale_expansion_zeroelimTRI(4, bc, adx, axbc);
1941  axxbclen = scale_expansion_zeroelimTRI(axbclen, axbc, adx, axxbc);
1942  aybclen = scale_expansion_zeroelimTRI(4, bc, ady, aybc);
1943  ayybclen = scale_expansion_zeroelimTRI(aybclen, aybc, ady, ayybc);
1944  alen = fast_expansion_sum_zeroelimTRI(axxbclen, axxbc, ayybclen, ayybc, adet);
1945 
1946  Two_Product(cdx, ady, cdxady1, cdxady0);
1947  Two_Product(adx, cdy, adxcdy1, adxcdy0);
1948  Two_Two_Diff(cdxady1, cdxady0, adxcdy1, adxcdy0, ca3, ca[2], ca[1], ca[0]);
1949  ca[3] = ca3;
1950  bxcalen = scale_expansion_zeroelimTRI(4, ca, bdx, bxca);
1951  bxxcalen = scale_expansion_zeroelimTRI(bxcalen, bxca, bdx, bxxca);
1952  bycalen = scale_expansion_zeroelimTRI(4, ca, bdy, byca);
1953  byycalen = scale_expansion_zeroelimTRI(bycalen, byca, bdy, byyca);
1954  blen = fast_expansion_sum_zeroelimTRI(bxxcalen, bxxca, byycalen, byyca, bdet);
1955 
1956  Two_Product(adx, bdy, adxbdy1, adxbdy0);
1957  Two_Product(bdx, ady, bdxady1, bdxady0);
1958  Two_Two_Diff(adxbdy1, adxbdy0, bdxady1, bdxady0, ab3, ab[2], ab[1], ab[0]);
1959  ab[3] = ab3;
1960  cxablen = scale_expansion_zeroelimTRI(4, ab, cdx, cxab);
1961  cxxablen = scale_expansion_zeroelimTRI(cxablen, cxab, cdx, cxxab);
1962  cyablen = scale_expansion_zeroelimTRI(4, ab, cdy, cyab);
1963  cyyablen = scale_expansion_zeroelimTRI(cyablen, cyab, cdy, cyyab);
1964  clen = fast_expansion_sum_zeroelimTRI(cxxablen, cxxab, cyyablen, cyyab, cdet);
1965 
1966  ablen = fast_expansion_sum_zeroelimTRI(alen, adet, blen, bdet, abdet);
1967  finlength = fast_expansion_sum_zeroelimTRI(ablen, abdet, clen, cdet, fin1);
1968 
1969  det = estimateTRI(finlength, fin1);
1970  errbound = iccerrboundB * permanent;
1971  if ((det >= errbound) || (-det >= errbound))
1972  {
1973  return det;
1974  }
1975 
1976  Two_Diff_Tail(pa[0], pd[0], adx, adxtail);
1977  Two_Diff_Tail(pa[1], pd[1], ady, adytail);
1978  Two_Diff_Tail(pb[0], pd[0], bdx, bdxtail);
1979  Two_Diff_Tail(pb[1], pd[1], bdy, bdytail);
1980  Two_Diff_Tail(pc[0], pd[0], cdx, cdxtail);
1981  Two_Diff_Tail(pc[1], pd[1], cdy, cdytail);
1982  if ((adxtail == 0.0) && (bdxtail == 0.0) && (cdxtail == 0.0) &&
1983  (adytail == 0.0) && (bdytail == 0.0) && (cdytail == 0.0))
1984  {
1985  return det;
1986  }
1987 
1988  errbound = iccerrboundC * permanent + resulterrbound * Absolute(det);
1989  det += ((adx * adx + ady * ady) * ((bdx * cdytail + cdy * bdxtail) -
1990  (bdy * cdxtail + cdx * bdytail)) +
1991  2.0 * (adx * adxtail + ady * adytail) * (bdx * cdy - bdy * cdx)) +
1992  ((bdx * bdx + bdy * bdy) * ((cdx * adytail + ady * cdxtail) -
1993  (cdy * adxtail + adx * cdytail)) +
1994  2.0 * (bdx * bdxtail + bdy * bdytail) * (cdx * ady - cdy * adx)) +
1995  ((cdx * cdx + cdy * cdy) * ((adx * bdytail + bdy * adxtail) -
1996  (ady * bdxtail + bdx * adytail)) +
1997  2.0 * (cdx * cdxtail + cdy * cdytail) * (adx * bdy - ady * bdx));
1998  if ((det >= errbound) || (-det >= errbound))
1999  {
2000  return det;
2001  }
2002 
2003  finnow = fin1;
2004  finother = fin2;
2005 
2006  if ((bdxtail != 0.0) || (bdytail != 0.0) || (cdxtail != 0.0) ||
2007  (cdytail != 0.0))
2008  {
2009  Square(adx, adxadx1, adxadx0);
2010  Square(ady, adyady1, adyady0);
2011  Two_Two_Sum(
2012  adxadx1, adxadx0, adyady1, adyady0, aa3, aa[2], aa[1], aa[0]);
2013  aa[3] = aa3;
2014  }
2015  if ((cdxtail != 0.0) || (cdytail != 0.0) || (adxtail != 0.0) ||
2016  (adytail != 0.0))
2017  {
2018  Square(bdx, bdxbdx1, bdxbdx0);
2019  Square(bdy, bdybdy1, bdybdy0);
2020  Two_Two_Sum(
2021  bdxbdx1, bdxbdx0, bdybdy1, bdybdy0, bb3, bb[2], bb[1], bb[0]);
2022  bb[3] = bb3;
2023  }
2024  if ((adxtail != 0.0) || (adytail != 0.0) || (bdxtail != 0.0) ||
2025  (bdytail != 0.0))
2026  {
2027  Square(cdx, cdxcdx1, cdxcdx0);
2028  Square(cdy, cdycdy1, cdycdy0);
2029  Two_Two_Sum(
2030  cdxcdx1, cdxcdx0, cdycdy1, cdycdy0, cc3, cc[2], cc[1], cc[0]);
2031  cc[3] = cc3;
2032  }
2033 
2034  if (adxtail != 0.0)
2035  {
2036  axtbclen = scale_expansion_zeroelimTRI(4, bc, adxtail, axtbc);
2037  temp16alen =
2038  scale_expansion_zeroelimTRI(axtbclen, axtbc, 2.0 * adx, temp16a);
2039 
2040  axtcclen = scale_expansion_zeroelimTRI(4, cc, adxtail, axtcc);
2041  temp16blen = scale_expansion_zeroelimTRI(axtcclen, axtcc, bdy, temp16b);
2042 
2043  axtbblen = scale_expansion_zeroelimTRI(4, bb, adxtail, axtbb);
2044  temp16clen = scale_expansion_zeroelimTRI(axtbblen, axtbb, -cdy, temp16c);
2045 
2046  temp32alen = fast_expansion_sum_zeroelimTRI(
2047  temp16alen, temp16a, temp16blen, temp16b, temp32a);
2048  temp48len = fast_expansion_sum_zeroelimTRI(
2049  temp16clen, temp16c, temp32alen, temp32a, temp48);
2050  finlength = fast_expansion_sum_zeroelimTRI(
2051  finlength, finnow, temp48len, temp48, finother);
2052  finswap = finnow;
2053  finnow = finother;
2054  finother = finswap;
2055  }
2056  if (adytail != 0.0)
2057  {
2058  aytbclen = scale_expansion_zeroelimTRI(4, bc, adytail, aytbc);
2059  temp16alen =
2060  scale_expansion_zeroelimTRI(aytbclen, aytbc, 2.0 * ady, temp16a);
2061 
2062  aytbblen = scale_expansion_zeroelimTRI(4, bb, adytail, aytbb);
2063  temp16blen = scale_expansion_zeroelimTRI(aytbblen, aytbb, cdx, temp16b);
2064 
2065  aytcclen = scale_expansion_zeroelimTRI(4, cc, adytail, aytcc);
2066  temp16clen = scale_expansion_zeroelimTRI(aytcclen, aytcc, -bdx, temp16c);
2067 
2068  temp32alen = fast_expansion_sum_zeroelimTRI(
2069  temp16alen, temp16a, temp16blen, temp16b, temp32a);
2070  temp48len = fast_expansion_sum_zeroelimTRI(
2071  temp16clen, temp16c, temp32alen, temp32a, temp48);
2072  finlength = fast_expansion_sum_zeroelimTRI(
2073  finlength, finnow, temp48len, temp48, finother);
2074  finswap = finnow;
2075  finnow = finother;
2076  finother = finswap;
2077  }
2078  if (bdxtail != 0.0)
2079  {
2080  bxtcalen = scale_expansion_zeroelimTRI(4, ca, bdxtail, bxtca);
2081  temp16alen =
2082  scale_expansion_zeroelimTRI(bxtcalen, bxtca, 2.0 * bdx, temp16a);
2083 
2084  bxtaalen = scale_expansion_zeroelimTRI(4, aa, bdxtail, bxtaa);
2085  temp16blen = scale_expansion_zeroelimTRI(bxtaalen, bxtaa, cdy, temp16b);
2086 
2087  bxtcclen = scale_expansion_zeroelimTRI(4, cc, bdxtail, bxtcc);
2088  temp16clen = scale_expansion_zeroelimTRI(bxtcclen, bxtcc, -ady, temp16c);
2089 
2090  temp32alen = fast_expansion_sum_zeroelimTRI(
2091  temp16alen, temp16a, temp16blen, temp16b, temp32a);
2092  temp48len = fast_expansion_sum_zeroelimTRI(
2093  temp16clen, temp16c, temp32alen, temp32a, temp48);
2094  finlength = fast_expansion_sum_zeroelimTRI(
2095  finlength, finnow, temp48len, temp48, finother);
2096  finswap = finnow;
2097  finnow = finother;
2098  finother = finswap;
2099  }
2100  if (bdytail != 0.0)
2101  {
2102  bytcalen = scale_expansion_zeroelimTRI(4, ca, bdytail, bytca);
2103  temp16alen =
2104  scale_expansion_zeroelimTRI(bytcalen, bytca, 2.0 * bdy, temp16a);
2105 
2106  bytcclen = scale_expansion_zeroelimTRI(4, cc, bdytail, bytcc);
2107  temp16blen = scale_expansion_zeroelimTRI(bytcclen, bytcc, adx, temp16b);
2108 
2109  bytaalen = scale_expansion_zeroelimTRI(4, aa, bdytail, bytaa);
2110  temp16clen = scale_expansion_zeroelimTRI(bytaalen, bytaa, -cdx, temp16c);
2111 
2112  temp32alen = fast_expansion_sum_zeroelimTRI(
2113  temp16alen, temp16a, temp16blen, temp16b, temp32a);
2114  temp48len = fast_expansion_sum_zeroelimTRI(
2115  temp16clen, temp16c, temp32alen, temp32a, temp48);
2116  finlength = fast_expansion_sum_zeroelimTRI(
2117  finlength, finnow, temp48len, temp48, finother);
2118  finswap = finnow;
2119  finnow = finother;
2120  finother = finswap;
2121  }
2122  if (cdxtail != 0.0)
2123  {
2124  cxtablen = scale_expansion_zeroelimTRI(4, ab, cdxtail, cxtab);
2125  temp16alen =
2126  scale_expansion_zeroelimTRI(cxtablen, cxtab, 2.0 * cdx, temp16a);
2127 
2128  cxtbblen = scale_expansion_zeroelimTRI(4, bb, cdxtail, cxtbb);
2129  temp16blen = scale_expansion_zeroelimTRI(cxtbblen, cxtbb, ady, temp16b);
2130 
2131  cxtaalen = scale_expansion_zeroelimTRI(4, aa, cdxtail, cxtaa);
2132  temp16clen = scale_expansion_zeroelimTRI(cxtaalen, cxtaa, -bdy, temp16c);
2133 
2134  temp32alen = fast_expansion_sum_zeroelimTRI(
2135  temp16alen, temp16a, temp16blen, temp16b, temp32a);
2136  temp48len = fast_expansion_sum_zeroelimTRI(
2137  temp16clen, temp16c, temp32alen, temp32a, temp48);
2138  finlength = fast_expansion_sum_zeroelimTRI(
2139  finlength, finnow, temp48len, temp48, finother);
2140  finswap = finnow;
2141  finnow = finother;
2142  finother = finswap;
2143  }
2144  if (cdytail != 0.0)
2145  {
2146  cytablen = scale_expansion_zeroelimTRI(4, ab, cdytail, cytab);
2147  temp16alen =
2148  scale_expansion_zeroelimTRI(cytablen, cytab, 2.0 * cdy, temp16a);
2149 
2150  cytaalen = scale_expansion_zeroelimTRI(4, aa, cdytail, cytaa);
2151  temp16blen = scale_expansion_zeroelimTRI(cytaalen, cytaa, bdx, temp16b);
2152 
2153  cytbblen = scale_expansion_zeroelimTRI(4, bb, cdytail, cytbb);
2154  temp16clen = scale_expansion_zeroelimTRI(cytbblen, cytbb, -adx, temp16c);
2155 
2156  temp32alen = fast_expansion_sum_zeroelimTRI(
2157  temp16alen, temp16a, temp16blen, temp16b, temp32a);
2158  temp48len = fast_expansion_sum_zeroelimTRI(
2159  temp16clen, temp16c, temp32alen, temp32a, temp48);
2160  finlength = fast_expansion_sum_zeroelimTRI(
2161  finlength, finnow, temp48len, temp48, finother);
2162  finswap = finnow;
2163  finnow = finother;
2164  finother = finswap;
2165  }
2166 
2167  if ((adxtail != 0.0) || (adytail != 0.0))
2168  {
2169  if ((bdxtail != 0.0) || (bdytail != 0.0) || (cdxtail != 0.0) ||
2170  (cdytail != 0.0))
2171  {
2172  Two_Product(bdxtail, cdy, ti1, ti0);
2173  Two_Product(bdx, cdytail, tj1, tj0);
2174  Two_Two_Sum(ti1, ti0, tj1, tj0, u3, u[2], u[1], u[0]);
2175  u[3] = u3;
2176  negate = -bdy;
2177  Two_Product(cdxtail, negate, ti1, ti0);
2178  negate = -bdytail;
2179  Two_Product(cdx, negate, tj1, tj0);
2180  Two_Two_Sum(ti1, ti0, tj1, tj0, v3, v[2], v[1], v[0]);
2181  v[3] = v3;
2182  bctlen = fast_expansion_sum_zeroelimTRI(4, u, 4, v, bct);
2183 
2184  Two_Product(bdxtail, cdytail, ti1, ti0);
2185  Two_Product(cdxtail, bdytail, tj1, tj0);
2186  Two_Two_Diff(ti1, ti0, tj1, tj0, bctt3, bctt[2], bctt[1], bctt[0]);
2187  bctt[3] = bctt3;
2188  bcttlen = 4;
2189  }
2190  else
2191  {
2192  bct[0] = 0.0;
2193  bctlen = 1;
2194  bctt[0] = 0.0;
2195  bcttlen = 1;
2196  }
2197 
2198  if (adxtail != 0.0)
2199  {
2200  temp16alen =
2201  scale_expansion_zeroelimTRI(axtbclen, axtbc, adxtail, temp16a);
2202  axtbctlen = scale_expansion_zeroelimTRI(bctlen, bct, adxtail, axtbct);
2203  temp32alen =
2204  scale_expansion_zeroelimTRI(axtbctlen, axtbct, 2.0 * adx, temp32a);
2205  temp48len = fast_expansion_sum_zeroelimTRI(
2206  temp16alen, temp16a, temp32alen, temp32a, temp48);
2207  finlength = fast_expansion_sum_zeroelimTRI(
2208  finlength, finnow, temp48len, temp48, finother);
2209  finswap = finnow;
2210  finnow = finother;
2211  finother = finswap;
2212  if (bdytail != 0.0)
2213  {
2214  temp8len = scale_expansion_zeroelimTRI(4, cc, adxtail, temp8);
2215  temp16alen =
2216  scale_expansion_zeroelimTRI(temp8len, temp8, bdytail, temp16a);
2217  finlength = fast_expansion_sum_zeroelimTRI(
2218  finlength, finnow, temp16alen, temp16a, finother);
2219  finswap = finnow;
2220  finnow = finother;
2221  finother = finswap;
2222  }
2223  if (cdytail != 0.0)
2224  {
2225  temp8len = scale_expansion_zeroelimTRI(4, bb, -adxtail, temp8);
2226  temp16alen =
2227  scale_expansion_zeroelimTRI(temp8len, temp8, cdytail, temp16a);
2228  finlength = fast_expansion_sum_zeroelimTRI(
2229  finlength, finnow, temp16alen, temp16a, finother);
2230  finswap = finnow;
2231  finnow = finother;
2232  finother = finswap;
2233  }
2234 
2235  temp32alen =
2236  scale_expansion_zeroelimTRI(axtbctlen, axtbct, adxtail, temp32a);
2237  axtbcttlen =
2238  scale_expansion_zeroelimTRI(bcttlen, bctt, adxtail, axtbctt);
2239  temp16alen = scale_expansion_zeroelimTRI(
2240  axtbcttlen, axtbctt, 2.0 * adx, temp16a);
2241  temp16blen =
2242  scale_expansion_zeroelimTRI(axtbcttlen, axtbctt, adxtail, temp16b);
2243  temp32blen = fast_expansion_sum_zeroelimTRI(
2244  temp16alen, temp16a, temp16blen, temp16b, temp32b);
2245  temp64len = fast_expansion_sum_zeroelimTRI(
2246  temp32alen, temp32a, temp32blen, temp32b, temp64);
2247  finlength = fast_expansion_sum_zeroelimTRI(
2248  finlength, finnow, temp64len, temp64, finother);
2249  finswap = finnow;
2250  finnow = finother;
2251  finother = finswap;
2252  }
2253  if (adytail != 0.0)
2254  {
2255  temp16alen =
2256  scale_expansion_zeroelimTRI(aytbclen, aytbc, adytail, temp16a);
2257  aytbctlen = scale_expansion_zeroelimTRI(bctlen, bct, adytail, aytbct);
2258  temp32alen =
2259  scale_expansion_zeroelimTRI(aytbctlen, aytbct, 2.0 * ady, temp32a);
2260  temp48len = fast_expansion_sum_zeroelimTRI(
2261  temp16alen, temp16a, temp32alen, temp32a, temp48);
2262  finlength = fast_expansion_sum_zeroelimTRI(
2263  finlength, finnow, temp48len, temp48, finother);
2264  finswap = finnow;
2265  finnow = finother;
2266  finother = finswap;
2267 
2268  temp32alen =
2269  scale_expansion_zeroelimTRI(aytbctlen, aytbct, adytail, temp32a);
2270  aytbcttlen =
2271  scale_expansion_zeroelimTRI(bcttlen, bctt, adytail, aytbctt);
2272  temp16alen = scale_expansion_zeroelimTRI(
2273  aytbcttlen, aytbctt, 2.0 * ady, temp16a);
2274  temp16blen =
2275  scale_expansion_zeroelimTRI(aytbcttlen, aytbctt, adytail, temp16b);
2276  temp32blen = fast_expansion_sum_zeroelimTRI(
2277  temp16alen, temp16a, temp16blen, temp16b, temp32b);
2278  temp64len = fast_expansion_sum_zeroelimTRI(
2279  temp32alen, temp32a, temp32blen, temp32b, temp64);
2280  finlength = fast_expansion_sum_zeroelimTRI(
2281  finlength, finnow, temp64len, temp64, finother);
2282  finswap = finnow;
2283  finnow = finother;
2284  finother = finswap;
2285  }
2286  }
2287  if ((bdxtail != 0.0) || (bdytail != 0.0))
2288  {
2289  if ((cdxtail != 0.0) || (cdytail != 0.0) || (adxtail != 0.0) ||
2290  (adytail != 0.0))
2291  {
2292  Two_Product(cdxtail, ady, ti1, ti0);
2293  Two_Product(cdx, adytail, tj1, tj0);
2294  Two_Two_Sum(ti1, ti0, tj1, tj0, u3, u[2], u[1], u[0]);
2295  u[3] = u3;
2296  negate = -cdy;
2297  Two_Product(adxtail, negate, ti1, ti0);
2298  negate = -cdytail;
2299  Two_Product(adx, negate, tj1, tj0);
2300  Two_Two_Sum(ti1, ti0, tj1, tj0, v3, v[2], v[1], v[0]);
2301  v[3] = v3;
2302  catlen = fast_expansion_sum_zeroelimTRI(4, u, 4, v, cat);
2303 
2304  Two_Product(cdxtail, adytail, ti1, ti0);
2305  Two_Product(adxtail, cdytail, tj1, tj0);
2306  Two_Two_Diff(ti1, ti0, tj1, tj0, catt3, catt[2], catt[1], catt[0]);
2307  catt[3] = catt3;
2308  cattlen = 4;
2309  }
2310  else
2311  {
2312  cat[0] = 0.0;
2313  catlen = 1;
2314  catt[0] = 0.0;
2315  cattlen = 1;
2316  }
2317 
2318  if (bdxtail != 0.0)
2319  {
2320  temp16alen =
2321  scale_expansion_zeroelimTRI(bxtcalen, bxtca, bdxtail, temp16a);
2322  bxtcatlen = scale_expansion_zeroelimTRI(catlen, cat, bdxtail, bxtcat);
2323  temp32alen =
2324  scale_expansion_zeroelimTRI(bxtcatlen, bxtcat, 2.0 * bdx, temp32a);
2325  temp48len = fast_expansion_sum_zeroelimTRI(
2326  temp16alen, temp16a, temp32alen, temp32a, temp48);
2327  finlength = fast_expansion_sum_zeroelimTRI(
2328  finlength, finnow, temp48len, temp48, finother);
2329  finswap = finnow;
2330  finnow = finother;
2331  finother = finswap;
2332  if (cdytail != 0.0)
2333  {
2334  temp8len = scale_expansion_zeroelimTRI(4, aa, bdxtail, temp8);
2335  temp16alen =
2336  scale_expansion_zeroelimTRI(temp8len, temp8, cdytail, temp16a);
2337  finlength = fast_expansion_sum_zeroelimTRI(
2338  finlength, finnow, temp16alen, temp16a, finother);
2339  finswap = finnow;
2340  finnow = finother;
2341  finother = finswap;
2342  }
2343  if (adytail != 0.0)
2344  {
2345  temp8len = scale_expansion_zeroelimTRI(4, cc, -bdxtail, temp8);
2346  temp16alen =
2347  scale_expansion_zeroelimTRI(temp8len, temp8, adytail, temp16a);
2348  finlength = fast_expansion_sum_zeroelimTRI(
2349  finlength, finnow, temp16alen, temp16a, finother);
2350  finswap = finnow;
2351  finnow = finother;
2352  finother = finswap;
2353  }
2354 
2355  temp32alen =
2356  scale_expansion_zeroelimTRI(bxtcatlen, bxtcat, bdxtail, temp32a);
2357  bxtcattlen =
2358  scale_expansion_zeroelimTRI(cattlen, catt, bdxtail, bxtcatt);
2359  temp16alen = scale_expansion_zeroelimTRI(
2360  bxtcattlen, bxtcatt, 2.0 * bdx, temp16a);
2361  temp16blen =
2362  scale_expansion_zeroelimTRI(bxtcattlen, bxtcatt, bdxtail, temp16b);
2363  temp32blen = fast_expansion_sum_zeroelimTRI(
2364  temp16alen, temp16a, temp16blen, temp16b, temp32b);
2365  temp64len = fast_expansion_sum_zeroelimTRI(
2366  temp32alen, temp32a, temp32blen, temp32b, temp64);
2367  finlength = fast_expansion_sum_zeroelimTRI(
2368  finlength, finnow, temp64len, temp64, finother);
2369  finswap = finnow;
2370  finnow = finother;
2371  finother = finswap;
2372  }
2373  if (bdytail != 0.0)
2374  {
2375  temp16alen =
2376  scale_expansion_zeroelimTRI(bytcalen, bytca, bdytail, temp16a);
2377  bytcatlen = scale_expansion_zeroelimTRI(catlen, cat, bdytail, bytcat);
2378  temp32alen =
2379  scale_expansion_zeroelimTRI(bytcatlen, bytcat, 2.0 * bdy, temp32a);
2380  temp48len = fast_expansion_sum_zeroelimTRI(
2381  temp16alen, temp16a, temp32alen, temp32a, temp48);
2382  finlength = fast_expansion_sum_zeroelimTRI(
2383  finlength, finnow, temp48len, temp48, finother);
2384  finswap = finnow;
2385  finnow = finother;
2386  finother = finswap;
2387 
2388  temp32alen =
2389  scale_expansion_zeroelimTRI(bytcatlen, bytcat, bdytail, temp32a);
2390  bytcattlen =
2391  scale_expansion_zeroelimTRI(cattlen, catt, bdytail, bytcatt);
2392  temp16alen = scale_expansion_zeroelimTRI(
2393  bytcattlen, bytcatt, 2.0 * bdy, temp16a);
2394  temp16blen =
2395  scale_expansion_zeroelimTRI(bytcattlen, bytcatt, bdytail, temp16b);
2396  temp32blen = fast_expansion_sum_zeroelimTRI(
2397  temp16alen, temp16a, temp16blen, temp16b, temp32b);
2398  temp64len = fast_expansion_sum_zeroelimTRI(
2399  temp32alen, temp32a, temp32blen, temp32b, temp64);
2400  finlength = fast_expansion_sum_zeroelimTRI(
2401  finlength, finnow, temp64len, temp64, finother);
2402  finswap = finnow;
2403  finnow = finother;
2404  finother = finswap;
2405  }
2406  }
2407  if ((cdxtail != 0.0) || (cdytail != 0.0))
2408  {
2409  if ((adxtail != 0.0) || (adytail != 0.0) || (bdxtail != 0.0) ||
2410  (bdytail != 0.0))
2411  {
2412  Two_Product(adxtail, bdy, ti1, ti0);
2413  Two_Product(adx, bdytail, tj1, tj0);
2414  Two_Two_Sum(ti1, ti0, tj1, tj0, u3, u[2], u[1], u[0]);
2415  u[3] = u3;
2416  negate = -ady;
2417  Two_Product(bdxtail, negate, ti1, ti0);
2418  negate = -adytail;
2419  Two_Product(bdx, negate, tj1, tj0);
2420  Two_Two_Sum(ti1, ti0, tj1, tj0, v3, v[2], v[1], v[0]);
2421  v[3] = v3;
2422  abtlen = fast_expansion_sum_zeroelimTRI(4, u, 4, v, abt);
2423 
2424  Two_Product(adxtail, bdytail, ti1, ti0);
2425  Two_Product(bdxtail, adytail, tj1, tj0);
2426  Two_Two_Diff(ti1, ti0, tj1, tj0, abtt3, abtt[2], abtt[1], abtt[0]);
2427  abtt[3] = abtt3;
2428  abttlen = 4;
2429  }
2430  else
2431  {
2432  abt[0] = 0.0;
2433  abtlen = 1;
2434  abtt[0] = 0.0;
2435  abttlen = 1;
2436  }
2437 
2438  if (cdxtail != 0.0)
2439  {
2440  temp16alen =
2441  scale_expansion_zeroelimTRI(cxtablen, cxtab, cdxtail, temp16a);
2442  cxtabtlen = scale_expansion_zeroelimTRI(abtlen, abt, cdxtail, cxtabt);
2443  temp32alen =
2444  scale_expansion_zeroelimTRI(cxtabtlen, cxtabt, 2.0 * cdx, temp32a);
2445  temp48len = fast_expansion_sum_zeroelimTRI(
2446  temp16alen, temp16a, temp32alen, temp32a, temp48);
2447  finlength = fast_expansion_sum_zeroelimTRI(
2448  finlength, finnow, temp48len, temp48, finother);
2449  finswap = finnow;
2450  finnow = finother;
2451  finother = finswap;
2452  if (adytail != 0.0)
2453  {
2454  temp8len = scale_expansion_zeroelimTRI(4, bb, cdxtail, temp8);
2455  temp16alen =
2456  scale_expansion_zeroelimTRI(temp8len, temp8, adytail, temp16a);
2457  finlength = fast_expansion_sum_zeroelimTRI(
2458  finlength, finnow, temp16alen, temp16a, finother);
2459  finswap = finnow;
2460  finnow = finother;
2461  finother = finswap;
2462  }
2463  if (bdytail != 0.0)
2464  {
2465  temp8len = scale_expansion_zeroelimTRI(4, aa, -cdxtail, temp8);
2466  temp16alen =
2467  scale_expansion_zeroelimTRI(temp8len, temp8, bdytail, temp16a);
2468  finlength = fast_expansion_sum_zeroelimTRI(
2469  finlength, finnow, temp16alen, temp16a, finother);
2470  finswap = finnow;
2471  finnow = finother;
2472  finother = finswap;
2473  }
2474 
2475  temp32alen =
2476  scale_expansion_zeroelimTRI(cxtabtlen, cxtabt, cdxtail, temp32a);
2477  cxtabttlen =
2478  scale_expansion_zeroelimTRI(abttlen, abtt, cdxtail, cxtabtt);
2479  temp16alen = scale_expansion_zeroelimTRI(
2480  cxtabttlen, cxtabtt, 2.0 * cdx, temp16a);
2481  temp16blen =
2482  scale_expansion_zeroelimTRI(cxtabttlen, cxtabtt, cdxtail, temp16b);
2483  temp32blen = fast_expansion_sum_zeroelimTRI(
2484  temp16alen, temp16a, temp16blen, temp16b, temp32b);
2485  temp64len = fast_expansion_sum_zeroelimTRI(
2486  temp32alen, temp32a, temp32blen, temp32b, temp64);
2487  finlength = fast_expansion_sum_zeroelimTRI(
2488  finlength, finnow, temp64len, temp64, finother);
2489  finswap = finnow;
2490  finnow = finother;
2491  finother = finswap;
2492  }
2493  if (cdytail != 0.0)
2494  {
2495  temp16alen =
2496  scale_expansion_zeroelimTRI(cytablen, cytab, cdytail, temp16a);
2497  cytabtlen = scale_expansion_zeroelimTRI(abtlen, abt, cdytail, cytabt);
2498  temp32alen =
2499  scale_expansion_zeroelimTRI(cytabtlen, cytabt, 2.0 * cdy, temp32a);
2500  temp48len = fast_expansion_sum_zeroelimTRI(
2501  temp16alen, temp16a, temp32alen, temp32a, temp48);
2502  finlength = fast_expansion_sum_zeroelimTRI(
2503  finlength, finnow, temp48len, temp48, finother);
2504  finswap = finnow;
2505  finnow = finother;
2506  finother = finswap;
2507 
2508  temp32alen =
2509  scale_expansion_zeroelimTRI(cytabtlen, cytabt, cdytail, temp32a);
2510  cytabttlen =
2511  scale_expansion_zeroelimTRI(abttlen, abtt, cdytail, cytabtt);
2512  temp16alen = scale_expansion_zeroelimTRI(
2513  cytabttlen, cytabtt, 2.0 * cdy, temp16a);
2514  temp16blen =
2515  scale_expansion_zeroelimTRI(cytabttlen, cytabtt, cdytail, temp16b);
2516  temp32blen = fast_expansion_sum_zeroelimTRI(
2517  temp16alen, temp16a, temp16blen, temp16b, temp32b);
2518  temp64len = fast_expansion_sum_zeroelimTRI(
2519  temp32alen, temp32a, temp32blen, temp32b, temp64);
2520  finlength = fast_expansion_sum_zeroelimTRI(
2521  finlength, finnow, temp64len, temp64, finother);
2522  finswap = finnow;
2523  finnow = finother;
2524  finother = finswap;
2525  }
2526  }
2527 
2528  return finnow[finlength - 1];
2529 }
#define Absolute(a)
#define Two_Two_Sum(a1, a0, b1, b0, x3, x2, x1, x0)
#define Two_Diff_Tail(a, b, x, y)
void negate(NekPoint< DataType > &rhs)
Definition: NekPoint.hpp:373
int fast_expansion_sum_zeroelimTRI(int elen, double *e, int flen, double *f, double *h)
int scale_expansion_zeroelimTRI(int elen, double *e, double b, double *h)
#define Two_Two_Diff(a1, a0, b1, b0, x3, x2, x1, x0)
#define Two_Product(a, b, x, y)
#define Square(a, x, y)
void Nektar::NekMeshUtils::DelaunayTriangle::infecthull ( struct mesh m,
struct behavior b 
)
private

Definition at line 7384 of file Triangle/Triangle.cpp.

References dest, Nektar::NekMeshUtils::mesh::dummysub, Nektar::NekMeshUtils::mesh::dummytri, infect, infected, lnextself, mark, oprev, org, Nektar::NekMeshUtils::otri::orient, otricopy, otriequal, poolalloc(), setmark, setvertexmark, Nektar::NekMeshUtils::osub::ss, symself, Nektar::NekMeshUtils::otri::tri, tspivot, vertexmark, and Nektar::NekMeshUtils::mesh::viri.

Referenced by carveholes().

7385 {
7386  struct otri hulltri;
7387  struct otri nexttri;
7388  struct otri starttri;
7389  struct osub hullsubseg;
7390  triangle **deadtriangle;
7391  vertex horg, hdest;
7392  triangle ptr; /* Temporary variable used by sym(). */
7393  subseg sptr; /* Temporary variable used by tspivot(). */
7394 
7395  /* Find a triangle handle on the hull. */
7396  hulltri.tri = m->dummytri;
7397  hulltri.orient = 0;
7398  symself(hulltri);
7399  /* Remember where we started so we know when to stop. */
7400  otricopy(hulltri, starttri);
7401  /* Go once counterclockwise around the convex hull. */
7402  do
7403  {
7404  /* Ignore triangles that are already infected. */
7405  if (!infected(hulltri))
7406  {
7407  /* Is the triangle protected by a subsegment? */
7408  tspivot(hulltri, hullsubseg);
7409  if (hullsubseg.ss == m->dummysub)
7410  {
7411  /* The triangle is not protected; infect it. */
7412  if (!infected(hulltri))
7413  {
7414  infect(hulltri);
7415  deadtriangle = (triangle **)poolalloc(&m->viri);
7416  *deadtriangle = hulltri.tri;
7417  }
7418  }
7419  else
7420  {
7421  /* The triangle is protected; set boundary markers if
7422  * appropriate. */
7423  if (mark(hullsubseg) == 0)
7424  {
7425  setmark(hullsubseg, 1);
7426  org(hulltri, horg);
7427  dest(hulltri, hdest);
7428  if (vertexmark(horg) == 0)
7429  {
7430  setvertexmark(horg, 1);
7431  }
7432  if (vertexmark(hdest) == 0)
7433  {
7434  setvertexmark(hdest, 1);
7435  }
7436  }
7437  }
7438  }
7439  /* To find the next hull edge, go clockwise around the next vertex. */
7440  lnextself(hulltri);
7441  oprev(hulltri, nexttri);
7442  while (nexttri.tri != m->dummytri)
7443  {
7444  otricopy(nexttri, hulltri);
7445  oprev(hulltri, nexttri);
7446  }
7447  } while (!otriequal(hulltri, starttri));
7448 }
#define vertexmark(vx)
#define setmark(osub, value)
void * poolalloc(struct memorypool *pool)
#define otriequal(otri1, otri2)
#define mark(osub)
#define lnextself(otri)
#define infected(otri)
#define symself(otri)
#define infect(otri)
#define setvertexmark(vx, value)
#define oprev(otri1, otri2)
#define otricopy(otri1, otri2)
#define tspivot(otri, osub)
#define dest(otri, vertexptr)
#define org(otri, vertexptr)
void Nektar::NekMeshUtils::DelaunayTriangle::initializetrisubpools ( struct mesh m,
struct behavior b 
)
private

Definition at line 986 of file Triangle/Triangle.cpp.

References Nektar::NekMeshUtils::mesh::areaboundindex, dummyinit(), Nektar::NekMeshUtils::mesh::eextras, Nektar::NekMeshUtils::mesh::elemattribindex, Nektar::NekMeshUtils::mesh::highorderindex, Nektar::NekMeshUtils::mesh::invertices, Nektar::NekMeshUtils::memorypool::itembytes, poolinit(), SUBSEGPERBLOCK, Nektar::NekMeshUtils::mesh::subsegs, Nektar::NekMeshUtils::mesh::triangles, TRIPERBLOCK, and Nektar::NekMeshUtils::behavior::usesegments.

Referenced by delaunay().

987 {
988  int trisize;
989 
990  /* The index within each triangle at which the extra nodes (above three) */
991  /* associated with high order elements are found. There are three */
992  /* pointers to other triangles, three pointers to corners, and possibly */
993  /* three pointers to subsegments before the extra nodes. */
994  m->highorderindex = 6 + (b->usesegments * 3);
995  /* The number of bytes occupied by a triangle. */
996  trisize = (3 + (m->highorderindex - 3)) *
997  sizeof(triangle);
998  /* The index within each triangle at which its attributes are found, */
999  /* where the index is measured in doubles. */
1000  m->elemattribindex = (trisize + sizeof(double) - 1) / sizeof(double);
1001  /* The index within each triangle at which the maximum area constraint */
1002  /* is found, where the index is measured in doubles. Note that if the */
1003  /* `regionattrib' flag is set, an additional attribute will be added. */
1004  m->areaboundindex = m->elemattribindex + m->eextras;
1005  /* If triangle attributes or an area bound are needed, increase the number
1006  */
1007  /* of bytes occupied by a triangle. */
1008  trisize = m->areaboundindex * sizeof(double);
1009 
1010  /* Having determined the memory size of a triangle, initialize the pool. */
1011  poolinit(&m->triangles,
1012  trisize,
1013  TRIPERBLOCK,
1014  (2 * m->invertices - 2) > TRIPERBLOCK ? (2 * m->invertices - 2)
1015  : TRIPERBLOCK,
1016  4);
1017 
1018  if (b->usesegments)
1019  {
1020  /* Initialize the pool of subsegments. Take into account all eight */
1021  /* pointers and one boundary marker. */
1022  poolinit(&m->subsegs,
1023  8 * sizeof(triangle) + sizeof(int),
1026  4);
1027 
1028  /* Initialize the "outer space" triangle and omnipresent subsegment. */
1029  dummyinit(m, b, m->triangles.itembytes, m->subsegs.itembytes);
1030  }
1031  else
1032  {
1033  /* Initialize the "outer space" triangle. */
1034  dummyinit(m, b, m->triangles.itembytes, 0);
1035  }
1036 }
void poolinit(struct memorypool *pool, int bytecount, int itemcount, int firstitemcount, int alignment)
#define SUBSEGPERBLOCK
void dummyinit(struct mesh *m, struct behavior *b, int trianglebytes, int subsegbytes)
#define TRIPERBLOCK
void Nektar::NekMeshUtils::DelaunayTriangle::initializevertexpool ( struct mesh m,
struct behavior b 
)
private

Definition at line 946 of file Triangle/Triangle.cpp.

References Nektar::NekMeshUtils::mesh::invertices, Nektar::NekMeshUtils::mesh::mesh_dim, Nektar::NekMeshUtils::mesh::nextras, Nektar::NekMeshUtils::behavior::poly, poolinit(), Nektar::NekMeshUtils::mesh::vertex2triindex, Nektar::NekMeshUtils::mesh::vertexmarkindex, VERTEXPERBLOCK, and Nektar::NekMeshUtils::mesh::vertices.

Referenced by transfernodes().

947 {
948  int vertexsize;
949 
950  /* The index within each vertex at which the boundary marker is found, */
951  /* followed by the vertex type. Ensure the vertex marker is aligned to */
952  /* a sizeof(int)-byte address. */
953  m->vertexmarkindex =
954  ((m->mesh_dim + m->nextras) * sizeof(double) + sizeof(int) - 1) /
955  sizeof(int);
956  vertexsize = (m->vertexmarkindex + 2) * sizeof(int);
957  if (b->poly)
958  {
959  /* The index within each vertex at which a triangle pointer is found. */
960  /* Ensure the pointer is aligned to a sizeof(triangle)-byte address.
961  */
962  m->vertex2triindex =
963  (vertexsize + sizeof(triangle) - 1) / sizeof(triangle);
964  vertexsize = (m->vertex2triindex + 1) * sizeof(triangle);
965  }
966 
967  /* Initialize the pool of vertices. */
968  poolinit(&m->vertices,
969  vertexsize,
971  m->invertices > VERTEXPERBLOCK ? m->invertices : VERTEXPERBLOCK,
972  sizeof(double));
973 }
void poolinit(struct memorypool *pool, int bytecount, int itemcount, int firstitemcount, int alignment)
#define VERTEXPERBLOCK
void Nektar::NekMeshUtils::DelaunayTriangle::insertsegment ( struct mesh m,
struct behavior b,
vertex  endpoint1,
vertex  endpoint2,
int  newmark 
)
private

Definition at line 7144 of file Triangle/Triangle.cpp.

References constrainededge(), decode, Nektar::NekMeshUtils::mesh::dummytri, internalerror(), locate(), Nektar::NekMeshUtils::ONVERTEX, org, Nektar::NekMeshUtils::otri::orient, otricopy, Nektar::NekMeshUtils::mesh::recenttri, scoutsegment(), symself, Nektar::NekMeshUtils::otri::tri, and vertex2tri.

Referenced by formskeleton().

7149 {
7150  struct otri searchtri1, searchtri2;
7151  triangle encodedtri;
7152  vertex checkvertex;
7153  triangle ptr; /* Temporary variable used by sym(). */
7154 
7155 
7156 
7157  /* Find a triangle whose origin is the segment's first endpoint. */
7158  checkvertex = (vertex)NULL;
7159  encodedtri = vertex2tri(endpoint1);
7160  if (encodedtri != (triangle)NULL)
7161  {
7162  decode(encodedtri, searchtri1);
7163  org(searchtri1, checkvertex);
7164  }
7165  if (checkvertex != endpoint1)
7166  {
7167  /* Find a boundary triangle to search from. */
7168  searchtri1.tri = m->dummytri;
7169  searchtri1.orient = 0;
7170  symself(searchtri1);
7171  /* Search for the segment's first endpoint by point location. */
7172  if (locate(m, b, endpoint1, &searchtri1) != ONVERTEX)
7173  {
7174  printf("Internal error in insertsegment(): Unable to locate PSLG "
7175  "vertex\n");
7176  printf(" (%.12g, %.12g) in triangulation.\n",
7177  endpoint1[0],
7178  endpoint1[1]);
7179  internalerror();
7180  }
7181  }
7182  /* Remember this triangle to improve subsequent point location. */
7183  otricopy(searchtri1, m->recenttri);
7184  /* Scout the beginnings of a path from the first endpoint */
7185  /* toward the second. */
7186  if (scoutsegment(m, b, &searchtri1, endpoint2, newmark))
7187  {
7188  /* The segment was easily inserted. */
7189  return;
7190  }
7191  /* The first endpoint may have changed if a collision with an intervening */
7192  /* vertex on the segment occurred. */
7193  org(searchtri1, endpoint1);
7194 
7195  /* Find a triangle whose origin is the segment's second endpoint. */
7196  checkvertex = (vertex)NULL;
7197  encodedtri = vertex2tri(endpoint2);
7198  if (encodedtri != (triangle)NULL)
7199  {
7200  decode(encodedtri, searchtri2);
7201  org(searchtri2, checkvertex);
7202  }
7203  if (checkvertex != endpoint2)
7204  {
7205  /* Find a boundary triangle to search from. */
7206  searchtri2.tri = m->dummytri;
7207  searchtri2.orient = 0;
7208  symself(searchtri2);
7209  /* Search for the segment's second endpoint by point location. */
7210  if (locate(m, b, endpoint2, &searchtri2) != ONVERTEX)
7211  {
7212  printf("Internal error in insertsegment(): Unable to locate PSLG "
7213  "vertex\n");
7214  printf(" (%.12g, %.12g) in triangulation.\n",
7215  endpoint2[0],
7216  endpoint2[1]);
7217  internalerror();
7218  }
7219  }
7220  /* Remember this triangle to improve subsequent point location. */
7221  otricopy(searchtri2, m->recenttri);
7222  /* Scout the beginnings of a path from the second endpoint */
7223  /* toward the first. */
7224  if (scoutsegment(m, b, &searchtri2, endpoint1, newmark))
7225  {
7226  /* The segment was easily inserted. */
7227  return;
7228  }
7229  /* The second endpoint may have changed if a collision with an intervening
7230  */
7231  /* vertex on the segment occurred. */
7232  org(searchtri2, endpoint2);
7233 
7234 
7235  /* Insert the segment directly into the triangulation. */
7236  constrainededge(m, b, &searchtri1, endpoint2, newmark);
7237 }
#define decode(ptr, otri)
#define symself(otri)
#define vertex2tri(vx)
void constrainededge(struct mesh *m, struct behavior *b, struct otri *starttri, vertex endpoint2, int newmark)
#define otricopy(otri1, otri2)
enum locateresult locate(struct mesh *m, struct behavior *b, vertex searchpoint, struct otri *searchtri)
int scoutsegment(struct mesh *m, struct behavior *b, struct otri *searchtri, vertex endpoint2, int newmark)
#define org(otri, vertexptr)
void Nektar::NekMeshUtils::DelaunayTriangle::insertsubseg ( struct mesh m,
struct behavior b,
struct otri tri,
int  subsegmark 
)
private

Definition at line 4307 of file Triangle/Triangle.cpp.

References dest, Nektar::NekMeshUtils::mesh::dummysub, makesubseg(), mark, org, setmark, setsdest, setsegdest, setsegorg, setsorg, setvertexmark, Nektar::NekMeshUtils::osub::ss, ssymself, sym, tsbond, tspivot, and vertexmark.

Referenced by constrainededge(), insertvertex(), markhull(), and scoutsegment().

4311 {
4312  struct otri oppotri;
4313  struct osub newsubseg;
4314  vertex triorg, tridest;
4315  triangle ptr; /* Temporary variable used by sym(). */
4316  subseg sptr; /* Temporary variable used by tspivot(). */
4317 
4318  org(*tri, triorg);
4319  dest(*tri, tridest);
4320  /* Mark vertices if possible. */
4321  if (vertexmark(triorg) == 0)
4322  {
4323  setvertexmark(triorg, subsegmark);
4324  }
4325  if (vertexmark(tridest) == 0)
4326  {
4327  setvertexmark(tridest, subsegmark);
4328  }
4329  /* Check if there's already a subsegment here. */
4330  tspivot(*tri, newsubseg);
4331  if (newsubseg.ss == m->dummysub)
4332  {
4333  /* Make new subsegment and initialize its vertices. */
4334  makesubseg(m, &newsubseg);
4335  setsorg(newsubseg, tridest);
4336  setsdest(newsubseg, triorg);
4337  setsegorg(newsubseg, tridest);
4338  setsegdest(newsubseg, triorg);
4339  /* Bond new subsegment to the two triangles it is sandwiched between. */
4340  /* Note that the facing triangle `oppotri' might be equal to */
4341  /* `dummytri' (outer space), but the new subsegment is bonded to it */
4342  /* all the same. */
4343  tsbond(*tri, newsubseg);
4344  sym(*tri, oppotri);
4345  ssymself(newsubseg);
4346  tsbond(oppotri, newsubseg);
4347  setmark(newsubseg, subsegmark);
4348  }
4349  else
4350  {
4351  if (mark(newsubseg) == 0)
4352  {
4353  setmark(newsubseg, subsegmark);
4354  }
4355  }
4356 }
#define vertexmark(vx)
#define setmark(osub, value)
#define setsegdest(osub, vertexptr)
#define setsegorg(osub, vertexptr)
#define mark(osub)
#define sym(otri1, otri2)
#define tsbond(otri, osub)
#define setsdest(osub, vertexptr)
#define setvertexmark(vx, value)
#define tspivot(otri, osub)
#define dest(otri, vertexptr)
void makesubseg(struct mesh *m, struct osub *newsubseg)
#define setsorg(osub, vertexptr)
#define org(otri, vertexptr)
#define ssymself(osub)
enum insertvertexresult Nektar::NekMeshUtils::DelaunayTriangle::insertvertex ( struct mesh m,
struct behavior b,
vertex  newvertex,
struct otri searchtri,
struct osub splitseg,
int  segmentflaws,
int  triflaws 
)
private

Definition at line 4658 of file Triangle/Triangle.cpp.

References apex, Nektar::NekMeshUtils::mesh::badsubsegs, bond, Nektar::NekMeshUtils::mesh::checkquality, checkseg4encroach(), Nektar::NekMeshUtils::mesh::checksegments, counterclockwise(), dest, Nektar::NekMeshUtils::mesh::dummysub, Nektar::NekMeshUtils::mesh::dummytri, Nektar::NekMeshUtils::DUPLICATEVERTEX, Nektar::NekMeshUtils::mesh::eextras, elemattribute, encode, Nektar::NekMeshUtils::ENCROACHINGVERTEX, Nektar::NekMeshUtils::badsubseg::encsubseg, Nektar::NekMeshUtils::flipstacker::flippedtri, Nektar::NekMeshUtils::mesh::flipstackers, Nektar::NekMeshUtils::mesh::hullsize, incircle(), Nektar::NekMeshUtils::mesh::infvertex1, Nektar::NekMeshUtils::mesh::infvertex2, Nektar::NekMeshUtils::mesh::infvertex3, insertsubseg(), Nektar::NekMeshUtils::mesh::lastflip, lnext, lnextself, locate(), lprev, lprevself, maketriangle(), mark, Nektar::NekMeshUtils::behavior::nobisect, Nektar::NekMeshUtils::ONEDGE, Nektar::NekMeshUtils::ONVERTEX, org, Nektar::NekMeshUtils::otri::orient, otricopy, Nektar::NekMeshUtils::OUTSIDE, poolalloc(), poolrestart(), preciselocate(), Nektar::NekMeshUtils::flipstacker::prevflip, Nektar::NekMeshUtils::mesh::recenttri, sbond, sdest, segdest, segorg, sencode, setapex, setdest, setelemattribute, setorg, setsdest, setsegdest, setsegorg, setvertexmark, sorg, spivot, Nektar::NekMeshUtils::osub::ss, ssymself, Nektar::NekMeshUtils::badsubseg::subsegdest, Nektar::NekMeshUtils::badsubseg::subsegorg, Nektar::NekMeshUtils::SUCCESSFULVERTEX, sym, symself, testtriangle(), Nektar::NekMeshUtils::otri::tri, tsbond, tsdissolve, tspivot, vertexmark, and Nektar::NekMeshUtils::VIOLATINGVERTEX.

Referenced by conformingedge(), segmentintersection(), splitencsegs(), and splittriangle().

4665 {
4666  struct otri horiz;
4667  struct otri top;
4668  struct otri botleft, botright;
4669  struct otri topleft, topright;
4670  struct otri newbotleft, newbotright;
4671  struct otri newtopright;
4672  struct otri botlcasing, botrcasing;
4673  struct otri toplcasing, toprcasing;
4674  struct otri testtri;
4675  struct osub botlsubseg, botrsubseg;
4676  struct osub toplsubseg, toprsubseg;
4677  struct osub brokensubseg;
4678  struct osub checksubseg;
4679  struct osub rightsubseg;
4680  struct osub newsubseg;
4681  struct badsubseg *encroached;
4682  struct flipstacker *newflip;
4683  vertex first;
4684  vertex leftvertex, rightvertex, botvertex, topvertex, farvertex;
4685  vertex segmentorg, segmentdest;
4686  double attrib;
4687  enum insertvertexresult success;
4688  enum locateresult intersect;
4689  int doflip;
4690  int mirrorflag;
4691  int enq;
4692  int i;
4693  triangle ptr; /* Temporary variable used by sym(). */
4694  subseg sptr; /* Temporary variable used by spivot() and tspivot(). */
4695 
4696  if (splitseg == (struct osub *)NULL)
4697  {
4698  /* Find the location of the vertex to be inserted. Check if a good */
4699  /* starting triangle has already been provided by the caller. */
4700  if (searchtri->tri == m->dummytri)
4701  {
4702  /* Find a boundary triangle. */
4703  horiz.tri = m->dummytri;
4704  horiz.orient = 0;
4705  symself(horiz);
4706  /* Search for a triangle containing `newvertex'. */
4707  intersect = locate(m, b, newvertex, &horiz);
4708  }
4709  else
4710  {
4711  /* Start searching from the triangle provided by the caller. */
4712  otricopy(*searchtri, horiz);
4713  intersect = preciselocate(m, b, newvertex, &horiz, 1);
4714  }
4715  }
4716  else
4717  {
4718  /* The calling routine provides the subsegment in which */
4719  /* the vertex is inserted. */
4720  otricopy(*searchtri, horiz);
4721  intersect = ONEDGE;
4722  }
4723 
4724  if (intersect == ONVERTEX)
4725  {
4726  /* There's already a vertex there. Return in `searchtri' a triangle */
4727  /* whose origin is the existing vertex. */
4728  otricopy(horiz, *searchtri);
4729  otricopy(horiz, m->recenttri);
4730  return DUPLICATEVERTEX;
4731  }
4732  if ((intersect == ONEDGE) || (intersect == OUTSIDE))
4733  {
4734  /* The vertex falls on an edge or boundary. */
4735  if (m->checksegments && (splitseg == (struct osub *)NULL))
4736  {
4737  /* Check whether the vertex falls on a subsegment. */
4738  tspivot(horiz, brokensubseg);
4739  if (brokensubseg.ss != m->dummysub)
4740  {
4741  /* The vertex falls on a subsegment, and hence will not be
4742  * inserted. */
4743  if (segmentflaws)
4744  {
4745  enq = b->nobisect != 2;
4746  if (enq && (b->nobisect == 1))
4747  {
4748  /* This subsegment may be split only if it is an */
4749  /* internal boundary. */
4750  sym(horiz, testtri);
4751  enq = testtri.tri != m->dummytri;
4752  }
4753  if (enq)
4754  {
4755  /* Add the subsegment to the list of encroached
4756  * subsegments. */
4757  encroached =
4758  (struct badsubseg *)poolalloc(&m->badsubsegs);
4759  encroached->encsubseg = sencode(brokensubseg);
4760  sorg(brokensubseg, encroached->subsegorg);
4761  sdest(brokensubseg, encroached->subsegdest);
4762 
4763  }
4764  }
4765  /* Return a handle whose primary edge contains the vertex, */
4766  /* which has not been inserted. */
4767  otricopy(horiz, *searchtri);
4768  otricopy(horiz, m->recenttri);
4769  return VIOLATINGVERTEX;
4770  }
4771  }
4772 
4773  /* Insert the vertex on an edge, dividing one triangle into two (if */
4774  /* the edge lies on a boundary) or two triangles into four. */
4775  lprev(horiz, botright);
4776  sym(botright, botrcasing);
4777  sym(horiz, topright);
4778  /* Is there a second triangle? (Or does this edge lie on a boundary?)
4779  */
4780  mirrorflag = topright.tri != m->dummytri;
4781  if (mirrorflag)
4782  {
4783  lnextself(topright);
4784  sym(topright, toprcasing);
4785  maketriangle(m, b, &newtopright);
4786  }
4787  else
4788  {
4789  /* Splitting a boundary edge increases the number of boundary edges.
4790  */
4791  m->hullsize++;
4792  }
4793  maketriangle(m, b, &newbotright);
4794 
4795  /* Set the vertices of changed and new triangles. */
4796  org(horiz, rightvertex);
4797  dest(horiz, leftvertex);
4798  apex(horiz, botvertex);
4799  setorg(newbotright, botvertex);
4800  setdest(newbotright, rightvertex);
4801  setapex(newbotright, newvertex);
4802  setorg(horiz, newvertex);
4803  for (i = 0; i < m->eextras; i++)
4804  {
4805  /* Set the element attributes of a new triangle. */
4806  setelemattribute(newbotright, i, elemattribute(botright, i));
4807  }
4808 
4809  if (mirrorflag)
4810  {
4811  dest(topright, topvertex);
4812  setorg(newtopright, rightvertex);
4813  setdest(newtopright, topvertex);
4814  setapex(newtopright, newvertex);
4815  setorg(topright, newvertex);
4816  for (i = 0; i < m->eextras; i++)
4817  {
4818  /* Set the element attributes of another new triangle. */
4819  setelemattribute(newtopright, i, elemattribute(topright, i));
4820  }
4821  }
4822 
4823  /* There may be subsegments that need to be bonded */
4824  /* to the new triangle(s). */
4825  if (m->checksegments)
4826  {
4827  tspivot(botright, botrsubseg);
4828  if (botrsubseg.ss != m->dummysub)
4829  {
4830  tsdissolve(botright);
4831  tsbond(newbotright, botrsubseg);
4832  }
4833  if (mirrorflag)
4834  {
4835  tspivot(topright, toprsubseg);
4836  if (toprsubseg.ss != m->dummysub)
4837  {
4838  tsdissolve(topright);
4839  tsbond(newtopright, toprsubseg);
4840  }
4841  }
4842  }
4843 
4844  /* Bond the new triangle(s) to the surrounding triangles. */
4845  bond(newbotright, botrcasing);
4846  lprevself(newbotright);
4847  bond(newbotright, botright);
4848  lprevself(newbotright);
4849  if (mirrorflag)
4850  {
4851  bond(newtopright, toprcasing);
4852  lnextself(newtopright);
4853  bond(newtopright, topright);
4854  lnextself(newtopright);
4855  bond(newtopright, newbotright);
4856  }
4857 
4858  if (splitseg != (struct osub *)NULL)
4859  {
4860  /* Split the subsegment into two. */
4861  setsdest(*splitseg, newvertex);
4862  segorg(*splitseg, segmentorg);
4863  segdest(*splitseg, segmentdest);
4864  ssymself(*splitseg);
4865  spivot(*splitseg, rightsubseg);
4866  insertsubseg(m, b, &newbotright, mark(*splitseg));
4867  tspivot(newbotright, newsubseg);
4868  setsegorg(newsubseg, segmentorg);
4869  setsegdest(newsubseg, segmentdest);
4870  sbond(*splitseg, newsubseg);
4871  ssymself(newsubseg);
4872  sbond(newsubseg, rightsubseg);
4873  ssymself(*splitseg);
4874  /* Transfer the subsegment's boundary marker to the vertex */
4875  /* if required. */
4876  if (vertexmark(newvertex) == 0)
4877  {
4878  setvertexmark(newvertex, mark(*splitseg));
4879  }
4880  }
4881 
4882  if (m->checkquality)
4883  {
4884  poolrestart(&m->flipstackers);
4885  m->lastflip = (struct flipstacker *)poolalloc(&m->flipstackers);
4886  m->lastflip->flippedtri = encode(horiz);
4887  m->lastflip->prevflip = (struct flipstacker *)1;
4888  }
4889 
4890  /* Position `horiz' on the first edge to check for */
4891  /* the Delaunay property. */
4892  lnextself(horiz);
4893  }
4894  else
4895  {
4896  /* Insert the vertex in a triangle, splitting it into three. */
4897  lnext(horiz, botleft);
4898  lprev(horiz, botright);
4899  sym(botleft, botlcasing);
4900  sym(botright, botrcasing);
4901  maketriangle(m, b, &newbotleft);
4902  maketriangle(m, b, &newbotright);
4903 
4904  /* Set the vertices of changed and new triangles. */
4905  org(horiz, rightvertex);
4906  dest(horiz, leftvertex);
4907  apex(horiz, botvertex);
4908  setorg(newbotleft, leftvertex);
4909  setdest(newbotleft, botvertex);
4910  setapex(newbotleft, newvertex);
4911  setorg(newbotright, botvertex);
4912  setdest(newbotright, rightvertex);
4913  setapex(newbotright, newvertex);
4914  setapex(horiz, newvertex);
4915  for (i = 0; i < m->eextras; i++)
4916  {
4917  /* Set the element attributes of the new triangles. */
4918  attrib = elemattribute(horiz, i);
4919  setelemattribute(newbotleft, i, attrib);
4920  setelemattribute(newbotright, i, attrib);
4921  }
4922 
4923  /* There may be subsegments that need to be bonded */
4924  /* to the new triangles. */
4925  if (m->checksegments)
4926  {
4927  tspivot(botleft, botlsubseg);
4928  if (botlsubseg.ss != m->dummysub)
4929  {
4930  tsdissolve(botleft);
4931  tsbond(newbotleft, botlsubseg);
4932  }
4933  tspivot(botright, botrsubseg);
4934  if (botrsubseg.ss != m->dummysub)
4935  {
4936  tsdissolve(botright);
4937  tsbond(newbotright, botrsubseg);
4938  }
4939  }
4940 
4941  /* Bond the new triangles to the surrounding triangles. */
4942  bond(newbotleft, botlcasing);
4943  bond(newbotright, botrcasing);
4944  lnextself(newbotleft);
4945  lprevself(newbotright);
4946  bond(newbotleft, newbotright);
4947  lnextself(newbotleft);
4948  bond(botleft, newbotleft);
4949  lprevself(newbotright);
4950  bond(botright, newbotright);
4951 
4952  if (m->checkquality)
4953  {
4954  poolrestart(&m->flipstackers);
4955  m->lastflip = (struct flipstacker *)poolalloc(&m->flipstackers);
4956  m->lastflip->flippedtri = encode(horiz);
4957  m->lastflip->prevflip = (struct flipstacker *)NULL;
4958  }
4959 
4960  }
4961 
4962  /* The insertion is successful by default, unless an encroached */
4963  /* subsegment is found. */
4964  success = SUCCESSFULVERTEX;
4965  /* Circle around the newly inserted vertex, checking each edge opposite */
4966  /* it for the Delaunay property. Non-Delaunay edges are flipped. */
4967  /* `horiz' is always the edge being checked. `first' marks where to */
4968  /* stop circling. */
4969  org(horiz, first);
4970  rightvertex = first;
4971  dest(horiz, leftvertex);
4972  /* Circle until finished. */
4973  while (1)
4974  {
4975  /* By default, the edge will be flipped. */
4976  doflip = 1;
4977 
4978  if (m->checksegments)
4979  {
4980  /* Check for a subsegment, which cannot be flipped. */
4981  tspivot(horiz, checksubseg);
4982  if (checksubseg.ss != m->dummysub)
4983  {
4984  /* The edge is a subsegment and cannot be flipped. */
4985  doflip = 0;
4986  if (segmentflaws)
4987  {
4988  /* Does the new vertex encroach upon this subsegment? */
4989  if (checkseg4encroach(m, b, &checksubseg))
4990  {
4991  success = ENCROACHINGVERTEX;
4992  }
4993  }
4994  }
4995  }
4996 
4997  if (doflip)
4998  {
4999  /* Check if the edge is a boundary edge. */
5000  sym(horiz, top);
5001  if (top.tri == m->dummytri)
5002  {
5003  /* The edge is a boundary edge and cannot be flipped. */
5004  doflip = 0;
5005  }
5006  else
5007  {
5008  /* Find the vertex on the other side of the edge. */
5009  apex(top, farvertex);
5010  /* In the incremental Delaunay triangulation algorithm, any of
5011  */
5012  /* `leftvertex', `rightvertex', and `farvertex' could be
5013  * vertices */
5014  /* of the triangular bounding box. These vertices must be */
5015  /* treated as if they are infinitely distant, even though
5016  * their */
5017  /* "coordinates" are not. */
5018  if ((leftvertex == m->infvertex1) ||
5019  (leftvertex == m->infvertex2) ||
5020  (leftvertex == m->infvertex3))
5021  {
5022  /* `leftvertex' is infinitely distant. Check the convexity
5023  * of */
5024  /* the boundary of the triangulation. 'farvertex' might
5025  * be */
5026  /* infinite as well, but trust me, this same condition
5027  * should */
5028  /* be applied. */
5029  doflip = counterclockwise(
5030  m, b, newvertex, rightvertex, farvertex) > 0.0;
5031  }
5032  else if ((rightvertex == m->infvertex1) ||
5033  (rightvertex == m->infvertex2) ||
5034  (rightvertex == m->infvertex3))
5035  {
5036  /* `rightvertex' is infinitely distant. Check the convexity
5037  * of */
5038  /* the boundary of the triangulation. 'farvertex' might
5039  * be */
5040  /* infinite as well, but trust me, this same condition
5041  * should */
5042  /* be applied. */
5043  doflip = counterclockwise(
5044  m, b, farvertex, leftvertex, newvertex) > 0.0;
5045  }
5046  else if ((farvertex == m->infvertex1) ||
5047  (farvertex == m->infvertex2) ||
5048  (farvertex == m->infvertex3))
5049  {
5050  /* `farvertex' is infinitely distant and cannot be inside */
5051  /* the circumcircle of the triangle `horiz'. */
5052  doflip = 0;
5053  }
5054  else
5055  {
5056  /* Test whether the edge is locally Delaunay. */
5057  doflip = incircle(m,
5058  b,
5059  leftvertex,
5060  newvertex,
5061  rightvertex,
5062  farvertex) > 0.0;
5063  }
5064  if (doflip)
5065  {
5066  /* We made it! Flip the edge `horiz' by rotating its
5067  * containing */
5068  /* quadrilateral (the two triangles adjacent to `horiz').
5069  */
5070  /* Identify the casing of the quadrilateral. */
5071  lprev(top, topleft);
5072  sym(topleft, toplcasing);
5073  lnext(top, topright);
5074  sym(topright, toprcasing);
5075  lnext(horiz, botleft);
5076  sym(botleft, botlcasing);
5077  lprev(horiz, botright);
5078  sym(botright, botrcasing);
5079  /* Rotate the quadrilateral one-quarter turn
5080  * counterclockwise. */
5081  bond(topleft, botlcasing);
5082  bond(botleft, botrcasing);
5083  bond(botright, toprcasing);
5084  bond(topright, toplcasing);
5085  if (m->checksegments)
5086  {
5087  /* Check for subsegments and rebond them to the
5088  * quadrilateral. */
5089  tspivot(topleft, toplsubseg);
5090  tspivot(botleft, botlsubseg);
5091  tspivot(botright, botrsubseg);
5092  tspivot(topright, toprsubseg);
5093  if (toplsubseg.ss == m->dummysub)
5094  {
5095  tsdissolve(topright);
5096  }
5097  else
5098  {
5099  tsbond(topright, toplsubseg);
5100  }
5101  if (botlsubseg.ss == m->dummysub)
5102  {
5103  tsdissolve(topleft);
5104  }
5105  else
5106  {
5107  tsbond(topleft, botlsubseg);
5108  }
5109  if (botrsubseg.ss == m->dummysub)
5110  {
5111  tsdissolve(botleft);
5112  }
5113  else
5114  {
5115  tsbond(botleft, botrsubseg);
5116  }
5117  if (toprsubseg.ss == m->dummysub)
5118  {
5119  tsdissolve(botright);
5120  }
5121  else
5122  {
5123  tsbond(botright, toprsubseg);
5124  }
5125  }
5126  /* New vertex assignments for the rotated quadrilateral. */
5127  setorg(horiz, farvertex);
5128  setdest(horiz, newvertex);
5129  setapex(horiz, rightvertex);
5130  setorg(top, newvertex);
5131  setdest(top, farvertex);
5132  setapex(top, leftvertex);
5133  for (i = 0; i < m->eextras; i++)
5134  {
5135  /* Take the average of the two triangles' attributes. */
5136  attrib = 0.5 * (elemattribute(top, i) +
5137  elemattribute(horiz, i));
5138  setelemattribute(top, i, attrib);
5139  setelemattribute(horiz, i, attrib);
5140  }
5141 
5142  if (m->checkquality)
5143  {
5144  newflip =
5145  (struct flipstacker *)poolalloc(&m->flipstackers);
5146  newflip->flippedtri = encode(horiz);
5147  newflip->prevflip = m->lastflip;
5148  m->lastflip = newflip;
5149  }
5150 
5151  /* On the next iterations, consider the two edges that were
5152  */
5153  /* exposed (this is, are now visible to the newly inserted
5154  */
5155  /* vertex) by the edge flip. */
5156  lprevself(horiz);
5157  leftvertex = farvertex;
5158  }
5159  }
5160  }
5161  if (!doflip)
5162  {
5163 /* The handle `horiz' is accepted as locally Delaunay. */
5164  if (triflaws)
5165  {
5166  /* Check the triangle `horiz' for quality. */
5167  testtriangle(m, b, &horiz);
5168  }
5169  /* Look for the next edge around the newly inserted vertex. */
5170  lnextself(horiz);
5171  sym(horiz, testtri);
5172  /* Check for finishing a complete revolution about the new vertex,
5173  * or */
5174  /* falling outside of the triangulation. The latter will happen
5175  */
5176  /* when a vertex is inserted at a boundary. */
5177  if ((leftvertex == first) || (testtri.tri == m->dummytri))
5178  {
5179  /* We're done. Return a triangle whose origin is the new
5180  * vertex. */
5181  lnext(horiz, *searchtri);
5182  lnext(horiz, m->recenttri);
5183  return success;
5184  }
5185  /* Finish finding the next edge around the newly inserted vertex. */
5186  lnext(testtri, horiz);
5187  rightvertex = leftvertex;
5188  dest(horiz, leftvertex);
5189  }
5190  }
5191 }
#define setdest(otri, vertexptr)
#define vertexmark(vx)
#define segdest(osub, vertexptr)
#define bond(otri1, otri2)
#define setsegdest(osub, vertexptr)
double incircle(struct mesh *m, struct behavior *b, vertex pa, vertex pb, vertex pc, vertex pd)
#define setapex(otri, vertexptr)
#define sbond(osub1, osub2)
void * poolalloc(struct memorypool *pool)
#define tsdissolve(otri)
void maketriangle(struct mesh *m, struct behavior *b, struct otri *newotri)
#define setsegorg(osub, vertexptr)
#define segorg(osub, vertexptr)
#define mark(osub)
#define setorg(otri, vertexptr)
#define sym(otri1, otri2)
void testtriangle(struct mesh *m, struct behavior *b, struct otri *testtri)
#define tsbond(otri, osub)
#define lprev(otri1, otri2)
#define lnextself(otri)
#define setsdest(osub, vertexptr)
void insertsubseg(struct mesh *m, struct behavior *b, struct otri *tri, int subsegmark)
enum locateresult preciselocate(struct mesh *m, struct behavior *b, vertex searchpoint, struct otri *searchtri, int stopatsubsegment)
#define symself(otri)
#define sdest(osub, vertexptr)
double counterclockwise(struct mesh *m, struct behavior *b, vertex pa, vertex pb, vertex pc)
#define setelemattribute(otri, attnum, value)
#define lprevself(otri)
#define apex(otri, vertexptr)
void poolrestart(struct memorypool *pool)
#define sorg(osub, vertexptr)
#define setvertexmark(vx, value)
#define elemattribute(otri, attnum)
#define otricopy(otri1, otri2)
#define tspivot(otri, osub)
#define lnext(otri1, otri2)
#define dest(otri, vertexptr)
int checkseg4encroach(struct mesh *m, struct behavior *b, struct osub *testsubseg)
#define spivot(osub1, osub2)
enum locateresult locate(struct mesh *m, struct behavior *b, vertex searchpoint, struct otri *searchtri)
#define org(otri, vertexptr)
#define encode(otri)
#define sencode(osub)
#define ssymself(osub)
void Nektar::NekMeshUtils::DelaunayTriangle::internalerror ( )
private

Definition at line 457 of file Triangle/Triangle.cpp.

References triexit().

Referenced by conformingedge(), finddirection(), insertsegment(), segmentintersection(), and splitencsegs().

458 {
459  printf(" Please report this bug to jrs@cs.berkeley.edu\n");
460  printf(" Include the message above, your input data set, and the exact\n");
461  printf(" command line you used to run Triangle.\n");
462  triexit(1);
463 }
enum locateresult Nektar::NekMeshUtils::DelaunayTriangle::locate ( struct mesh m,
struct behavior b,
vertex  searchpoint,
struct otri searchtri 
)
private

Definition at line 4138 of file Triangle/Triangle.cpp.

References Nektar::NekMeshUtils::memorypool::alignbytes, counterclockwise(), deadtri, dest, Nektar::NekMeshUtils::memorypool::firstblock, Nektar::NekMeshUtils::memorypool::itembytes, Nektar::NekMeshUtils::memorypool::items, Nektar::NekMeshUtils::memorypool::itemsfirstblock, lnextself, Nektar::NekMeshUtils::memorypool::maxitems, Nektar::NekMeshUtils::ONEDGE, Nektar::NekMeshUtils::ONVERTEX, org, Nektar::NekMeshUtils::otri::orient, otricopy, preciselocate(), randomnation(), Nektar::NekMeshUtils::mesh::recenttri, SAMPLEFACTOR, Nektar::NekMeshUtils::mesh::samples, symself, Nektar::NekMeshUtils::otri::tri, Nektar::NekMeshUtils::mesh::triangles, and TRIPERBLOCK.

Referenced by carveholes(), insertsegment(), and insertvertex().

4142 {
4143  void **sampleblock;
4144  char *firsttri;
4145  struct otri sampletri;
4146  vertex torg, tdest;
4147  unsigned long alignptr;
4148  double searchdist, dist;
4149  double ahead;
4150  long samplesperblock, totalsamplesleft, samplesleft;
4151  long population, totalpopulation;
4152  triangle ptr; /* Temporary variable used by sym(). */
4153 
4154  /* Record the distance from the suggested starting triangle to the */
4155  /* point we seek. */
4156  org(*searchtri, torg);
4157  searchdist = (searchpoint[0] - torg[0]) * (searchpoint[0] - torg[0]) +
4158  (searchpoint[1] - torg[1]) * (searchpoint[1] - torg[1]);
4159 
4160  /* If a recently encountered triangle has been recorded and has not been */
4161  /* deallocated, test it as a good starting point. */
4162  if (m->recenttri.tri != (triangle *)NULL)
4163  {
4164  if (!deadtri(m->recenttri.tri))
4165  {
4166  org(m->recenttri, torg);
4167  if ((torg[0] == searchpoint[0]) && (torg[1] == searchpoint[1]))
4168  {
4169  otricopy(m->recenttri, *searchtri);
4170  return ONVERTEX;
4171  }
4172  dist = (searchpoint[0] - torg[0]) * (searchpoint[0] - torg[0]) +
4173  (searchpoint[1] - torg[1]) * (searchpoint[1] - torg[1]);
4174  if (dist < searchdist)
4175  {
4176  otricopy(m->recenttri, *searchtri);
4177  searchdist = dist;
4178  }
4179  }
4180  }
4181 
4182  /* The number of random samples taken is proportional to the cube root of */
4183  /* the number of triangles in the mesh. The next bit of code assumes */
4184  /* that the number of triangles increases monotonically (or at least */
4185  /* doesn't decrease enough to matter). */
4186  while (SAMPLEFACTOR * m->samples * m->samples * m->samples <
4187  m->triangles.items)
4188  {
4189  m->samples++;
4190  }
4191 
4192  /* We'll draw ceiling(samples * TRIPERBLOCK / maxitems) random samples */
4193  /* from each block of triangles (except the first)--until we meet the */
4194  /* sample quota. The ceiling means that blocks at the end might be */
4195  /* neglected, but I don't care. */
4196  samplesperblock =
4197  (m->samples * TRIPERBLOCK - 1) / m->triangles.maxitems + 1;
4198  /* We'll draw ceiling(samples * itemsfirstblock / maxitems) random samples
4199  */
4200  /* from the first block of triangles. */
4201  samplesleft = (m->samples * m->triangles.itemsfirstblock - 1) /
4202  m->triangles.maxitems +
4203  1;
4204  totalsamplesleft = m->samples;
4205  population = m->triangles.itemsfirstblock;
4206  totalpopulation = m->triangles.maxitems;
4207  sampleblock = m->triangles.firstblock;
4208  sampletri.orient = 0;
4209  while (totalsamplesleft > 0)
4210  {
4211  /* If we're in the last block, `population' needs to be corrected. */
4212  if (population > totalpopulation)
4213  {
4214  population = totalpopulation;
4215  }
4216  /* Find a pointer to the first triangle in the block. */
4217  alignptr = (unsigned long)(sampleblock + 1);
4218  firsttri =
4219  (char *)(alignptr + (unsigned long)m->triangles.alignbytes -
4220  (alignptr % (unsigned long)m->triangles.alignbytes));
4221 
4222  /* Choose `samplesleft' randomly sampled triangles in this block. */
4223  do
4224  {
4225  sampletri.tri =
4226  (triangle *)(firsttri +
4227  (randomnation((unsigned int)population) *
4228  m->triangles.itembytes));
4229  if (!deadtri(sampletri.tri))
4230  {
4231  org(sampletri, torg);
4232  dist = (searchpoint[0] - torg[0]) * (searchpoint[0] - torg[0]) +
4233  (searchpoint[1] - torg[1]) * (searchpoint[1] - torg[1]);
4234  if (dist < searchdist)
4235  {
4236  otricopy(sampletri, *searchtri);
4237  searchdist = dist;
4238  }
4239  }
4240 
4241  samplesleft--;
4242  totalsamplesleft--;
4243  } while ((samplesleft > 0) && (totalsamplesleft > 0));
4244 
4245  if (totalsamplesleft > 0)
4246  {
4247  sampleblock = (void **)*sampleblock;
4248  samplesleft = samplesperblock;
4249  totalpopulation -= population;
4250  population = TRIPERBLOCK;
4251  }
4252  }
4253 
4254  /* Where are we? */
4255  org(*searchtri, torg);
4256  dest(*searchtri, tdest);
4257  /* Check the starting triangle's vertices. */
4258  if ((torg[0] == searchpoint[0]) && (torg[1] == searchpoint[1]))
4259  {
4260  return ONVERTEX;
4261  }
4262  if ((tdest[0] == searchpoint[0]) && (tdest[1] == searchpoint[1]))
4263  {
4264  lnextself(*searchtri);
4265  return ONVERTEX;
4266  }
4267  /* Orient `searchtri' to fit the preconditions of calling preciselocate().
4268  */
4269  ahead = counterclockwise(m, b, torg, tdest, searchpoint);
4270  if (ahead < 0.0)
4271  {
4272  /* Turn around so that `searchpoint' is to the left of the */
4273  /* edge specified by `searchtri'. */
4274  symself(*searchtri);
4275  }
4276  else if (ahead == 0.0)
4277  {
4278  /* Check if `searchpoint' is between `torg' and `tdest'. */
4279  if (((torg[0] < searchpoint[0]) == (searchpoint[0] < tdest[0])) &&
4280  ((torg[1] < searchpoint[1]) == (searchpoint[1] < tdest[1])))
4281  {
4282  return ONEDGE;
4283  }
4284  }
4285  return preciselocate(m, b, searchpoint, searchtri, 0);
4286 }
unsigned long randomnation(unsigned int choices)
#define lnextself(otri)
enum locateresult preciselocate(struct mesh *m, struct behavior *b, vertex searchpoint, struct otri *searchtri, int stopatsubsegment)
#define symself(otri)
double counterclockwise(struct mesh *m, struct behavior *b, vertex pa, vertex pb, vertex pc)
#define TRIPERBLOCK
#define otricopy(otri1, otri2)
#define SAMPLEFACTOR
#define dest(otri, vertexptr)
#define deadtri(tria)
#define org(otri, vertexptr)
void Nektar::NekMeshUtils::DelaunayTriangle::makesubseg ( struct mesh m,
struct osub newsubseg 
)
private

Definition at line 1297 of file Triangle/Triangle.cpp.

References Nektar::NekMeshUtils::mesh::dummysub, Nektar::NekMeshUtils::mesh::dummytri, poolalloc(), setmark, Nektar::NekMeshUtils::osub::ss, Nektar::NekMeshUtils::osub::ssorient, and Nektar::NekMeshUtils::mesh::subsegs.

Referenced by insertsubseg().

1298 {
1299  newsubseg->ss = (subseg *)poolalloc(&m->subsegs);
1300  /* Initialize the two adjoining subsegments to be the omnipresent */
1301  /* subsegment. */
1302  newsubseg->ss[0] = (subseg)m->dummysub;
1303  newsubseg->ss[1] = (subseg)m->dummysub;
1304  /* Four NULL vertices. */
1305  newsubseg->ss[2] = (subseg)NULL;
1306  newsubseg->ss[3] = (subseg)NULL;
1307  newsubseg->ss[4] = (subseg)NULL;
1308  newsubseg->ss[5] = (subseg)NULL;
1309  /* Initialize the two adjoining triangles to be "outer space." */
1310  newsubseg->ss[6] = (subseg)m->dummytri;
1311  newsubseg->ss[7] = (subseg)m->dummytri;
1312  /* Set the boundary marker to zero. */
1313  setmark(*newsubseg, 0);
1314 
1315  newsubseg->ssorient = 0;
1316 }
#define setmark(osub, value)
void * poolalloc(struct memorypool *pool)
void Nektar::NekMeshUtils::DelaunayTriangle::maketriangle ( struct mesh m,
struct behavior b,
struct otri newotri 
)
private

Definition at line 1262 of file Triangle/Triangle.cpp.

References Nektar::NekMeshUtils::mesh::dummysub, Nektar::NekMeshUtils::mesh::dummytri, Nektar::NekMeshUtils::mesh::eextras, Nektar::NekMeshUtils::otri::orient, poolalloc(), setelemattribute, Nektar::NekMeshUtils::otri::tri, Nektar::NekMeshUtils::mesh::triangles, and Nektar::NekMeshUtils::behavior::usesegments.

Referenced by divconqrecurse(), insertvertex(), and mergehulls().

1263 {
1264  int i;
1265 
1266  newotri->tri = (triangle *)poolalloc(&m->triangles);
1267  /* Initialize the three adjoining triangles to be "outer space". */
1268  newotri->tri[0] = (triangle)m->dummytri;
1269  newotri->tri[1] = (triangle)m->dummytri;
1270  newotri->tri[2] = (triangle)m->dummytri;
1271  /* Three NULL vertices. */
1272  newotri->tri[3] = (triangle)NULL;
1273  newotri->tri[4] = (triangle)NULL;
1274  newotri->tri[5] = (triangle)NULL;
1275  if (b->usesegments)
1276  {
1277  /* Initialize the three adjoining subsegments to be the omnipresent */
1278  /* subsegment. */
1279  newotri->tri[6] = (triangle)m->dummysub;
1280  newotri->tri[7] = (triangle)m->dummysub;
1281  newotri->tri[8] = (triangle)m->dummysub;
1282  }
1283  for (i = 0; i < m->eextras; i++)
1284  {
1285  setelemattribute(*newotri, i, 0.0);
1286  }
1287 
1288  newotri->orient = 0;
1289 }
void * poolalloc(struct memorypool *pool)
#define setelemattribute(otri, attnum, value)
void Nektar::NekMeshUtils::DelaunayTriangle::makevertexmap ( struct mesh m,
struct behavior b 
)
private

Definition at line 3898 of file Triangle/Triangle.cpp.

References encode, org, Nektar::NekMeshUtils::otri::orient, setvertex2tri, traversalinit(), Nektar::NekMeshUtils::otri::tri, Nektar::NekMeshUtils::mesh::triangles, and triangletraverse().

Referenced by formskeleton().

3899 {
3900  struct otri triangleloop;
3901  vertex triorg;
3902 
3903  traversalinit(&m->triangles);
3904  triangleloop.tri = triangletraverse(m);
3905  while (triangleloop.tri != (triangle *)NULL)
3906  {
3907  /* Check all three vertices of the triangle. */
3908  for (triangleloop.orient = 0; triangleloop.orient < 3;
3909  triangleloop.orient++)
3910  {
3911  org(triangleloop, triorg);
3912  setvertex2tri(triorg, encode(triangleloop));
3913  }
3914  triangleloop.tri = triangletraverse(m);
3915  }
3916 }
void traversalinit(struct memorypool *pool)
#define setvertex2tri(vx, value)
triangle * triangletraverse(struct mesh *m)
#define org(otri, vertexptr)
#define encode(otri)
void Nektar::NekMeshUtils::DelaunayTriangle::markhull ( struct mesh m,
struct behavior b 
)
private

Definition at line 7245 of file Triangle/Triangle.cpp.

References Nektar::NekMeshUtils::mesh::dummytri, insertsubseg(), lnextself, oprev, Nektar::NekMeshUtils::otri::orient, otricopy, otriequal, symself, and Nektar::NekMeshUtils::otri::tri.

Referenced by formskeleton().

7246 {
7247  struct otri hulltri;
7248  struct otri nexttri;
7249  struct otri starttri;
7250  triangle ptr; /* Temporary variable used by sym() and oprev(). */
7251 
7252  /* Find a triangle handle on the hull. */
7253  hulltri.tri = m->dummytri;
7254  hulltri.orient = 0;
7255  symself(hulltri);
7256  /* Remember where we started so we know when to stop. */
7257  otricopy(hulltri, starttri);
7258  /* Go once counterclockwise around the convex hull. */
7259  do
7260  {
7261  /* Create a subsegment if there isn't already one here. */
7262  insertsubseg(m, b, &hulltri, 1);
7263  /* To find the next hull edge, go clockwise around the next vertex. */
7264  lnextself(hulltri);
7265  oprev(hulltri, nexttri);
7266  while (nexttri.tri != m->dummytri)
7267  {
7268  otricopy(nexttri, hulltri);
7269  oprev(hulltri, nexttri);
7270  }
7271  } while (!otriequal(hulltri, starttri));
7272 }
#define otriequal(otri1, otri2)
#define lnextself(otri)
void insertsubseg(struct mesh *m, struct behavior *b, struct otri *tri, int subsegmark)
#define symself(otri)
#define oprev(otri1, otri2)
#define otricopy(otri1, otri2)
void Nektar::NekMeshUtils::DelaunayTriangle::mergehulls ( struct mesh m,
struct behavior b,
struct otri farleft,
struct otri innerleft,
struct otri innerright,
struct otri farright,
int  axis 
)
private

Definition at line 5785 of file Triangle/Triangle.cpp.

References apex, bond, counterclockwise(), dest, incircle(), lnext, lnextself, lprev, lprevself, maketriangle(), org, otricopy, setapex, setdest, setorg, sym, and symself.

Referenced by divconqrecurse().

5792 {
5793  struct otri leftcand, rightcand;
5794  struct otri baseedge;
5795  struct otri nextedge;
5796  struct otri sidecasing, topcasing, outercasing;
5797  struct otri checkedge;
5798  vertex innerleftdest;
5799  vertex innerrightorg;
5800  vertex innerleftapex, innerrightapex;
5801  vertex farleftpt, farrightpt;
5802  vertex farleftapex, farrightapex;
5803  vertex lowerleft, lowerright;
5804  vertex upperleft, upperright;
5805  vertex nextapex;
5806  vertex checkvertex;
5807  int changemade;
5808  int badedge;
5809  int leftfinished, rightfinished;
5810  triangle ptr; /* Temporary variable used by sym(). */
5811 
5812  dest(*innerleft, innerleftdest);
5813  apex(*innerleft, innerleftapex);
5814  org(*innerright, innerrightorg);
5815  apex(*innerright, innerrightapex);
5816  /* Special treatment for horizontal cuts. */
5817  if (axis == 1)
5818  {
5819  org(*farleft, farleftpt);
5820  apex(*farleft, farleftapex);
5821  dest(*farright, farrightpt);
5822  apex(*farright, farrightapex);
5823  /* The pointers to the extremal vertices are shifted to point to the */
5824  /* topmost and bottommost vertex of each hull, rather than the */
5825  /* leftmost and rightmost vertices. */
5826  while (farleftapex[1] < farleftpt[1])
5827  {
5828  lnextself(*farleft);
5829  symself(*farleft);
5830  farleftpt = farleftapex;
5831  apex(*farleft, farleftapex);
5832  }
5833  sym(*innerleft, checkedge);
5834  apex(checkedge, checkvertex);
5835  while (checkvertex[1] > innerleftdest[1])
5836  {
5837  lnext(checkedge, *innerleft);
5838  innerleftapex = innerleftdest;
5839  innerleftdest = checkvertex;
5840  sym(*innerleft, checkedge);
5841  apex(checkedge, checkvertex);
5842  }
5843  while (innerrightapex[1] < innerrightorg[1])
5844  {
5845  lnextself(*innerright);
5846  symself(*innerright);
5847  innerrightorg = innerrightapex;
5848  apex(*innerright, innerrightapex);
5849  }
5850  sym(*farright, checkedge);
5851  apex(checkedge, checkvertex);
5852  while (checkvertex[1] > farrightpt[1])
5853  {
5854  lnext(checkedge, *farright);
5855  farrightapex = farrightpt;
5856  farrightpt = checkvertex;
5857  sym(*farright, checkedge);
5858  apex(checkedge, checkvertex);
5859  }
5860  }
5861  /* Find a line tangent to and below both hulls. */
5862  do
5863  {
5864  changemade = 0;
5865  /* Make innerleftdest the "bottommost" vertex of the left hull. */
5866  if (counterclockwise(
5867  m, b, innerleftdest, innerleftapex, innerrightorg) > 0.0)
5868  {
5869  lprevself(*innerleft);
5870  symself(*innerleft);
5871  innerleftdest = innerleftapex;
5872  apex(*innerleft, innerleftapex);
5873  changemade = 1;
5874  }
5875  /* Make innerrightorg the "bottommost" vertex of the right hull. */
5876  if (counterclockwise(
5877  m, b, innerrightapex, innerrightorg, innerleftdest) > 0.0)
5878  {
5879  lnextself(*innerright);
5880  symself(*innerright);
5881  innerrightorg = innerrightapex;
5882  apex(*innerright, innerrightapex);
5883  changemade = 1;
5884  }
5885  } while (changemade);
5886  /* Find the two candidates to be the next "gear tooth." */
5887  sym(*innerleft, leftcand);
5888  sym(*innerright, rightcand);
5889  /* Create the bottom new bounding triangle. */
5890  maketriangle(m, b, &baseedge);
5891  /* Connect it to the bounding boxes of the left and right triangulations. */
5892  bond(baseedge, *innerleft);
5893  lnextself(baseedge);
5894  bond(baseedge, *innerright);
5895  lnextself(baseedge);
5896  setorg(baseedge, innerrightorg);
5897  setdest(baseedge, innerleftdest);
5898  /* Apex is intentionally left NULL. */
5899 
5900  /* Fix the extreme triangles if necessary. */
5901  org(*farleft, farleftpt);
5902  if (innerleftdest == farleftpt)
5903  {
5904  lnext(baseedge, *farleft);
5905  }
5906  dest(*farright, farrightpt);
5907  if (innerrightorg == farrightpt)
5908  {
5909  lprev(baseedge, *farright);
5910  }
5911  /* The vertices of the current knitting edge. */
5912  lowerleft = innerleftdest;
5913  lowerright = innerrightorg;
5914  /* The candidate vertices for knitting. */
5915  apex(leftcand, upperleft);
5916  apex(rightcand, upperright);
5917  /* Walk up the gap between the two triangulations, knitting them together.
5918  */
5919  while (1)
5920  {
5921  /* Have we reached the top? (This isn't quite the right question, */
5922  /* because even though the left triangulation might seem finished now,
5923  */
5924  /* moving up on the right triangulation might reveal a new vertex of
5925  */
5926  /* the left triangulation. And vice-versa.) */
5927  leftfinished =
5928  counterclockwise(m, b, upperleft, lowerleft, lowerright) <= 0.0;
5929  rightfinished =
5930  counterclockwise(m, b, upperright, lowerleft, lowerright) <= 0.0;
5931  if (leftfinished && rightfinished)
5932  {
5933  /* Create the top new bounding triangle. */
5934  maketriangle(m, b, &nextedge);
5935  setorg(nextedge, lowerleft);
5936  setdest(nextedge, lowerright);
5937  /* Apex is intentionally left NULL. */
5938  /* Connect it to the bounding boxes of the two triangulations. */
5939  bond(nextedge, baseedge);
5940  lnextself(nextedge);
5941  bond(nextedge, rightcand);
5942  lnextself(nextedge);
5943  bond(nextedge, leftcand);
5944 
5945  /* Special treatment for horizontal cuts. */
5946  if (axis == 1)
5947  {
5948  org(*farleft, farleftpt);
5949  apex(*farleft, farleftapex);
5950  dest(*farright, farrightpt);
5951  apex(*farright, farrightapex);
5952  sym(*farleft, checkedge);
5953  apex(checkedge, checkvertex);
5954  /* The pointers to the extremal vertices are restored to the */
5955  /* leftmost and rightmost vertices (rather than topmost and */
5956  /* bottommost). */
5957  while (checkvertex[0] < farleftpt[0])
5958  {
5959  lprev(checkedge, *farleft);
5960  farleftapex = farleftpt;
5961  farleftpt = checkvertex;
5962  sym(*farleft, checkedge);
5963  apex(checkedge, checkvertex);
5964  }
5965  while (farrightapex[0] > farrightpt[0])
5966  {
5967  lprevself(*farright);
5968  symself(*farright);
5969  farrightpt = farrightapex;
5970  apex(*farright, farrightapex);
5971  }
5972  }
5973  return;
5974  }
5975  /* Consider eliminating edges from the left triangulation. */
5976  if (!leftfinished)
5977  {
5978  /* What vertex would be exposed if an edge were deleted? */
5979  lprev(leftcand, nextedge);
5980  symself(nextedge);
5981  apex(nextedge, nextapex);
5982  /* If nextapex is NULL, then no vertex would be exposed; the */
5983  /* triangulation would have been eaten right through. */
5984  if (nextapex != (vertex)NULL)
5985  {
5986  /* Check whether the edge is Delaunay. */
5987  badedge =
5988  incircle(m, b, lowerleft, lowerright, upperleft, nextapex) >
5989  0.0;
5990  while (badedge)
5991  {
5992  /* Eliminate the edge with an edge flip. As a result, the
5993  */
5994  /* left triangulation will have one more boundary
5995  * triangle. */
5996  lnextself(nextedge);
5997  sym(nextedge, topcasing);
5998  lnextself(nextedge);
5999  sym(nextedge, sidecasing);
6000  bond(nextedge, topcasing);
6001  bond(leftcand, sidecasing);
6002  lnextself(leftcand);
6003  sym(leftcand, outercasing);
6004  lprevself(nextedge);
6005  bond(nextedge, outercasing);
6006  /* Correct the vertices to reflect the edge flip. */
6007  setorg(leftcand, lowerleft);
6008  setdest(leftcand, NULL);
6009  setapex(leftcand, nextapex);
6010  setorg(nextedge, NULL);
6011  setdest(nextedge, upperleft);
6012  setapex(nextedge, nextapex);
6013  /* Consider the newly exposed vertex. */
6014  upperleft = nextapex;
6015  /* What vertex would be exposed if another edge were
6016  * deleted? */
6017  otricopy(sidecasing, nextedge);
6018  apex(nextedge, nextapex);
6019  if (nextapex != (vertex)NULL)
6020  {
6021  /* Check whether the edge is Delaunay. */
6022  badedge = incircle(m,
6023  b,
6024  lowerleft,
6025  lowerright,
6026  upperleft,
6027  nextapex) > 0.0;
6028  }
6029  else
6030  {
6031  /* Avoid eating right through the triangulation. */
6032  badedge = 0;
6033  }
6034  }
6035  }
6036  }
6037  /* Consider eliminating edges from the right triangulation. */
6038  if (!rightfinished)
6039  {
6040  /* What vertex would be exposed if an edge were deleted? */
6041  lnext(rightcand, nextedge);
6042  symself(nextedge);
6043  apex(nextedge, nextapex);
6044  /* If nextapex is NULL, then no vertex would be exposed; the */
6045  /* triangulation would have been eaten right through. */
6046  if (nextapex != (vertex)NULL)
6047  {
6048  /* Check whether the edge is Delaunay. */
6049  badedge =
6050  incircle(
6051  m, b, lowerleft, lowerright, upperright, nextapex) >
6052  0.0;
6053  while (badedge)
6054  {
6055  /* Eliminate the edge with an edge flip. As a result, the
6056  */
6057  /* right triangulation will have one more boundary
6058  * triangle. */
6059  lprevself(nextedge);
6060  sym(nextedge, topcasing);
6061  lprevself(nextedge);
6062  sym(nextedge, sidecasing);
6063  bond(nextedge, topcasing);
6064  bond(rightcand, sidecasing);
6065  lprevself(rightcand);
6066  sym(rightcand, outercasing);
6067  lnextself(nextedge);
6068  bond(nextedge, outercasing);
6069  /* Correct the vertices to reflect the edge flip. */
6070  setorg(rightcand, NULL);
6071  setdest(rightcand, lowerright);
6072  setapex(rightcand, nextapex);
6073  setorg(nextedge, upperright);
6074  setdest(nextedge, NULL);
6075  setapex(nextedge, nextapex);
6076  /* Consider the newly exposed vertex. */
6077  upperright = nextapex;
6078  /* What vertex would be exposed if another edge were
6079  * deleted? */
6080  otricopy(sidecasing, nextedge);
6081  apex(nextedge, nextapex);
6082  if (nextapex != (vertex)NULL)
6083  {
6084  /* Check whether the edge is Delaunay. */
6085  badedge = incircle(m,
6086  b,
6087  lowerleft,
6088  lowerright,
6089  upperright,
6090  nextapex) > 0.0;
6091  }
6092  else
6093  {
6094  /* Avoid eating right through the triangulation. */
6095  badedge = 0;
6096  }
6097  }
6098  }
6099  }
6100  if (leftfinished ||
6101  (!rightfinished &&
6102  (incircle(m, b, upperleft, lowerleft, lowerright, upperright) >
6103  0.0)))
6104  {
6105  /* Knit the triangulations, adding an edge from `lowerleft' */
6106  /* to `upperright'. */
6107  bond(baseedge, rightcand);
6108  lprev(rightcand, baseedge);
6109  setdest(baseedge, lowerleft);
6110  lowerright = upperright;
6111  sym(baseedge, rightcand);
6112  apex(rightcand, upperright);
6113  }
6114  else
6115  {
6116  /* Knit the triangulations, adding an edge from `upperleft' */
6117  /* to `lowerright'. */
6118  bond(baseedge, leftcand);
6119  lnext(leftcand, baseedge);
6120  setorg(baseedge, lowerright);
6121  lowerleft = upperleft;
6122  sym(baseedge, leftcand);
6123  apex(leftcand, upperleft);
6124  }
6125  }
6126 }
#define setdest(otri, vertexptr)
#define bond(otri1, otri2)
double incircle(struct mesh *m, struct behavior *b, vertex pa, vertex pb, vertex pc, vertex pd)
#define setapex(otri, vertexptr)
void maketriangle(struct mesh *m, struct behavior *b, struct otri *newotri)
#define setorg(otri, vertexptr)
#define sym(otri1, otri2)
#define lprev(otri1, otri2)
#define lnextself(otri)
#define symself(otri)
double counterclockwise(struct mesh *m, struct behavior *b, vertex pa, vertex pb, vertex pc)
#define lprevself(otri)
#define apex(otri, vertexptr)
#define otricopy(otri1, otri2)
#define lnext(otri1, otri2)
#define dest(otri, vertexptr)
#define org(otri, vertexptr)
double Nektar::NekMeshUtils::DelaunayTriangle::nonregular ( struct mesh m,
struct behavior b,
vertex  pa,
vertex  pb,
vertex  pc,
vertex  pd 
)
private

Definition at line 3222 of file Triangle/Triangle.cpp.

References incircle(), orient3d(), and Nektar::NekMeshUtils::behavior::weighted.

3228 {
3229  if (b->weighted == 0)
3230  {
3231  return incircle(m, b, pa, pb, pc, pd);
3232  }
3233  else if (b->weighted == 1)
3234  {
3235  return orient3d(m,
3236  b,
3237  pa,
3238  pb,
3239  pc,
3240  pd,
3241  pa[0] * pa[0] + pa[1] * pa[1] - pa[2],
3242  pb[0] * pb[0] + pb[1] * pb[1] - pb[2],
3243  pc[0] * pc[0] + pc[1] * pc[1] - pc[2],
3244  pd[0] * pd[0] + pd[1] * pd[1] - pd[2]);
3245  }
3246  else
3247  {
3248  return orient3d(m, b, pa, pb, pc, pd, pa[2], pb[2], pc[2], pd[2]);
3249  }
3250 }
double incircle(struct mesh *m, struct behavior *b, vertex pa, vertex pb, vertex pc, vertex pd)
double orient3d(struct mesh *m, struct behavior *b, vertex pa, vertex pb, vertex pc, vertex pd, double aheight, double bheight, double cheight, double dheight)
void Nektar::NekMeshUtils::DelaunayTriangle::numbernodes ( struct mesh m,
struct behavior b 
)
private

Definition at line 8609 of file Triangle/Triangle.cpp.

References Nektar::NekMeshUtils::behavior::jettison, setvertexmark, traversalinit(), UNDEADVERTEX, vertextraverse(), vertextype, and Nektar::NekMeshUtils::mesh::vertices.

8610 {
8611  vertex vertexloop;
8612  int vertexnumber;
8613 
8614  traversalinit(&m->vertices);
8615  vertexnumber = 0;
8616  vertexloop = vertextraverse(m);
8617  while (vertexloop != (vertex)NULL)
8618  {
8619  setvertexmark(vertexloop, vertexnumber);
8620  if (!b->jettison || (vertextype(vertexloop) != UNDEADVERTEX))
8621  {
8622  vertexnumber++;
8623  }
8624  vertexloop = vertextraverse(m);
8625  }
8626 }
#define UNDEADVERTEX
void traversalinit(struct memorypool *pool)
#define vertextype(vx)
#define setvertexmark(vx, value)
double Nektar::NekMeshUtils::DelaunayTriangle::orient3d ( struct mesh m,
struct behavior b,
vertex  pa,
vertex  pb,
vertex  pc,
vertex  pd,
double  aheight,
double  bheight,
double  cheight,
double  dheight 
)
private

Definition at line 3151 of file Triangle/Triangle.cpp.

References Absolute, o3derrboundA, orient3dadapt(), and Nektar::NekMeshUtils::mesh::orient3dcount.

Referenced by nonregular().

3161 {
3162  double adx, bdx, cdx, ady, bdy, cdy, adheight, bdheight, cdheight;
3163  double bdxcdy, cdxbdy, cdxady, adxcdy, adxbdy, bdxady;
3164  double det;
3165  double permanent, errbound;
3166 
3167  m->orient3dcount++;
3168 
3169  adx = pa[0] - pd[0];
3170  bdx = pb[0] - pd[0];
3171  cdx = pc[0] - pd[0];
3172  ady = pa[1] - pd[1];
3173  bdy = pb[1] - pd[1];
3174  cdy = pc[1] - pd[1];
3175  adheight = aheight - dheight;
3176  bdheight = bheight - dheight;
3177  cdheight = cheight - dheight;
3178 
3179  bdxcdy = bdx * cdy;
3180  cdxbdy = cdx * bdy;
3181 
3182  cdxady = cdx * ady;
3183  adxcdy = adx * cdy;
3184 
3185  adxbdy = adx * bdy;
3186  bdxady = bdx * ady;
3187 
3188  det = adheight * (bdxcdy - cdxbdy) + bdheight * (cdxady - adxcdy) +
3189  cdheight * (adxbdy - bdxady);
3190 
3191  permanent = (Absolute(bdxcdy) + Absolute(cdxbdy)) * Absolute(adheight) +
3192  (Absolute(cdxady) + Absolute(adxcdy)) * Absolute(bdheight) +
3193  (Absolute(adxbdy) + Absolute(bdxady)) * Absolute(cdheight);
3194  errbound = o3derrboundA * permanent;
3195  if ((det > errbound) || (-det > errbound))
3196  {
3197  return det;
3198  }
3199 
3200  return orient3dadapt(
3201  pa, pb, pc, pd, aheight, bheight, cheight, dheight, permanent);
3202 }
#define Absolute(a)
double orient3dadapt(vertex pa, vertex pb, vertex pc, vertex pd, double aheight, double bheight, double cheight, double dheight, double permanent)
double Nektar::NekMeshUtils::DelaunayTriangle::orient3dadapt ( vertex  pa,
vertex  pb,
vertex  pc,
vertex  pd,
double  aheight,
double  bheight,
double  cheight,
double  dheight,
double  permanent 
)
private

Definition at line 2602 of file Triangle/Triangle.cpp.

References Absolute, estimateTRI(), fast_expansion_sum_zeroelimTRI(), Nektar::negate(), o3derrboundB, o3derrboundC, resulterrbound, scale_expansion_zeroelimTRI(), Two_Diff_Tail, Two_One_Product, Two_Product, and Two_Two_Diff.

Referenced by orient3d().

2611 {
2612  double adx, bdx, cdx, ady, bdy, cdy, adheight, bdheight, cdheight;
2613  double det, errbound;
2614 
2615  double bdxcdy1, cdxbdy1, cdxady1, adxcdy1, adxbdy1, bdxady1;
2616  double bdxcdy0, cdxbdy0, cdxady0, adxcdy0, adxbdy0, bdxady0;
2617  double bc[4], ca[4], ab[4];
2618  double bc3, ca3, ab3;
2619  double adet[8], bdet[8], cdet[8];
2620  int alen, blen, clen;
2621  double abdet[16];
2622  int ablen;
2623  double *finnow, *finother, *finswap;
2624  double fin1[192], fin2[192];
2625  int finlength;
2626 
2627  double adxtail, bdxtail, cdxtail;
2628  double adytail, bdytail, cdytail;
2629  double adheighttail, bdheighttail, cdheighttail;
2630  double at_blarge, at_clarge;
2631  double bt_clarge, bt_alarge;
2632  double ct_alarge, ct_blarge;
2633  double at_b[4], at_c[4], bt_c[4], bt_a[4], ct_a[4], ct_b[4];
2634  int at_blen, at_clen, bt_clen, bt_alen, ct_alen, ct_blen;
2635  double bdxt_cdy1, cdxt_bdy1, cdxt_ady1;
2636  double adxt_cdy1, adxt_bdy1, bdxt_ady1;
2637  double bdxt_cdy0, cdxt_bdy0, cdxt_ady0;
2638  double adxt_cdy0, adxt_bdy0, bdxt_ady0;
2639  double bdyt_cdx1, cdyt_bdx1, cdyt_adx1;
2640  double adyt_cdx1, adyt_bdx1, bdyt_adx1;
2641  double bdyt_cdx0, cdyt_bdx0, cdyt_adx0;
2642  double adyt_cdx0, adyt_bdx0, bdyt_adx0;
2643  double bct[8], cat[8], abt[8];
2644  int bctlen, catlen, abtlen;
2645  double bdxt_cdyt1, cdxt_bdyt1, cdxt_adyt1;
2646  double adxt_cdyt1, adxt_bdyt1, bdxt_adyt1;
2647  double bdxt_cdyt0, cdxt_bdyt0, cdxt_adyt0;
2648  double adxt_cdyt0, adxt_bdyt0, bdxt_adyt0;
2649  double u[4], v[12], w[16];
2650  double u3;
2651  int vlength, wlength;
2652  double negate;
2653 
2654  double bvirt;
2655  double avirt, bround, around;
2656  double c;
2657  double abig;
2658  double ahi, alo, bhi, blo;
2659  double err1, err2, err3;
2660  double _i, _j, _k;
2661  double _0;
2662 
2663  adx = (double)(pa[0] - pd[0]);
2664  bdx = (double)(pb[0] - pd[0]);
2665  cdx = (double)(pc[0] - pd[0]);
2666  ady = (double)(pa[1] - pd[1]);
2667  bdy = (double)(pb[1] - pd[1]);
2668  cdy = (double)(pc[1] - pd[1]);
2669  adheight = (double)(aheight - dheight);
2670  bdheight = (double)(bheight - dheight);
2671  cdheight = (double)(cheight - dheight);
2672 
2673  Two_Product(bdx, cdy, bdxcdy1, bdxcdy0);
2674  Two_Product(cdx, bdy, cdxbdy1, cdxbdy0);
2675  Two_Two_Diff(bdxcdy1, bdxcdy0, cdxbdy1, cdxbdy0, bc3, bc[2], bc[1], bc[0]);
2676  bc[3] = bc3;
2677  alen = scale_expansion_zeroelimTRI(4, bc, adheight, adet);
2678 
2679  Two_Product(cdx, ady, cdxady1, cdxady0);
2680  Two_Product(adx, cdy, adxcdy1, adxcdy0);
2681  Two_Two_Diff(cdxady1, cdxady0, adxcdy1, adxcdy0, ca3, ca[2], ca[1], ca[0]);
2682  ca[3] = ca3;
2683  blen = scale_expansion_zeroelimTRI(4, ca, bdheight, bdet);
2684 
2685  Two_Product(adx, bdy, adxbdy1, adxbdy0);
2686  Two_Product(bdx, ady, bdxady1, bdxady0);
2687  Two_Two_Diff(adxbdy1, adxbdy0, bdxady1, bdxady0, ab3, ab[2], ab[1], ab[0]);
2688  ab[3] = ab3;
2689  clen = scale_expansion_zeroelimTRI(4, ab, cdheight, cdet);
2690 
2691  ablen = fast_expansion_sum_zeroelimTRI(alen, adet, blen, bdet, abdet);
2692  finlength = fast_expansion_sum_zeroelimTRI(ablen, abdet, clen, cdet, fin1);
2693 
2694  det = estimateTRI(finlength, fin1);
2695  errbound = o3derrboundB * permanent;
2696  if ((det >= errbound) || (-det >= errbound))
2697  {
2698  return det;
2699  }
2700 
2701  Two_Diff_Tail(pa[0], pd[0], adx, adxtail);
2702  Two_Diff_Tail(pb[0], pd[0], bdx, bdxtail);
2703  Two_Diff_Tail(pc[0], pd[0], cdx, cdxtail);
2704  Two_Diff_Tail(pa[1], pd[1], ady, adytail);
2705  Two_Diff_Tail(pb[1], pd[1], bdy, bdytail);
2706  Two_Diff_Tail(pc[1], pd[1], cdy, cdytail);
2707  Two_Diff_Tail(aheight, dheight, adheight, adheighttail);
2708  Two_Diff_Tail(bheight, dheight, bdheight, bdheighttail);
2709  Two_Diff_Tail(cheight, dheight, cdheight, cdheighttail);
2710 
2711  if ((adxtail == 0.0) && (bdxtail == 0.0) && (cdxtail == 0.0) &&
2712  (adytail == 0.0) && (bdytail == 0.0) && (cdytail == 0.0) &&
2713  (adheighttail == 0.0) && (bdheighttail == 0.0) && (cdheighttail == 0.0))
2714  {
2715  return det;
2716  }
2717 
2718  errbound = o3derrboundC * permanent + resulterrbound * Absolute(det);
2719  det += (adheight * ((bdx * cdytail + cdy * bdxtail) -
2720  (bdy * cdxtail + cdx * bdytail)) +
2721  adheighttail * (bdx * cdy - bdy * cdx)) +
2722  (bdheight * ((cdx * adytail + ady * cdxtail) -
2723  (cdy * adxtail + adx * cdytail)) +
2724  bdheighttail * (cdx * ady - cdy * adx)) +
2725  (cdheight * ((adx * bdytail + bdy * adxtail) -
2726  (ady * bdxtail + bdx * adytail)) +
2727  cdheighttail * (adx * bdy - ady * bdx));
2728  if ((det >= errbound) || (-det >= errbound))
2729  {
2730  return det;
2731  }
2732 
2733  finnow = fin1;
2734  finother = fin2;
2735 
2736  if (adxtail == 0.0)
2737  {
2738  if (adytail == 0.0)
2739  {
2740  at_b[0] = 0.0;
2741  at_blen = 1;
2742  at_c[0] = 0.0;
2743  at_clen = 1;
2744  }
2745  else
2746  {
2747  negate = -adytail;
2748  Two_Product(negate, bdx, at_blarge, at_b[0]);
2749  at_b[1] = at_blarge;
2750  at_blen = 2;
2751  Two_Product(adytail, cdx, at_clarge, at_c[0]);
2752  at_c[1] = at_clarge;
2753  at_clen = 2;
2754  }
2755  }
2756  else
2757  {
2758  if (adytail == 0.0)
2759  {
2760  Two_Product(adxtail, bdy, at_blarge, at_b[0]);
2761  at_b[1] = at_blarge;
2762  at_blen = 2;
2763  negate = -adxtail;
2764  Two_Product(negate, cdy, at_clarge, at_c[0]);
2765  at_c[1] = at_clarge;
2766  at_clen = 2;
2767  }
2768  else
2769  {
2770  Two_Product(adxtail, bdy, adxt_bdy1, adxt_bdy0);
2771  Two_Product(adytail, bdx, adyt_bdx1, adyt_bdx0);
2772  Two_Two_Diff(adxt_bdy1,
2773  adxt_bdy0,
2774  adyt_bdx1,
2775  adyt_bdx0,
2776  at_blarge,
2777  at_b[2],
2778  at_b[1],
2779  at_b[0]);
2780  at_b[3] = at_blarge;
2781  at_blen = 4;
2782  Two_Product(adytail, cdx, adyt_cdx1, adyt_cdx0);
2783  Two_Product(adxtail, cdy, adxt_cdy1, adxt_cdy0);
2784  Two_Two_Diff(adyt_cdx1,
2785  adyt_cdx0,
2786  adxt_cdy1,
2787  adxt_cdy0,
2788  at_clarge,
2789  at_c[2],
2790  at_c[1],
2791  at_c[0]);
2792  at_c[3] = at_clarge;
2793  at_clen = 4;
2794  }
2795  }
2796  if (bdxtail == 0.0)
2797  {
2798  if (bdytail == 0.0)
2799  {
2800  bt_c[0] = 0.0;
2801  bt_clen = 1;
2802  bt_a[0] = 0.0;
2803  bt_alen = 1;
2804  }
2805  else
2806  {
2807  negate = -bdytail;
2808  Two_Product(negate, cdx, bt_clarge, bt_c[0]);
2809  bt_c[1] = bt_clarge;
2810  bt_clen = 2;
2811  Two_Product(bdytail, adx, bt_alarge, bt_a[0]);
2812  bt_a[1] = bt_alarge;
2813  bt_alen = 2;
2814  }
2815  }
2816  else
2817  {
2818  if (bdytail == 0.0)
2819  {
2820  Two_Product(bdxtail, cdy, bt_clarge, bt_c[0]);
2821  bt_c[1] = bt_clarge;
2822  bt_clen = 2;
2823  negate = -bdxtail;
2824  Two_Product(negate, ady, bt_alarge, bt_a[0]);
2825  bt_a[1] = bt_alarge;
2826  bt_alen = 2;
2827  }
2828  else
2829  {
2830  Two_Product(bdxtail, cdy, bdxt_cdy1, bdxt_cdy0);
2831  Two_Product(bdytail, cdx, bdyt_cdx1, bdyt_cdx0);
2832  Two_Two_Diff(bdxt_cdy1,
2833  bdxt_cdy0,
2834  bdyt_cdx1,
2835  bdyt_cdx0,
2836  bt_clarge,
2837  bt_c[2],
2838  bt_c[1],
2839  bt_c[0]);
2840  bt_c[3] = bt_clarge;
2841  bt_clen = 4;
2842  Two_Product(bdytail, adx, bdyt_adx1, bdyt_adx0);
2843  Two_Product(bdxtail, ady, bdxt_ady1, bdxt_ady0);
2844  Two_Two_Diff(bdyt_adx1,
2845  bdyt_adx0,
2846  bdxt_ady1,
2847  bdxt_ady0,
2848  bt_alarge,
2849  bt_a[2],
2850  bt_a[1],
2851  bt_a[0]);
2852  bt_a[3] = bt_alarge;
2853  bt_alen = 4;
2854  }
2855  }
2856  if (cdxtail == 0.0)
2857  {
2858  if (cdytail == 0.0)
2859  {
2860  ct_a[0] = 0.0;
2861  ct_alen = 1;
2862  ct_b[0] = 0.0;
2863  ct_blen = 1;
2864  }
2865  else
2866  {
2867  negate = -cdytail;
2868  Two_Product(negate, adx, ct_alarge, ct_a[0]);
2869  ct_a[1] = ct_alarge;
2870  ct_alen = 2;
2871  Two_Product(cdytail, bdx, ct_blarge, ct_b[0]);
2872  ct_b[1] = ct_blarge;
2873  ct_blen = 2;
2874  }
2875  }
2876  else
2877  {
2878  if (cdytail == 0.0)
2879  {
2880  Two_Product(cdxtail, ady, ct_alarge, ct_a[0]);
2881  ct_a[1] = ct_alarge;
2882  ct_alen = 2;
2883  negate = -cdxtail;
2884  Two_Product(negate, bdy, ct_blarge, ct_b[0]);
2885  ct_b[1] = ct_blarge;
2886  ct_blen = 2;
2887  }
2888  else
2889  {
2890  Two_Product(cdxtail, ady, cdxt_ady1, cdxt_ady0);
2891  Two_Product(cdytail, adx, cdyt_adx1, cdyt_adx0);
2892  Two_Two_Diff(cdxt_ady1,
2893  cdxt_ady0,
2894  cdyt_adx1,
2895  cdyt_adx0,
2896  ct_alarge,
2897  ct_a[2],
2898  ct_a[1],
2899  ct_a[0]);
2900  ct_a[3] = ct_alarge;
2901  ct_alen = 4;
2902  Two_Product(cdytail, bdx, cdyt_bdx1, cdyt_bdx0);
2903  Two_Product(cdxtail, bdy, cdxt_bdy1, cdxt_bdy0);
2904  Two_Two_Diff(cdyt_bdx1,
2905  cdyt_bdx0,
2906  cdxt_bdy1,
2907  cdxt_bdy0,
2908  ct_blarge,
2909  ct_b[2],
2910  ct_b[1],
2911  ct_b[0]);
2912  ct_b[3] = ct_blarge;
2913  ct_blen = 4;
2914  }
2915  }
2916 
2917  bctlen = fast_expansion_sum_zeroelimTRI(bt_clen, bt_c, ct_blen, ct_b, bct);
2918  wlength = scale_expansion_zeroelimTRI(bctlen, bct, adheight, w);
2919  finlength =
2920  fast_expansion_sum_zeroelimTRI(finlength, finnow, wlength, w, finother);
2921  finswap = finnow;
2922  finnow = finother;
2923  finother = finswap;
2924 
2925  catlen = fast_expansion_sum_zeroelimTRI(ct_alen, ct_a, at_clen, at_c, cat);
2926  wlength = scale_expansion_zeroelimTRI(catlen, cat, bdheight, w);
2927  finlength =
2928  fast_expansion_sum_zeroelimTRI(finlength, finnow, wlength, w, finother);
2929  finswap = finnow;
2930  finnow = finother;
2931  finother = finswap;
2932 
2933  abtlen = fast_expansion_sum_zeroelimTRI(at_blen, at_b, bt_alen, bt_a, abt);
2934  wlength = scale_expansion_zeroelimTRI(abtlen, abt, cdheight, w);
2935  finlength =
2936  fast_expansion_sum_zeroelimTRI(finlength, finnow, wlength, w, finother);
2937  finswap = finnow;
2938  finnow = finother;
2939  finother = finswap;
2940 
2941  if (adheighttail != 0.0)
2942  {
2943  vlength = scale_expansion_zeroelimTRI(4, bc, adheighttail, v);
2944  finlength = fast_expansion_sum_zeroelimTRI(
2945  finlength, finnow, vlength, v, finother);
2946  finswap = finnow;
2947  finnow = finother;
2948  finother = finswap;
2949  }
2950  if (bdheighttail != 0.0)
2951  {
2952  vlength = scale_expansion_zeroelimTRI(4, ca, bdheighttail, v);
2953  finlength = fast_expansion_sum_zeroelimTRI(
2954  finlength, finnow, vlength, v, finother);
2955  finswap = finnow;
2956  finnow = finother;
2957  finother = finswap;
2958  }
2959  if (cdheighttail != 0.0)
2960  {
2961  vlength = scale_expansion_zeroelimTRI(4, ab, cdheighttail, v);
2962  finlength = fast_expansion_sum_zeroelimTRI(
2963  finlength, finnow, vlength, v, finother);
2964  finswap = finnow;
2965  finnow = finother;
2966  finother = finswap;
2967  }
2968 
2969  if (adxtail != 0.0)
2970  {
2971  if (bdytail != 0.0)
2972  {
2973  Two_Product(adxtail, bdytail, adxt_bdyt1, adxt_bdyt0);
2975  adxt_bdyt1, adxt_bdyt0, cdheight, u3, u[2], u[1], u[0]);
2976  u[3] = u3;
2977  finlength =
2978  fast_expansion_sum_zeroelimTRI(finlength, finnow, 4, u, finother);
2979  finswap = finnow;
2980  finnow = finother;
2981  finother = finswap;
2982  if (cdheighttail != 0.0)
2983  {
2985  adxt_bdyt1, adxt_bdyt0, cdheighttail, u3, u[2], u[1], u[0]);
2986  u[3] = u3;
2987  finlength = fast_expansion_sum_zeroelimTRI(
2988  finlength, finnow, 4, u, finother);
2989  finswap = finnow;
2990  finnow = finother;
2991  finother = finswap;
2992  }
2993  }
2994  if (cdytail != 0.0)
2995  {
2996  negate = -adxtail;
2997  Two_Product(negate, cdytail, adxt_cdyt1, adxt_cdyt0);
2999  adxt_cdyt1, adxt_cdyt0, bdheight, u3, u[2], u[1], u[0]);
3000  u[3] = u3;
3001  finlength =
3002  fast_expansion_sum_zeroelimTRI(finlength, finnow, 4, u, finother);
3003  finswap = finnow;
3004  finnow = finother;
3005  finother = finswap;
3006  if (bdheighttail != 0.0)
3007  {
3009  adxt_cdyt1, adxt_cdyt0, bdheighttail, u3, u[2], u[1], u[0]);
3010  u[3] = u3;
3011  finlength = fast_expansion_sum_zeroelimTRI(
3012  finlength, finnow, 4, u, finother);
3013  finswap = finnow;
3014  finnow = finother;
3015  finother = finswap;
3016  }
3017  }
3018  }
3019  if (bdxtail != 0.0)
3020  {
3021  if (cdytail != 0.0)
3022  {
3023  Two_Product(bdxtail, cdytail, bdxt_cdyt1, bdxt_cdyt0);
3025  bdxt_cdyt1, bdxt_cdyt0, adheight, u3, u[2], u[1], u[0]);
3026  u[3] = u3;
3027  finlength =
3028  fast_expansion_sum_zeroelimTRI(finlength, finnow, 4, u, finother);
3029  finswap = finnow;
3030  finnow = finother;
3031  finother = finswap;
3032  if (adheighttail != 0.0)
3033  {
3035  bdxt_cdyt1, bdxt_cdyt0, adheighttail, u3, u[2], u[1], u[0]);
3036  u[3] = u3;
3037  finlength = fast_expansion_sum_zeroelimTRI(
3038  finlength, finnow, 4, u, finother);
3039  finswap = finnow;
3040  finnow = finother;
3041  finother = finswap;
3042  }
3043  }
3044  if (adytail != 0.0)
3045  {
3046  negate = -bdxtail;
3047  Two_Product(negate, adytail, bdxt_adyt1, bdxt_adyt0);
3049  bdxt_adyt1, bdxt_adyt0, cdheight, u3, u[2], u[1], u[0]);
3050  u[3] = u3;
3051  finlength =
3052  fast_expansion_sum_zeroelimTRI(finlength, finnow, 4, u, finother);
3053  finswap = finnow;
3054  finnow = finother;
3055  finother = finswap;
3056  if (cdheighttail != 0.0)
3057  {
3059  bdxt_adyt1, bdxt_adyt0, cdheighttail, u3, u[2], u[1], u[0]);
3060  u[3] = u3;
3061  finlength = fast_expansion_sum_zeroelimTRI(
3062  finlength, finnow, 4, u, finother);
3063  finswap = finnow;
3064  finnow = finother;
3065  finother = finswap;
3066  }
3067  }
3068  }
3069  if (cdxtail != 0.0)
3070  {
3071  if (adytail != 0.0)
3072  {
3073  Two_Product(cdxtail, adytail, cdxt_adyt1, cdxt_adyt0);
3075  cdxt_adyt1, cdxt_adyt0, bdheight, u3, u[2], u[1], u[0]);
3076  u[3] = u3;
3077  finlength =
3078  fast_expansion_sum_zeroelimTRI(finlength, finnow, 4, u, finother);
3079  finswap = finnow;
3080  finnow = finother;
3081  finother = finswap;
3082  if (bdheighttail != 0.0)
3083  {
3085  cdxt_adyt1, cdxt_adyt0, bdheighttail, u3, u[2], u[1], u[0]);
3086  u[3] = u3;
3087  finlength = fast_expansion_sum_zeroelimTRI(
3088  finlength, finnow, 4, u, finother);
3089  finswap = finnow;
3090  finnow = finother;
3091  finother = finswap;
3092  }
3093  }
3094  if (bdytail != 0.0)
3095  {
3096  negate = -cdxtail;
3097  Two_Product(negate, bdytail, cdxt_bdyt1, cdxt_bdyt0);
3099  cdxt_bdyt1, cdxt_bdyt0, adheight, u3, u[2], u[1], u[0]);
3100  u[3] = u3;
3101  finlength =
3102  fast_expansion_sum_zeroelimTRI(finlength, finnow, 4, u, finother);
3103  finswap = finnow;
3104  finnow = finother;
3105  finother = finswap;
3106  if (adheighttail != 0.0)
3107  {
3109  cdxt_bdyt1, cdxt_bdyt0, adheighttail, u3, u[2], u[1], u[0]);
3110  u[3] = u3;
3111  finlength = fast_expansion_sum_zeroelimTRI(
3112  finlength, finnow, 4, u, finother);
3113  finswap = finnow;
3114  finnow = finother;
3115  finother = finswap;
3116  }
3117  }
3118  }
3119 
3120  if (adheighttail != 0.0)
3121  {
3122  wlength = scale_expansion_zeroelimTRI(bctlen, bct, adheighttail, w);
3123  finlength = fast_expansion_sum_zeroelimTRI(
3124  finlength, finnow, wlength, w, finother);
3125  finswap = finnow;
3126  finnow = finother;
3127  finother = finswap;
3128  }
3129  if (bdheighttail != 0.0)
3130  {
3131  wlength = scale_expansion_zeroelimTRI(catlen, cat, bdheighttail, w);
3132  finlength = fast_expansion_sum_zeroelimTRI(
3133  finlength, finnow, wlength, w, finother);
3134  finswap = finnow;
3135  finnow = finother;
3136  finother = finswap;
3137  }
3138  if (cdheighttail != 0.0)
3139  {
3140  wlength = scale_expansion_zeroelimTRI(abtlen, abt, cdheighttail, w);
3141  finlength = fast_expansion_sum_zeroelimTRI(
3142  finlength, finnow, wlength, w, finother);
3143  finswap = finnow;
3144  finnow = finother;
3145  finother = finswap;
3146  }
3147 
3148  return finnow[finlength - 1];
3149 }
#define Absolute(a)
#define Two_One_Product(a1, a0, b, x3, x2, x1, x0)
#define Two_Diff_Tail(a, b, x, y)
void negate(NekPoint< DataType > &rhs)
Definition: NekPoint.hpp:373
int fast_expansion_sum_zeroelimTRI(int elen, double *e, int flen, double *f, double *h)
int scale_expansion_zeroelimTRI(int elen, double *e, double b, double *h)
#define Two_Two_Diff(a1, a0, b1, b0, x3, x2, x1, x0)
#define Two_Product(a, b, x, y)
void Nektar::NekMeshUtils::DelaunayTriangle::parsecommandline ( int  argc,
char **  argv,
struct behavior b 
)
private

Definition at line 472 of file Triangle/Triangle.cpp.

References Nektar::NekMeshUtils::behavior::goodangle, Nektar::NekMeshUtils::behavior::jettison, Nektar::NekMeshUtils::behavior::minangle, Nektar::NekMeshUtils::behavior::nobisect, Nektar::NekMeshUtils::behavior::offconstant, PI, Nektar::NekMeshUtils::behavior::poly, Nektar::NekMeshUtils::behavior::quality, Nektar::NekMeshUtils::behavior::usertest, Nektar::NekMeshUtils::behavior::usesegments, and Nektar::NekMeshUtils::behavior::weighted.

Referenced by triangulate().

473 {
474  int i, j, k;
475  char workstring[2048];
476 
477  b->poly = b->quality = 0;
478  b->usertest = 0;
479  b->weighted = b->jettison = 0;
480  b->nobisect = 0;
481  b->minangle = 0.0;
482 
483  for (i = 0; i < argc; i++)
484  {
485  for (j = 0; argv[i][j] != '\0'; j++)
486  {
487  if (argv[i][j] == 'p')
488  {
489  b->poly = 1;
490  }
491  if (argv[i][j] == 'q')
492  {
493  b->quality = 1;
494  if (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) ||
495  (argv[i][j + 1] == '.'))
496  {
497  k = 0;
498  while (
499  ((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) ||
500  (argv[i][j + 1] == '.'))
501  {
502  j++;
503  workstring[k] = argv[i][j];
504  k++;
505  }
506  workstring[k] = '\0';
507  b->minangle = (double)strtod(workstring, (char **)NULL);
508  }
509  else
510  {
511  b->minangle = 20.0;
512  }
513  }
514  if (argv[i][j] == 'u')
515  {
516  b->quality = 1;
517  b->usertest = 1;
518  }
519  if (argv[i][j] == 'w')
520  {
521  b->weighted = 1;
522  }
523  if (argv[i][j] == 'W')
524  {
525  b->weighted = 2;
526  }
527  if (argv[i][j] == 'j')
528  {
529  b->jettison = 1;
530  }
531  if (argv[i][j] == 'Y')
532  {
533  b->nobisect++;
534  }
535  }
536  }
537 
538  b->usesegments = b->poly || b->quality;
539  b->goodangle = cos(b->minangle * PI / 180.0);
540  if (b->goodangle == 1.0)
541  {
542  b->offconstant = 0.0;
543  }
544  else
545  {
546  b->offconstant =
547  0.475 * sqrt((1.0 + b->goodangle) / (1.0 - b->goodangle));
548  }
549  b->goodangle *= b->goodangle;
550 
551  /* Regular/weighted triangulations are incompatible with PSLGs */
552  /* and meshing. */
553  if (b->weighted && (b->poly || b->quality))
554  {
555  b->weighted = 0;
556  }
557 }
#define PI
void Nektar::NekMeshUtils::DelaunayTriangle::plague ( struct mesh m,
struct behavior b 
)
private

Definition at line 7467 of file Triangle/Triangle.cpp.

References dest, dissolve, Nektar::NekMeshUtils::mesh::dummysub, Nektar::NekMeshUtils::mesh::dummytri, Nektar::NekMeshUtils::mesh::hullsize, infect, infected, mark, onext, onextself, oprev, oprevself, org, Nektar::NekMeshUtils::otri::orient, otriequal, poolalloc(), poolrestart(), setmark, setorg, setvertexmark, setvertextype, Nektar::NekMeshUtils::osub::ss, stdissolve, subsegdealloc(), sym, traversalinit(), traverse(), Nektar::NekMeshUtils::otri::tri, triangledealloc(), tsdissolve, tspivot, Nektar::NekMeshUtils::mesh::undeads, UNDEADVERTEX, uninfect, vertexmark, and Nektar::NekMeshUtils::mesh::viri.

Referenced by carveholes().

7468 {
7469  struct otri testtri;
7470  struct otri neighbor;
7471  triangle **virusloop;
7472  triangle **deadtriangle;
7473  struct osub neighborsubseg;
7474  vertex testvertex;
7475  vertex norg, ndest;
7476  int killorg;
7477  triangle ptr; /* Temporary variable used by sym() and onext(). */
7478  subseg sptr; /* Temporary variable used by tspivot(). */
7479 
7480  /* Loop through all the infected triangles, spreading the virus to */
7481  /* their neighbors, then to their neighbors' neighbors. */
7482  traversalinit(&m->viri);
7483  virusloop = (triangle **)traverse(&m->viri);
7484  while (virusloop != (triangle **)NULL)
7485  {
7486  testtri.tri = *virusloop;
7487  /* A triangle is marked as infected by messing with one of its pointers
7488  */
7489  /* to subsegments, setting it to an illegal value. Hence, we have to
7490  */
7491  /* temporarily uninfect this triangle so that we can examine its */
7492  /* adjacent subsegments. */
7493  uninfect(testtri);
7494 
7495  /* Check each of the triangle's three neighbors. */
7496  for (testtri.orient = 0; testtri.orient < 3; testtri.orient++)
7497  {
7498  /* Find the neighbor. */
7499  sym(testtri, neighbor);
7500  /* Check for a subsegment between the triangle and its neighbor. */
7501  tspivot(testtri, neighborsubseg);
7502  /* Check if the neighbor is nonexistent or already infected. */
7503  if ((neighbor.tri == m->dummytri) || infected(neighbor))
7504  {
7505  if (neighborsubseg.ss != m->dummysub)
7506  {
7507  /* There is a subsegment separating the triangle from its */
7508  /* neighbor, but both triangles are dying, so the
7509  * subsegment */
7510  /* dies too. */
7511  subsegdealloc(m, neighborsubseg.ss);
7512  if (neighbor.tri != m->dummytri)
7513  {
7514  /* Make sure the subsegment doesn't get deallocated
7515  * again */
7516  /* later when the infected neighbor is visited. */
7517  uninfect(neighbor);
7518  tsdissolve(neighbor);
7519  infect(neighbor);
7520  }
7521  }
7522  }
7523  else
7524  { /* The neighbor exists and is not infected. */
7525  if (neighborsubseg.ss == m->dummysub)
7526  {
7527  /* There is no subsegment protecting the neighbor, so */
7528  /* the neighbor becomes infected. */
7529 
7530  infect(neighbor);
7531  /* Ensure that the neighbor's neighbors will be infected. */
7532  deadtriangle = (triangle **)poolalloc(&m->viri);
7533  *deadtriangle = neighbor.tri;
7534  }
7535  else
7536  { /* The neighbor is protected by a subsegment. */
7537  /* Remove this triangle from the subsegment. */
7538  stdissolve(neighborsubseg);
7539  /* The subsegment becomes a boundary. Set markers
7540  * accordingly. */
7541  if (mark(neighborsubseg) == 0)
7542  {
7543  setmark(neighborsubseg, 1);
7544  }
7545  org(neighbor, norg);
7546  dest(neighbor, ndest);
7547  if (vertexmark(norg) == 0)
7548  {
7549  setvertexmark(norg, 1);
7550  }
7551  if (vertexmark(ndest) == 0)
7552  {
7553  setvertexmark(ndest, 1);
7554  }
7555  }
7556  }
7557  }
7558  /* Remark the triangle as infected, so it doesn't get added to the */
7559  /* virus pool again. */
7560  infect(testtri);
7561  virusloop = (triangle **)traverse(&m->viri);
7562  }
7563 
7564 
7565  traversalinit(&m->viri);
7566  virusloop = (triangle **)traverse(&m->viri);
7567  while (virusloop != (triangle **)NULL)
7568  {
7569  testtri.tri = *virusloop;
7570 
7571  /* Check each of the three corners of the triangle for elimination. */
7572  /* This is done by walking around each vertex, checking if it is */
7573  /* still connected to at least one live triangle. */
7574  for (testtri.orient = 0; testtri.orient < 3; testtri.orient++)
7575  {
7576  org(testtri, testvertex);
7577  /* Check if the vertex has already been tested. */
7578  if (testvertex != (vertex)NULL)
7579  {
7580  killorg = 1;
7581  /* Mark the corner of the triangle as having been tested. */
7582  setorg(testtri, NULL);
7583  /* Walk counterclockwise about the vertex. */
7584  onext(testtri, neighbor);
7585  /* Stop upon reaching a boundary or the starting triangle. */
7586  while ((neighbor.tri != m->dummytri) &&
7587  (!otriequal(neighbor, testtri)))
7588  {
7589  if (infected(neighbor))
7590  {
7591  /* Mark the corner of this triangle as having been
7592  * tested. */
7593  setorg(neighbor, NULL);
7594  }
7595  else
7596  {
7597  /* A live triangle. The vertex survives. */
7598  killorg = 0;
7599  }
7600  /* Walk counterclockwise about the vertex. */
7601  onextself(neighbor);
7602  }
7603  /* If we reached a boundary, we must walk clockwise as well. */
7604  if (neighbor.tri == m->dummytri)
7605  {
7606  /* Walk clockwise about the vertex. */
7607  oprev(testtri, neighbor);
7608  /* Stop upon reaching a boundary. */
7609  while (neighbor.tri != m->dummytri)
7610  {
7611  if (infected(neighbor))
7612  {
7613  /* Mark the corner of this triangle as having been
7614  * tested. */
7615  setorg(neighbor, NULL);
7616  }
7617  else
7618  {
7619  /* A live triangle. The vertex survives. */
7620  killorg = 0;
7621  }
7622  /* Walk clockwise about the vertex. */
7623  oprevself(neighbor);
7624  }
7625  }
7626  if (killorg)
7627  {
7628 
7629  setvertextype(testvertex, UNDEADVERTEX);
7630  m->undeads++;
7631  }
7632  }
7633  }
7634 
7635  /* Record changes in the number of boundary edges, and disconnect */
7636  /* dead triangles from their neighbors. */
7637  for (testtri.orient = 0; testtri.orient < 3; testtri.orient++)
7638  {
7639  sym(testtri, neighbor);
7640  if (neighbor.tri == m->dummytri)
7641  {
7642  /* There is no neighboring triangle on this edge, so this edge
7643  */
7644  /* is a boundary edge. This triangle is being deleted, so
7645  * this */
7646  /* boundary edge is deleted. */
7647  m->hullsize--;
7648  }
7649  else
7650  {
7651  /* Disconnect the triangle from its neighbor. */
7652  dissolve(neighbor);
7653  /* There is a neighboring triangle on this edge, so this edge */
7654  /* becomes a boundary edge when this triangle is deleted. */
7655  m->hullsize++;
7656  }
7657  }
7658  /* Return the dead triangle to the pool of triangles. */
7659  triangledealloc(m, testtri.tri);
7660  virusloop = (triangle **)traverse(&m->viri);
7661  }
7662  /* Empty the virus pool. */
7663  poolrestart(&m->viri);
7664 }
#define vertexmark(vx)
#define onextself(otri)
#define setmark(osub, value)
void subsegdealloc(struct mesh *m, subseg *dyingsubseg)
void * traverse(struct memorypool *pool)
void * poolalloc(struct memorypool *pool)
#define tsdissolve(otri)
#define UNDEADVERTEX
#define uninfect(otri)
#define setvertextype(vx, value)
void traversalinit(struct memorypool *pool)
#define otriequal(otri1, otri2)
void triangledealloc(struct mesh *m, triangle *dyingtriangle)
#define mark(osub)
#define setorg(otri, vertexptr)
#define sym(otri1, otri2)
#define stdissolve(osub)
#define infected(otri)
#define onext(otri1, otri2)
void poolrestart(struct memorypool *pool)
#define infect(otri)
#define setvertexmark(vx, value)
#define oprev(otri1, otri2)
#define oprevself(otri)
#define tspivot(otri, osub)
#define dest(otri, vertexptr)
#define dissolve(otri)
#define org(otri, vertexptr)
void * Nektar::NekMeshUtils::DelaunayTriangle::poolalloc ( struct memorypool pool)
private

Definition at line 702 of file Triangle/Triangle.cpp.

References Nektar::NekMeshUtils::memorypool::alignbytes, Nektar::NekMeshUtils::memorypool::deaditemstack, Nektar::NekMeshUtils::memorypool::itembytes, Nektar::NekMeshUtils::memorypool::items, Nektar::NekMeshUtils::memorypool::itemsperblock, Nektar::NekMeshUtils::memorypool::maxitems, Nektar::NekMeshUtils::memorypool::nextitem, Nektar::NekMeshUtils::memorypool::nowblock, trimalloc(), and Nektar::NekMeshUtils::memorypool::unallocateditems.

Referenced by carveholes(), checkseg4encroach(), conformingedge(), enqueuebadtri(), infecthull(), insertvertex(), makesubseg(), maketriangle(), plague(), regionplague(), segmentintersection(), splitencsegs(), splittriangle(), and transfernodes().

703 {
704  void *newitem;
705  void **newblock;
706  unsigned long alignptr;
707 
708  /* First check the linked list of dead items. If the list is not */
709  /* empty, allocate an item from the list rather than a fresh one. */
710  if (pool->deaditemstack != (void *)NULL)
711  {
712  newitem = pool->deaditemstack; /* Take first item in list. */
713  pool->deaditemstack = *(void **)pool->deaditemstack;
714  }
715  else
716  {
717  /* Check if there are any free items left in the current block. */
718  if (pool->unallocateditems == 0)
719  {
720  /* Check if another block must be allocated. */
721  if (*(pool->nowblock) == (void *)NULL)
722  {
723  /* Allocate a new block of items, pointed to by the previous
724  * block. */
725  newblock =
726  (void **)trimalloc(pool->itemsperblock * pool->itembytes +
727  (int)sizeof(void *) + pool->alignbytes);
728  *(pool->nowblock) = (void *)newblock;
729  /* The next block pointer is NULL. */
730  *newblock = (void *)NULL;
731  }
732 
733  /* Move to the new block. */
734  pool->nowblock = (void **)*(pool->nowblock);
735  /* Find the first item in the block. */
736  /* Increment by the size of (void *). */
737  alignptr = (unsigned long)(pool->nowblock + 1);
738  /* Align the item on an `alignbytes'-byte boundary. */
739  pool->nextitem =
740  (void *)(alignptr + (unsigned long)pool->alignbytes -
741  (alignptr % (unsigned long)pool->alignbytes));
742  /* There are lots of unallocated items left in this block. */
743  pool->unallocateditems = pool->itemsperblock;
744  }
745 
746  /* Allocate a new item. */
747  newitem = pool->nextitem;
748  /* Advance `nextitem' pointer to next free item in block. */
749  pool->nextitem = (void *)((char *)pool->nextitem + pool->itembytes);
750  pool->unallocateditems--;
751  pool->maxitems++;
752  }
753  pool->items++;
754  return newitem;
755 }
void Nektar::NekMeshUtils::DelaunayTriangle::pooldealloc ( struct memorypool pool,
void dyingitem 
)
private

Definition at line 765 of file Triangle/Triangle.cpp.

References Nektar::NekMeshUtils::memorypool::deaditemstack, and Nektar::NekMeshUtils::memorypool::items.

Referenced by badsubsegdealloc(), enforcequality(), subsegdealloc(), triangledealloc(), and vertexdealloc().

766 {
767  /* Push freshly killed item onto stack. */
768  *((void **)dyingitem) = pool->deaditemstack;
769  pool->deaditemstack = dyingitem;
770  pool->items--;
771 }
void Nektar::NekMeshUtils::DelaunayTriangle::pooldeinit ( struct memorypool pool)
private

Definition at line 686 of file Triangle/Triangle.cpp.

References Nektar::NekMeshUtils::memorypool::firstblock, Nektar::NekMeshUtils::memorypool::nowblock, and trifree().

Referenced by carveholes(), and triangledeinit().

687 {
688  while (pool->firstblock != (void **)NULL)
689  {
690  pool->nowblock = (void **)*(pool->firstblock);
691  trifree((void *)pool->firstblock);
692  pool->firstblock = pool->nowblock;
693  }
694 }
void Nektar::NekMeshUtils::DelaunayTriangle::poolinit ( struct memorypool pool,
int  bytecount,
int  itemcount,
int  firstitemcount,
int  alignment 
)
private

Definition at line 639 of file Triangle/Triangle.cpp.

References Nektar::NekMeshUtils::memorypool::alignbytes, Nektar::NekMeshUtils::memorypool::firstblock, Nektar::NekMeshUtils::memorypool::itembytes, Nektar::NekMeshUtils::memorypool::itemsfirstblock, Nektar::NekMeshUtils::memorypool::itemsperblock, poolrestart(), and trimalloc().

Referenced by carveholes(), enforcequality(), initializetrisubpools(), and initializevertexpool().

644 {
645  /* Find the proper alignment, which must be at least as large as: */
646  /* - The parameter `alignment'. */
647  /* - sizeof(void *), so the stack of dead items can be maintained */
648  /* without unaligned accesses. */
649  if (alignment > sizeof(void *))
650  {
651  pool->alignbytes = alignment;
652  }
653  else
654  {
655  pool->alignbytes = sizeof(void *);
656  }
657  pool->itembytes =
658  ((bytecount - 1) / pool->alignbytes + 1) * pool->alignbytes;
659  pool->itemsperblock = itemcount;
660  if (firstitemcount == 0)
661  {
662  pool->itemsfirstblock = itemcount;
663  }
664  else
665  {
666  pool->itemsfirstblock = firstitemcount;
667  }
668 
669  /* Allocate a block of items. Space for `itemsfirstblock' items and one */
670  /* pointer (to point to the next block) are allocated, as well as space */
671  /* to ensure alignment of the items. */
672  pool->firstblock =
673  (void **)trimalloc(pool->itemsfirstblock * pool->itembytes +
674  (int)sizeof(void *) + pool->alignbytes);
675  /* Set the next block pointer to NULL. */
676  *(pool->firstblock) = (void *)NULL;
677  poolrestart(pool);
678 }
void poolrestart(struct memorypool *pool)
void Nektar::NekMeshUtils::DelaunayTriangle::poolrestart ( struct memorypool pool)
private

Definition at line 600 of file Triangle/Triangle.cpp.

References Nektar::NekMeshUtils::memorypool::alignbytes, Nektar::NekMeshUtils::memorypool::deaditemstack, Nektar::NekMeshUtils::memorypool::firstblock, Nektar::NekMeshUtils::memorypool::items, Nektar::NekMeshUtils::memorypool::itemsfirstblock, Nektar::NekMeshUtils::memorypool::maxitems, Nektar::NekMeshUtils::memorypool::nextitem, Nektar::NekMeshUtils::memorypool::nowblock, and Nektar::NekMeshUtils::memorypool::unallocateditems.

Referenced by insertvertex(), plague(), poolinit(), and regionplague().

601 {
602  unsigned long alignptr;
603 
604  pool->items = 0;
605  pool->maxitems = 0;
606 
607  /* Set the currently active block. */
608  pool->nowblock = pool->firstblock;
609  /* Find the first item in the pool. Increment by the size of (void *). */
610  alignptr = (unsigned long)(pool->nowblock + 1);
611  /* Align the item on an `alignbytes'-byte boundary. */
612  pool->nextitem = (void *)(alignptr + (unsigned long)pool->alignbytes -
613  (alignptr % (unsigned long)pool->alignbytes));
614  /* There are lots of unallocated items left in this block. */
615  pool->unallocateditems = pool->itemsfirstblock;
616  /* The stack of deallocated items is empty. */
617  pool->deaditemstack = (void *)NULL;
618 }
void Nektar::NekMeshUtils::DelaunayTriangle::poolzero ( struct memorypool pool)
private

Definition at line 572 of file Triangle/Triangle.cpp.

References Nektar::NekMeshUtils::memorypool::alignbytes, Nektar::NekMeshUtils::memorypool::deaditemstack, Nektar::NekMeshUtils::memorypool::firstblock, Nektar::NekMeshUtils::memorypool::itembytes, Nektar::NekMeshUtils::memorypool::items, Nektar::NekMeshUtils::memorypool::itemsfirstblock, Nektar::NekMeshUtils::memorypool::itemsperblock, Nektar::NekMeshUtils::memorypool::maxitems, Nektar::NekMeshUtils::memorypool::nextitem, Nektar::NekMeshUtils::memorypool::nowblock, Nektar::NekMeshUtils::memorypool::pathblock, Nektar::NekMeshUtils::memorypool::pathitem, Nektar::NekMeshUtils::memorypool::pathitemsleft, and Nektar::NekMeshUtils::memorypool::unallocateditems.

Referenced by triangleinit().

573 {
574  pool->firstblock = (void **)NULL;
575  pool->nowblock = (void **)NULL;
576  pool->nextitem = (void *)NULL;
577  pool->deaditemstack = (void *)NULL;
578  pool->pathblock = (void **)NULL;
579  pool->pathitem = (void *)NULL;
580  pool->alignbytes = 0;
581  pool->itembytes = 0;
582  pool->itemsperblock = 0;
583  pool->itemsfirstblock = 0;
584  pool->items = 0;
585  pool->maxitems = 0;
586  pool->unallocateditems = 0;
587  pool->pathitemsleft = 0;
588 }
enum locateresult Nektar::NekMeshUtils::DelaunayTriangle::preciselocate ( struct mesh m,
struct behavior b,
vertex  searchpoint,
struct otri searchtri,
int  stopatsubsegment 
)
private

Definition at line 3985 of file Triangle/Triangle.cpp.

References apex, Nektar::NekMeshUtils::mesh::checksegments, counterclockwise(), dest, Nektar::NekMeshUtils::mesh::dummysub, Nektar::NekMeshUtils::mesh::dummytri, Nektar::NekMeshUtils::INTRIANGLE, lnext, lnextself, lprev, lprevself, Nektar::NekMeshUtils::ONEDGE, Nektar::NekMeshUtils::ONVERTEX, org, otricopy, Nektar::NekMeshUtils::OUTSIDE, Nektar::NekMeshUtils::osub::ss, sym, Nektar::NekMeshUtils::otri::tri, and tspivot.

Referenced by insertvertex(), and locate().

3990 {
3991  struct otri backtracktri;
3992  struct osub checkedge;
3993  vertex forg, fdest, fapex;
3994  double orgorient, destorient;
3995  int moveleft;
3996  triangle ptr; /* Temporary variable used by sym(). */
3997  subseg sptr; /* Temporary variable used by tspivot(). */
3998 
3999  /* Where are we? */
4000  org(*searchtri, forg);
4001  dest(*searchtri, fdest);
4002  apex(*searchtri, fapex);
4003  while (1)
4004  {
4005  /* Check whether the apex is the point we seek. */
4006  if ((fapex[0] == searchpoint[0]) && (fapex[1] == searchpoint[1]))
4007  {
4008  lprevself(*searchtri);
4009  return ONVERTEX;
4010  }
4011  /* Does the point lie on the other side of the line defined by the */
4012  /* triangle edge opposite the triangle's destination? */
4013  destorient = counterclockwise(m, b, forg, fapex, searchpoint);
4014  /* Does the point lie on the other side of the line defined by the */
4015  /* triangle edge opposite the triangle's origin? */
4016  orgorient = counterclockwise(m, b, fapex, fdest, searchpoint);
4017  if (destorient > 0.0)
4018  {
4019  if (orgorient > 0.0)
4020  {
4021  /* Move left if the inner product of (fapex - searchpoint) and
4022  */
4023  /* (fdest - forg) is positive. This is equivalent to drawing
4024  */
4025  /* a line perpendicular to the line (forg, fdest) and passing
4026  */
4027  /* through `fapex', and determining which side of this line */
4028  /* `searchpoint' falls on. */
4029  moveleft =
4030  (fapex[0] - searchpoint[0]) * (fdest[0] - forg[0]) +
4031  (fapex[1] - searchpoint[1]) * (fdest[1] - forg[1]) >
4032  0.0;
4033  }
4034  else
4035  {
4036  moveleft = 1;
4037  }
4038  }
4039  else
4040  {
4041  if (orgorient > 0.0)
4042  {
4043  moveleft = 0;
4044  }
4045  else
4046  {
4047  /* The point we seek must be on the boundary of or inside this
4048  */
4049  /* triangle. */
4050  if (destorient == 0.0)
4051  {
4052  lprevself(*searchtri);
4053  return ONEDGE;
4054  }
4055  if (orgorient == 0.0)
4056  {
4057  lnextself(*searchtri);
4058  return ONEDGE;
4059  }
4060  return INTRIANGLE;
4061  }
4062  }
4063 
4064  /* Move to another triangle. Leave a trace `backtracktri' in case */
4065  /* floating-point roundoff or some such bogey causes us to walk */
4066  /* off a boundary of the triangulation. */
4067  if (moveleft)
4068  {
4069  lprev(*searchtri, backtracktri);
4070  fdest = fapex;
4071  }
4072  else
4073  {
4074  lnext(*searchtri, backtracktri);
4075  forg = fapex;
4076  }
4077  sym(backtracktri, *searchtri);
4078 
4079  if (m->checksegments && stopatsubsegment)
4080  {
4081  /* Check for walking through a subsegment. */
4082  tspivot(backtracktri, checkedge);
4083  if (checkedge.ss != m->dummysub)
4084  {
4085  /* Go back to the last triangle. */
4086  otricopy(backtracktri, *searchtri);
4087  return OUTSIDE;
4088  }
4089  }
4090  /* Check for walking right out of the triangulation. */
4091  if (searchtri->tri == m->dummytri)
4092  {
4093  /* Go back to the last triangle. */
4094  otricopy(backtracktri, *searchtri);
4095  return OUTSIDE;
4096  }
4097 
4098  apex(*searchtri, fapex);
4099  }
4100 }
#define sym(otri1, otri2)
#define lprev(otri1, otri2)
#define lnextself(otri)
double counterclockwise(struct mesh *m, struct behavior *b, vertex pa, vertex pb, vertex pc)
#define lprevself(otri)
#define apex(otri, vertexptr)
#define otricopy(otri1, otri2)
#define tspivot(otri, osub)
#define lnext(otri1, otri2)
#define dest(otri, vertexptr)
#define org(otri, vertexptr)
void Nektar::NekMeshUtils::DelaunayTriangle::precisionerror ( )
private

Definition at line 7958 of file Triangle/Triangle.cpp.

Referenced by splitencsegs(), and splittriangle().

7959 {
7960  printf("Try increasing the area criterion and/or reducing the minimum\n");
7961  printf(" allowable angle so that tiny triangles are not created.\n");
7962 #ifdef SINGLE
7963  printf("Alternatively, try recompiling me with double precision\n");
7964  printf(" arithmetic (by removing \"#define SINGLE\" from the\n");
7965  printf(" source file or \"-DSINGLE\" from the makefile).\n");
7966 #endif /* SINGLE */
7967 }
unsigned long Nektar::NekMeshUtils::DelaunayTriangle::randomnation ( unsigned int  choices)
private

Definition at line 3414 of file Triangle/Triangle.cpp.

References randomseed.

Referenced by locate(), vertexmedian(), and vertexsort().

3415 {
3416  randomseed = (randomseed * 1366l + 150889l) % 714025l;
3417  return randomseed / (714025l / choices + 1);
3418 }
void Nektar::NekMeshUtils::DelaunayTriangle::regionplague ( struct mesh m,
struct behavior b,
double  attribute,
double  area 
)
private

Definition at line 7681 of file Triangle/Triangle.cpp.

References Nektar::NekMeshUtils::mesh::dummysub, Nektar::NekMeshUtils::mesh::dummytri, infect, infected, Nektar::NekMeshUtils::otri::orient, poolalloc(), poolrestart(), Nektar::NekMeshUtils::osub::ss, sym, traversalinit(), traverse(), Nektar::NekMeshUtils::otri::tri, tspivot, uninfect, and Nektar::NekMeshUtils::mesh::viri.

Referenced by carveholes().

7685 {
7686  struct otri testtri;
7687  struct otri neighbor;
7688  triangle **virusloop;
7689  triangle **regiontri;
7690  struct osub neighborsubseg;
7691  triangle ptr; /* Temporary variable used by sym() and onext(). */
7692  subseg sptr; /* Temporary variable used by tspivot(). */
7693 
7694 
7695  /* Loop through all the infected triangles, spreading the attribute */
7696  /* and/or area constraint to their neighbors, then to their neighbors' */
7697  /* neighbors. */
7698  traversalinit(&m->viri);
7699  virusloop = (triangle **)traverse(&m->viri);
7700  while (virusloop != (triangle **)NULL)
7701  {
7702  testtri.tri = *virusloop;
7703  /* A triangle is marked as infected by messing with one of its pointers
7704  */
7705  /* to subsegments, setting it to an illegal value. Hence, we have to
7706  */
7707  /* temporarily uninfect this triangle so that we can examine its */
7708  /* adjacent subsegments. */
7709  uninfect(testtri);
7710 
7711  /* Check each of the triangle's three neighbors. */
7712  for (testtri.orient = 0; testtri.orient < 3; testtri.orient++)
7713  {
7714  /* Find the neighbor. */
7715  sym(testtri, neighbor);
7716  /* Check for a subsegment between the triangle and its neighbor. */
7717  tspivot(testtri, neighborsubseg);
7718  /* Make sure the neighbor exists, is not already infected, and */
7719  /* isn't protected by a subsegment. */
7720  if ((neighbor.tri != m->dummytri) && !infected(neighbor) &&
7721  (neighborsubseg.ss == m->dummysub))
7722  {
7723 
7724  /* Infect the neighbor. */
7725  infect(neighbor);
7726  /* Ensure that the neighbor's neighbors will be infected. */
7727  regiontri = (triangle **)poolalloc(&m->viri);
7728  *regiontri = neighbor.tri;
7729  }
7730  }
7731  /* Remark the triangle as infected, so it doesn't get added to the */
7732  /* virus pool again. */
7733  infect(testtri);
7734  virusloop = (triangle **)traverse(&m->viri);
7735  }
7736 
7737  /* Uninfect all triangles. */
7738 
7739  traversalinit(&m->viri);
7740  virusloop = (triangle **)traverse(&m->viri);
7741  while (virusloop != (triangle **)NULL)
7742  {
7743  testtri.tri = *virusloop;
7744  uninfect(testtri);
7745  virusloop = (triangle **)traverse(&m->viri);
7746  }
7747  /* Empty the virus pool. */
7748  poolrestart(&m->viri);
7749 }
void * traverse(struct memorypool *pool)
void * poolalloc(struct memorypool *pool)
#define uninfect(otri)
void traversalinit(struct memorypool *pool)
#define sym(otri1, otri2)
#define infected(otri)
void poolrestart(struct memorypool *pool)
#define infect(otri)
#define tspivot(otri, osub)
long Nektar::NekMeshUtils::DelaunayTriangle::removeghosts ( struct mesh m,
struct behavior b,
struct otri startghost 
)
private

Definition at line 6300 of file Triangle/Triangle.cpp.

References dissolve, Nektar::NekMeshUtils::mesh::dummytri, encode, lnext, lprev, lprevself, org, otricopy, otriequal, Nektar::NekMeshUtils::behavior::poly, setvertexmark, sym, symself, Nektar::NekMeshUtils::otri::tri, triangledealloc(), and vertexmark.

Referenced by divconqdelaunay().

6301 {
6302  struct otri searchedge;
6303  struct otri dissolveedge;
6304  struct otri deadtriangle;
6305  vertex markorg;
6306  long hullsize;
6307  triangle ptr; /* Temporary variable used by sym(). */
6308 
6309 
6310  /* Find an edge on the convex hull to start point location from. */
6311  lprev(*startghost, searchedge);
6312  symself(searchedge);
6313  m->dummytri[0] = encode(searchedge);
6314  /* Remove the bounding box and count the convex hull edges. */
6315  otricopy(*startghost, dissolveedge);
6316  hullsize = 0;
6317  do
6318  {
6319  hullsize++;
6320  lnext(dissolveedge, deadtriangle);
6321  lprevself(dissolveedge);
6322  symself(dissolveedge);
6323  /* If no PSLG is involved, set the boundary markers of all the vertices
6324  */
6325  /* on the convex hull. If a PSLG is used, this step is done later. */
6326  if (!b->poly)
6327  {
6328  /* Watch out for the case where all the input vertices are
6329  * collinear. */
6330  if (dissolveedge.tri != m->dummytri)
6331  {
6332  org(dissolveedge, markorg);
6333  if (vertexmark(markorg) == 0)
6334  {
6335  setvertexmark(markorg, 1);
6336  }
6337  }
6338  }
6339  /* Remove a bounding triangle from a convex hull triangle. */
6340  dissolve(dissolveedge);
6341  /* Find the next bounding triangle. */
6342  sym(deadtriangle, dissolveedge);
6343  /* Delete the bounding triangle. */
6344  triangledealloc(m, deadtriangle.tri);
6345  } while (!otriequal(dissolveedge, *startghost));
6346  return hullsize;
6347 }
#define vertexmark(vx)
#define otriequal(otri1, otri2)
void triangledealloc(struct mesh *m, triangle *dyingtriangle)
#define sym(otri1, otri2)
#define lprev(otri1, otri2)
#define symself(otri)
#define lprevself(otri)
#define setvertexmark(vx, value)
#define otricopy(otri1, otri2)
#define lnext(otri1, otri2)
#define dissolve(otri)
#define org(otri, vertexptr)
#define encode(otri)
int Nektar::NekMeshUtils::DelaunayTriangle::scale_expansion_zeroelimTRI ( int  elen,
double *  e,
double  b,
double *  h 
)
private

Definition at line 1630 of file Triangle/Triangle.cpp.

References Fast_Two_Sum, Split, Two_Product_Presplit, and Two_Sum.

Referenced by incircleadaptTRI(), and orient3dadapt().

1631 {
1632  double Q, sum;
1633  double hh;
1634  double product1;
1635  double product0;
1636  int eindex, hindex;
1637  double enow;
1638  double bvirt;
1639  double avirt, bround, around;
1640  double c;
1641  double abig;
1642  double ahi, alo, bhi, blo;
1643  double err1, err2, err3;
1644 
1645  Split(b, bhi, blo);
1646  Two_Product_Presplit(e[0], b, bhi, blo, Q, hh);
1647  hindex = 0;
1648  if (hh != 0)
1649  {
1650  h[hindex++] = hh;
1651  }
1652  for (eindex = 1; eindex < elen; eindex++)
1653  {
1654  enow = e[eindex];
1655  Two_Product_Presplit(enow, b, bhi, blo, product1, product0);
1656  Two_Sum(Q, product0, sum, hh);
1657  if (hh != 0)
1658  {
1659  h[hindex++] = hh;
1660  }
1661  Fast_Two_Sum(product1, sum, Q, hh);
1662  if (hh != 0)
1663  {
1664  h[hindex++] = hh;
1665  }
1666  }
1667  if ((Q != 0.0) || (hindex == 0))
1668  {
1669  h[hindex++] = Q;
1670  }
1671  return hindex;
1672 }
#define Two_Product_Presplit(a, b, bhi, blo, x, y)
#define Fast_Two_Sum(a, b, x, y)
#define Split(a, ahi, alo)
#define Two_Sum(a, b, x, y)
int Nektar::NekMeshUtils::DelaunayTriangle::scoutsegment ( struct mesh m,
struct behavior b,
struct otri searchtri,
vertex  endpoint2,
int  newmark 
)
private

Definition at line 6699 of file Triangle/Triangle.cpp.

References apex, dest, Nektar::NekMeshUtils::mesh::dummysub, finddirection(), insertsubseg(), Nektar::NekMeshUtils::LEFTCOLLINEAR, lnext, lnextself, lprevself, otricopy, Nektar::NekMeshUtils::RIGHTCOLLINEAR, segmentintersection(), Nektar::NekMeshUtils::osub::ss, and tspivot.

Referenced by conformingedge(), constrainededge(), and insertsegment().

6704 {
6705  struct otri crosstri;
6706  struct osub crosssubseg;
6707  vertex leftvertex, rightvertex;
6708  enum finddirectionresult collinear;
6709  subseg sptr; /* Temporary variable used by tspivot(). */
6710 
6711  collinear = finddirection(m, b, searchtri, endpoint2);
6712  dest(*searchtri, rightvertex);
6713  apex(*searchtri, leftvertex);
6714  if (((leftvertex[0] == endpoint2[0]) && (leftvertex[1] == endpoint2[1])) ||
6715  ((rightvertex[0] == endpoint2[0]) && (rightvertex[1] == endpoint2[1])))
6716  {
6717  /* The segment is already an edge in the mesh. */
6718  if ((leftvertex[0] == endpoint2[0]) && (leftvertex[1] == endpoint2[1]))
6719  {
6720  lprevself(*searchtri);
6721  }
6722  /* Insert a subsegment, if there isn't already one there. */
6723  insertsubseg(m, b, searchtri, newmark);
6724  return 1;
6725  }
6726  else if (collinear == LEFTCOLLINEAR)
6727  {
6728  /* We've collided with a vertex between the segment's endpoints. */
6729  /* Make the collinear vertex be the triangle's origin. */
6730  lprevself(*searchtri);
6731  insertsubseg(m, b, searchtri, newmark);
6732  /* Insert the remainder of the segment. */
6733  return scoutsegment(m, b, searchtri, endpoint2, newmark);
6734  }
6735  else if (collinear == RIGHTCOLLINEAR)
6736  {
6737  /* We've collided with a vertex between the segment's endpoints. */
6738  insertsubseg(m, b, searchtri, newmark);
6739  /* Make the collinear vertex be the triangle's origin. */
6740  lnextself(*searchtri);
6741  /* Insert the remainder of the segment. */
6742  return scoutsegment(m, b, searchtri, endpoint2, newmark);
6743  }
6744  else
6745  {
6746  lnext(*searchtri, crosstri);
6747  tspivot(crosstri, crosssubseg);
6748  /* Check for a crossing segment. */
6749  if (crosssubseg.ss == m->dummysub)
6750  {
6751  return 0;
6752  }
6753  else
6754  {
6755  /* Insert a vertex at the intersection. */
6756  segmentintersection(m, b, &crosstri, &crosssubseg, endpoint2);
6757  otricopy(crosstri, *searchtri);
6758  insertsubseg(m, b, searchtri, newmark);
6759  /* Insert the remainder of the segment. */
6760  return scoutsegment(m, b, searchtri, endpoint2, newmark);
6761  }
6762  }
6763 }
void segmentintersection(struct mesh *m, struct behavior *b, struct otri *splittri, struct osub *splitsubseg, vertex endpoint2)
#define lnextself(otri)
void insertsubseg(struct mesh *m, struct behavior *b, struct otri *tri, int subsegmark)
#define lprevself(otri)
#define apex(otri, vertexptr)
enum finddirectionresult finddirection(struct mesh *m, struct behavior *b, struct otri *searchtri, vertex searchpoint)
#define otricopy(otri1, otri2)
#define tspivot(otri, osub)
#define lnext(otri1, otri2)
#define dest(otri, vertexptr)
int scoutsegment(struct mesh *m, struct behavior *b, struct otri *searchtri, vertex endpoint2, int newmark)
void Nektar::NekMeshUtils::DelaunayTriangle::segmentintersection ( struct mesh m,
struct behavior b,
struct otri splittri,
struct osub splitsubseg,
vertex  endpoint2 
)
private

Definition at line 6575 of file Triangle/Triangle.cpp.

References apex, dest, Nektar::NekMeshUtils::mesh::dummysub, encode, finddirection(), INPUTVERTEX, insertvertex(), internalerror(), mark, Nektar::NekMeshUtils::mesh::nextras, onextself, org, poolalloc(), sdissolve, setsegorg, setvertex2tri, setvertexmark, setvertextype, snextself, spivot, Nektar::NekMeshUtils::osub::ss, ssymself, Nektar::NekMeshUtils::mesh::steinerleft, Nektar::NekMeshUtils::SUCCESSFULVERTEX, and Nektar::NekMeshUtils::mesh::vertices.

Referenced by constrainededge(), and scoutsegment().

6580 {
6581  struct osub opposubseg;
6582  vertex endpoint1;
6583  vertex torg, tdest;
6584  vertex leftvertex, rightvertex;
6585  vertex newvertex;
6586  enum insertvertexresult success;
6587  double ex, ey;
6588  double tx, ty;
6589  double etx, ety;
6590  double split, denom;
6591  int i;
6592  triangle ptr; /* Temporary variable used by onext(). */
6593  subseg sptr; /* Temporary variable used by snext(). */
6594 
6595  /* Find the other three segment endpoints. */
6596  apex(*splittri, endpoint1);
6597  org(*splittri, torg);
6598  dest(*splittri, tdest);
6599  /* Segment intersection formulae; see the Antonio reference. */
6600  tx = tdest[0] - torg[0];
6601  ty = tdest[1] - torg[1];
6602  ex = endpoint2[0] - endpoint1[0];
6603  ey = endpoint2[1] - endpoint1[1];
6604  etx = torg[0] - endpoint2[0];
6605  ety = torg[1] - endpoint2[1];
6606  denom = ty * ex - tx * ey;
6607  if (denom == 0.0)
6608  {
6609  printf("Internal error in segmentintersection():");
6610  printf(" Attempt to find intersection of parallel segments.\n");
6611  internalerror();
6612  }
6613  split = (ey * etx - ex * ety) / denom;
6614  /* Create the new vertex. */
6615  newvertex = (vertex)poolalloc(&m->vertices);
6616  /* Interpolate its coordinate and attributes. */
6617  for (i = 0; i < 2 + m->nextras; i++)
6618  {
6619  newvertex[i] = torg[i] + split * (tdest[i] - torg[i]);
6620  }
6621  setvertexmark(newvertex, mark(*splitsubseg));
6622  setvertextype(newvertex, INPUTVERTEX);
6623 
6624  /* Insert the intersection vertex. This should always succeed. */
6625  success = insertvertex(m, b, newvertex, splittri, splitsubseg, 0, 0);
6626  if (success != SUCCESSFULVERTEX)
6627  {
6628  printf("Internal error in segmentintersection():\n");
6629  printf(" Failure to split a segment.\n");
6630  internalerror();
6631  }
6632  /* Record a triangle whose origin is the new vertex. */
6633  setvertex2tri(newvertex, encode(*splittri));
6634  if (m->steinerleft > 0)
6635  {
6636  m->steinerleft--;
6637  }
6638 
6639  /* Divide the segment into two, and correct the segment endpoints. */
6640  ssymself(*splitsubseg);
6641  spivot(*splitsubseg, opposubseg);
6642  sdissolve(*splitsubseg);
6643  sdissolve(opposubseg);
6644  do
6645  {
6646  setsegorg(*splitsubseg, newvertex);
6647  snextself(*splitsubseg);
6648  } while (splitsubseg->ss != m->dummysub);
6649  do
6650  {
6651  setsegorg(opposubseg, newvertex);
6652  snextself(opposubseg);
6653  } while (opposubseg.ss != m->dummysub);
6654 
6655  /* Inserting the vertex may have caused edge flips. We wish to rediscover
6656  */
6657  /* the edge connecting endpoint1 to the new intersection vertex. */
6658  finddirection(m, b, splittri, endpoint1);
6659  dest(*splittri, rightvertex);
6660  apex(*splittri, leftvertex);
6661  if ((leftvertex[0] == endpoint1[0]) && (leftvertex[1] == endpoint1[1]))
6662  {
6663  onextself(*splittri);
6664  }
6665  else if ((rightvertex[0] != endpoint1[0]) ||
6666  (rightvertex[1] != endpoint1[1]))
6667  {
6668  printf("Internal error in segmentintersection():\n");
6669  printf(" Topological inconsistency after splitting a segment.\n");
6670  internalerror();
6671  }
6672  /* `splittri' should have destination endpoint1. */
6673 }
#define onextself(otri)
void * poolalloc(struct memorypool *pool)
#define setsegorg(osub, vertexptr)
enum insertvertexresult insertvertex(struct mesh *m, struct behavior *b, vertex newvertex, struct otri *searchtri, struct osub *splitseg, int segmentflaws, int triflaws)
#define setvertextype(vx, value)
#define mark(osub)
#define INPUTVERTEX
#define snextself(osub)
#define setvertex2tri(vx, value)
#define sdissolve(osub)
#define apex(otri, vertexptr)
enum finddirectionresult finddirection(struct mesh *m, struct behavior *b, struct otri *searchtri, vertex searchpoint)
#define setvertexmark(vx, value)
#define dest(otri, vertexptr)
#define spivot(osub1, osub2)
#define org(otri, vertexptr)
#define encode(otri)
#define ssymself(osub)
void Nektar::NekMeshUtils::DelaunayTriangle::splitencsegs ( struct mesh m,
struct behavior b,
int  triflaws 
)
private

Definition at line 7983 of file Triangle/Triangle.cpp.

References apex, badsubsegdealloc(), Nektar::NekMeshUtils::mesh::badsubsegs, badsubsegtraverse(), checkseg4encroach(), counterclockwise(), deadsubseg, deletevertex(), Nektar::NekMeshUtils::mesh::dummysub, Nektar::NekMeshUtils::mesh::dummytri, Nektar::NekMeshUtils::ENCROACHINGVERTEX, Nektar::NekMeshUtils::badsubseg::encsubseg, FREEVERTEX, insertvertex(), internalerror(), Nektar::NekMeshUtils::memorypool::items, lnext, lnextself, lprev, lprevself, mark, Nektar::NekMeshUtils::mesh::nextras, org, poolalloc(), precisionerror(), sdecode, sdest, SEGMENTVERTEX, setvertexmark, setvertextype, snextself, sorg, Nektar::NekMeshUtils::osub::ss, Nektar::NekMeshUtils::mesh::steinerleft, stpivot, Nektar::NekMeshUtils::badsubseg::subsegdest, Nektar::NekMeshUtils::badsubseg::subsegorg, Nektar::NekMeshUtils::SUCCESSFULVERTEX, sym, traversalinit(), Nektar::NekMeshUtils::otri::tri, triexit(), tspivot, vertextype, and Nektar::NekMeshUtils::mesh::vertices.

Referenced by enforcequality().

7984 {
7985  struct otri enctri;
7986  struct otri testtri;
7987  struct osub testsh;
7988  struct osub currentenc;
7989  struct badsubseg *encloop;
7990  vertex eorg, edest, eapex;
7991  vertex newvertex;
7992  enum insertvertexresult success;
7993  double segmentlength, nearestpoweroftwo;
7994  double split;
7995  double multiplier, divisor;
7996  int acuteorg, acuteorg2, acutedest, acutedest2;
7997  int i;
7998  triangle ptr; /* Temporary variable used by stpivot(). */
7999  subseg sptr; /* Temporary variable used by snext(). */
8000 
8001  /* Note that steinerleft == -1 if an unlimited number */
8002  /* of Steiner points is allowed. */
8003  while ((m->badsubsegs.items > 0) && (m->steinerleft != 0))
8004  {
8005  traversalinit(&m->badsubsegs);
8006  encloop = badsubsegtraverse(m);
8007  while ((encloop != (struct badsubseg *)NULL) && (m->steinerleft != 0))
8008  {
8009  sdecode(encloop->encsubseg, currentenc);
8010  sorg(currentenc, eorg);
8011  sdest(currentenc, edest);
8012  /* Make sure that this segment is still the same segment it was */
8013  /* when it was determined to be encroached. If the segment was */
8014  /* enqueued multiple times (because several newly inserted */
8015  /* vertices encroached it), it may have already been split. */
8016  if (!deadsubseg(currentenc.ss) && (eorg == encloop->subsegorg) &&
8017  (edest == encloop->subsegdest))
8018  {
8019  /* To decide where to split a segment, we need to know if the */
8020  /* segment shares an endpoint with an adjacent segment. */
8021  /* The concern is that, if we simply split every encroached */
8022  /* segment in its center, two adjacent segments with a small
8023  */
8024  /* angle between them might lead to an infinite loop; each */
8025  /* vertex added to split one segment will encroach upon the */
8026  /* other segment, which must then be split with a vertex that
8027  */
8028  /* will encroach upon the first segment, and so on forever. */
8029  /* To avoid this, imagine a set of concentric circles, whose */
8030  /* radii are powers of two, about each segment endpoint. */
8031  /* These concentric circles determine where the segment is */
8032  /* split. (If both endpoints are shared with adjacent */
8033  /* segments, split the segment in the middle, and apply the */
8034  /* concentric circles for later splittings.) */
8035 
8036  /* Is the origin shared with another segment? */
8037  stpivot(currentenc, enctri);
8038  lnext(enctri, testtri);
8039  tspivot(testtri, testsh);
8040  acuteorg = testsh.ss != m->dummysub;
8041  /* Is the destination shared with another segment? */
8042  lnextself(testtri);
8043  tspivot(testtri, testsh);
8044  acutedest = testsh.ss != m->dummysub;
8045 
8046  /* If we're using Chew's algorithm (rather than Ruppert's) */
8047  /* to define encroachment, delete free vertices from the */
8048  /* subsegment's diametral circle. */
8049  if (!acuteorg && !acutedest)
8050  {
8051  apex(enctri, eapex);
8052  while ((vertextype(eapex) == FREEVERTEX) &&
8053  ((eorg[0] - eapex[0]) * (edest[0] - eapex[0]) +
8054  (eorg[1] - eapex[1]) * (edest[1] - eapex[1]) <
8055  0.0))
8056  {
8057  deletevertex(m, b, &testtri);
8058  stpivot(currentenc, enctri);
8059  apex(enctri, eapex);
8060  lprev(enctri, testtri);
8061  }
8062  }
8063 
8064  /* Now, check the other side of the segment, if there's a
8065  * triangle */
8066  /* there. */
8067  sym(enctri, testtri);
8068  if (testtri.tri != m->dummytri)
8069  {
8070  /* Is the destination shared with another segment? */
8071  lnextself(testtri);
8072  tspivot(testtri, testsh);
8073  acutedest2 = testsh.ss != m->dummysub;
8074  acutedest = acutedest || acutedest2;
8075  /* Is the origin shared with another segment? */
8076  lnextself(testtri);
8077  tspivot(testtri, testsh);
8078  acuteorg2 = testsh.ss != m->dummysub;
8079  acuteorg = acuteorg || acuteorg2;
8080 
8081  /* Delete free vertices from the subsegment's diametral
8082  * circle. */
8083  if (!acuteorg2 && !acutedest2)
8084  {
8085  org(testtri, eapex);
8086  while (
8087  (vertextype(eapex) == FREEVERTEX) &&
8088  ((eorg[0] - eapex[0]) * (edest[0] - eapex[0]) +
8089  (eorg[1] - eapex[1]) * (edest[1] - eapex[1]) <
8090  0.0))
8091  {
8092  deletevertex(m, b, &testtri);
8093  sym(enctri, testtri);
8094  apex(testtri, eapex);
8095  lprevself(testtri);
8096  }
8097  }
8098  }
8099 
8100  /* Use the concentric circles if exactly one endpoint is shared
8101  */
8102  /* with another adjacent segment. */
8103  if (acuteorg || acutedest)
8104  {
8105  segmentlength =
8106  sqrt((edest[0] - eorg[0]) * (edest[0] - eorg[0]) +
8107  (edest[1] - eorg[1]) * (edest[1] - eorg[1]));
8108  /* Find the power of two that most evenly splits the
8109  * segment. */
8110  /* The worst case is a 2:1 ratio between subsegment
8111  * lengths. */
8112  nearestpoweroftwo = 1.0;
8113  while (segmentlength > 3.0 * nearestpoweroftwo)
8114  {
8115  nearestpoweroftwo *= 2.0;
8116  }
8117  while (segmentlength < 1.5 * nearestpoweroftwo)
8118  {
8119  nearestpoweroftwo *= 0.5;
8120  }
8121  /* Where do we split the segment? */
8122  split = nearestpoweroftwo / segmentlength;
8123  if (acutedest)
8124  {
8125  split = 1.0 - split;
8126  }
8127  }
8128  else
8129  {
8130  /* If we're not worried about adjacent segments, split */
8131  /* this segment in the middle. */
8132  split = 0.5;
8133  }
8134 
8135  /* Create the new vertex. */
8136  newvertex = (vertex)poolalloc(&m->vertices);
8137  /* Interpolate its coordinate and attributes. */
8138  for (i = 0; i < 2 + m->nextras; i++)
8139  {
8140  newvertex[i] = eorg[i] + split * (edest[i] - eorg[i]);
8141  }
8142 
8143  /* Roundoff in the above calculation may yield a `newvertex'
8144  */
8145  /* that is not precisely collinear with `eorg' and
8146  * `edest'. */
8147  /* Improve collinearity by one step of iterative
8148  * refinement. */
8149  multiplier = counterclockwise(m, b, eorg, edest, newvertex);
8150  divisor = ((eorg[0] - edest[0]) * (eorg[0] - edest[0]) +
8151  (eorg[1] - edest[1]) * (eorg[1] - edest[1]));
8152  if ((multiplier != 0.0) && (divisor != 0.0))
8153  {
8154  multiplier = multiplier / divisor;
8155  /* Watch out for NANs. */
8156  if (multiplier == multiplier)
8157  {
8158  newvertex[0] += multiplier * (edest[1] - eorg[1]);
8159  newvertex[1] += multiplier * (eorg[0] - edest[0]);
8160  }
8161  }
8162 
8163  setvertexmark(newvertex, mark(currentenc));
8164  setvertextype(newvertex, SEGMENTVERTEX);
8165 
8166  /* Check whether the new vertex lies on an endpoint. */
8167  if (((newvertex[0] == eorg[0]) && (newvertex[1] == eorg[1])) ||
8168  ((newvertex[0] == edest[0]) && (newvertex[1] == edest[1])))
8169  {
8170  printf("Error: Ran out of precision at (%.12g, %.12g).\n",
8171  newvertex[0],
8172  newvertex[1]);
8173  printf("I attempted to split a segment to a smaller size "
8174  "than\n");
8175  printf(
8176  " can be accommodated by the finite precision of\n");
8177  printf(" floating point arithmetic.\n");
8178  precisionerror();
8179  triexit(1);
8180  }
8181  /* Insert the splitting vertex. This should always succeed. */
8182  success = insertvertex(
8183  m, b, newvertex, &enctri, &currentenc, 1, triflaws);
8184  if ((success != SUCCESSFULVERTEX) &&
8185  (success != ENCROACHINGVERTEX))
8186  {
8187  printf("Internal error in splitencsegs():\n");
8188  printf(" Failure to split a segment.\n");
8189  internalerror();
8190  }
8191  if (m->steinerleft > 0)
8192  {
8193  m->steinerleft--;
8194  }
8195  /* Check the two new subsegments to see if they're encroached.
8196  */
8197  checkseg4encroach(m, b, &currentenc);
8198  snextself(currentenc);
8199  checkseg4encroach(m, b, &currentenc);
8200  }
8201 
8202  badsubsegdealloc(m, encloop);
8203  encloop = badsubsegtraverse(m);
8204  }
8205  }
8206 }
void badsubsegdealloc(struct mesh *m, struct badsubseg *dyingseg)
#define SEGMENTVERTEX
#define stpivot(osub, otri)
struct badsubseg * badsubsegtraverse(struct mesh *m)
void * poolalloc(struct memorypool *pool)
enum insertvertexresult insertvertex(struct mesh *m, struct behavior *b, vertex newvertex, struct otri *searchtri, struct osub *splitseg, int segmentflaws, int triflaws)
#define setvertextype(vx, value)
void traversalinit(struct memorypool *pool)
#define mark(osub)
#define sym(otri1, otri2)
#define lprev(otri1, otri2)
#define snextself(osub)
#define lnextself(otri)
#define vertextype(vx)
#define FREEVERTEX
#define sdest(osub, vertexptr)
double counterclockwise(struct mesh *m, struct behavior *b, vertex pa, vertex pb, vertex pc)
#define lprevself(otri)
#define apex(otri, vertexptr)
#define sorg(osub, vertexptr)
void deletevertex(struct mesh *m, struct behavior *b, struct otri *deltri)
#define setvertexmark(vx, value)
#define tspivot(otri, osub)
#define lnext(otri1, otri2)
#define deadsubseg(sub)
int checkseg4encroach(struct mesh *m, struct behavior *b, struct osub *testsubseg)
#define org(otri, vertexptr)
#define sdecode(sptr, osub)
void Nektar::NekMeshUtils::DelaunayTriangle::splittriangle ( struct mesh m,
struct behavior b,
struct badtriang badtri 
)
private

Definition at line 8238 of file Triangle/Triangle.cpp.

References apex, deadtri, decode, dest, Nektar::NekMeshUtils::ENCROACHINGVERTEX, findcircumcenter(), FREEVERTEX, insertvertex(), lprevself, Nektar::NekMeshUtils::mesh::nextras, org, poolalloc(), Nektar::NekMeshUtils::badtriang::poortri, precisionerror(), setvertexmark, setvertextype, Nektar::NekMeshUtils::mesh::steinerleft, Nektar::NekMeshUtils::SUCCESSFULVERTEX, Nektar::NekMeshUtils::otri::tri, Nektar::NekMeshUtils::badtriang::triangapex, Nektar::NekMeshUtils::badtriang::triangdest, Nektar::NekMeshUtils::badtriang::triangorg, undovertex(), vertexdealloc(), Nektar::NekMeshUtils::mesh::vertices, and Nektar::NekMeshUtils::VIOLATINGVERTEX.

Referenced by enforcequality().

8239 {
8240  struct otri badotri;
8241  vertex borg, bdest, bapex;
8242  vertex newvertex;
8243  double xi, eta;
8244  enum insertvertexresult success;
8245  int errorflag;
8246  int i;
8247 
8248  decode(badtri->poortri, badotri);
8249  org(badotri, borg);
8250  dest(badotri, bdest);
8251  apex(badotri, bapex);
8252  /* Make sure that this triangle is still the same triangle it was */
8253  /* when it was tested and determined to be of bad quality. */
8254  /* Subsequent transformations may have made it a different triangle. */
8255  if (!deadtri(badotri.tri) && (borg == badtri->triangorg) &&
8256  (bdest == badtri->triangdest) && (bapex == badtri->triangapex))
8257  {
8258 
8259 
8260  errorflag = 0;
8261  /* Create a new vertex at the triangle's circumcenter. */
8262  newvertex = (vertex)poolalloc(&m->vertices);
8263  findcircumcenter(m, b, borg, bdest, bapex, newvertex, &xi, &eta, 1);
8264 
8265  /* Check whether the new vertex lies on a triangle vertex. */
8266  if (((newvertex[0] == borg[0]) && (newvertex[1] == borg[1])) ||
8267  ((newvertex[0] == bdest[0]) && (newvertex[1] == bdest[1])) ||
8268  ((newvertex[0] == bapex[0]) && (newvertex[1] == bapex[1])))
8269  {
8270  vertexdealloc(m, newvertex);
8271  }
8272  else
8273  {
8274  for (i = 2; i < 2 + m->nextras; i++)
8275  {
8276  /* Interpolate the vertex attributes at the circumcenter. */
8277  newvertex[i] = borg[i] + xi * (bdest[i] - borg[i]) +
8278  eta * (bapex[i] - borg[i]);
8279  }
8280  /* The new vertex must be in the interior, and therefore is a */
8281  /* free vertex with a marker of zero. */
8282  setvertexmark(newvertex, 0);
8283  setvertextype(newvertex, FREEVERTEX);
8284 
8285  /* Ensure that the handle `badotri' does not represent the longest
8286  */
8287  /* edge of the triangle. This ensures that the circumcenter must
8288  */
8289  /* fall to the left of this edge, so point location will work. */
8290  /* (If the angle org-apex-dest exceeds 90 degrees, then the */
8291  /* circumcenter lies outside the org-dest edge, and eta is */
8292  /* negative. Roundoff error might prevent eta from being */
8293  /* negative when it should be, so I test eta against xi.) */
8294  if (eta < xi)
8295  {
8296  lprevself(badotri);
8297  }
8298 
8299  /* Insert the circumcenter, searching from the edge of the triangle,
8300  */
8301  /* and maintain the Delaunay property of the triangulation. */
8302  success = insertvertex(
8303  m, b, newvertex, &badotri, (struct osub *)NULL, 1, 1);
8304  if (success == SUCCESSFULVERTEX)
8305  {
8306  if (m->steinerleft > 0)
8307  {
8308  m->steinerleft--;
8309  }
8310  }
8311  else if (success == ENCROACHINGVERTEX)
8312  {
8313  /* If the newly inserted vertex encroaches upon a subsegment, */
8314  /* delete the new vertex. */
8315  undovertex(m, b);
8316 
8317  vertexdealloc(m, newvertex);
8318  }
8319  else if (success == VIOLATINGVERTEX)
8320  {
8321  /* Failed to insert the new vertex, but some subsegment was */
8322  /* marked as being encroached. */
8323  vertexdealloc(m, newvertex);
8324  }
8325  else
8326  { /* success == DUPLICATEVERTEX */
8327  /* Couldn't insert the new vertex because a vertex is already
8328  * there. */
8329 
8330  vertexdealloc(m, newvertex);
8331  }
8332  }
8333  if (errorflag)
8334  {
8335 
8336  printf(
8337  "This probably means that I am trying to refine triangles\n");
8338  printf(
8339  " to a smaller size than can be accommodated by the finite\n");
8340  printf(" precision of floating point arithmetic. (You can be\n");
8341  printf(" sure of this if I fail to terminate.)\n");
8342  precisionerror();
8343  }
8344  }
8345 }
void * poolalloc(struct memorypool *pool)
#define decode(ptr, otri)
enum insertvertexresult insertvertex(struct mesh *m, struct behavior *b, vertex newvertex, struct otri *searchtri, struct osub *splitseg, int segmentflaws, int triflaws)
#define setvertextype(vx, value)
void vertexdealloc(struct mesh *m, vertex dyingvertex)
#define FREEVERTEX
#define lprevself(otri)
#define apex(otri, vertexptr)
void undovertex(struct mesh *m, struct behavior *b)
#define setvertexmark(vx, value)
#define dest(otri, vertexptr)
#define deadtri(tria)
void findcircumcenter(struct mesh *m, struct behavior *b, vertex torg, vertex tdest, vertex tapex, vertex circumcenter, double *xi, double *eta, int offcenter)
#define org(otri, vertexptr)
void Nektar::NekMeshUtils::DelaunayTriangle::subsegdealloc ( struct mesh m,
subseg dyingsubseg 
)
private

Definition at line 1079 of file Triangle/Triangle.cpp.

References killsubseg, pooldealloc(), and Nektar::NekMeshUtils::mesh::subsegs.

Referenced by plague().

1080 {
1081  /* Mark the subsegment as dead. This makes it possible to detect dead */
1082  /* subsegments when traversing the list of all subsegments. */
1083  killsubseg(dyingsubseg);
1084  pooldealloc(&m->subsegs, (void *)dyingsubseg);
1085 }
void pooldealloc(struct memorypool *pool, void *dyingitem)
#define killsubseg(sub)
subseg * Nektar::NekMeshUtils::DelaunayTriangle::subsegtraverse ( struct mesh m)
private

Definition at line 1093 of file Triangle/Triangle.cpp.

References deadsubseg, Nektar::NekMeshUtils::mesh::subsegs, and traverse().

Referenced by tallyencs(), and writepoly().

1094 {
1095  subseg *newsubseg;
1096 
1097  do
1098  {
1099  newsubseg = (subseg *)traverse(&m->subsegs);
1100  if (newsubseg == (subseg *)NULL)
1101  {
1102  return (subseg *)NULL;
1103  }
1104  } while (deadsubseg(newsubseg)); /* Skip dead ones. */
1105  return newsubseg;
1106 }
void * traverse(struct memorypool *pool)
#define deadsubseg(sub)
void Nektar::NekMeshUtils::DelaunayTriangle::tallyencs ( struct mesh m,
struct behavior b 
)
private

Definition at line 7937 of file Triangle/Triangle.cpp.

References checkseg4encroach(), Nektar::NekMeshUtils::osub::ss, Nektar::NekMeshUtils::osub::ssorient, Nektar::NekMeshUtils::mesh::subsegs, subsegtraverse(), and traversalinit().

Referenced by enforcequality().

7938 {
7939  struct osub subsegloop;
7940 
7941  traversalinit(&m->subsegs);
7942  subsegloop.ssorient = 0;
7943  subsegloop.ss = subsegtraverse(m);
7944  while (subsegloop.ss != (subseg *)NULL)
7945  {
7946  /* If the segment is encroached, add it to the list. */
7947  checkseg4encroach(m, b, &subsegloop);
7948  subsegloop.ss = subsegtraverse(m);
7949  }
7950 }
void traversalinit(struct memorypool *pool)
int checkseg4encroach(struct mesh *m, struct behavior *b, struct osub *testsubseg)
void Nektar::NekMeshUtils::DelaunayTriangle::tallyfaces ( struct mesh m,
struct behavior b 
)
private

Definition at line 8214 of file Triangle/Triangle.cpp.

References Nektar::NekMeshUtils::otri::orient, testtriangle(), traversalinit(), Nektar::NekMeshUtils::otri::tri, Nektar::NekMeshUtils::mesh::triangles, and triangletraverse().

Referenced by enforcequality().

8215 {
8216  struct otri triangleloop;
8217 
8218 
8219  traversalinit(&m->triangles);
8220  triangleloop.orient = 0;
8221  triangleloop.tri = triangletraverse(m);
8222  while (triangleloop.tri != (triangle *)NULL)
8223  {
8224  /* If the triangle is bad, enqueue it. */
8225  testtriangle(m, b, &triangleloop);
8226  triangleloop.tri = triangletraverse(m);
8227  }
8228 }
void traversalinit(struct memorypool *pool)
void testtriangle(struct mesh *m, struct behavior *b, struct otri *testtri)
triangle * triangletraverse(struct mesh *m)
void Nektar::NekMeshUtils::DelaunayTriangle::testtriangle ( struct mesh m,
struct behavior b,
struct otri testtri 
)
private

Definition at line 3710 of file Triangle/Triangle.cpp.

References apex, dest, dnextself, Nektar::NekMeshUtils::mesh::dummysub, enqueuebadtri(), Nektar::NekMeshUtils::behavior::goodangle, lnext, lprev, oprevself, org, otricopy, segdest, SEGMENTVERTEX, segorg, Nektar::NekMeshUtils::osub::ss, triunsuitable(), tspivot, Nektar::NekMeshUtils::behavior::usertest, and vertextype.

Referenced by deletevertex(), insertvertex(), tallyfaces(), and triangulatepolygon().

3711 {
3712  struct otri tri1, tri2;
3713  struct osub testsub;
3714  vertex torg, tdest, tapex;
3715  vertex base1, base2;
3716  vertex org1, dest1, org2, dest2;
3717  vertex joinvertex;
3718  double dxod, dyod, dxda, dyda, dxao, dyao;
3719  double dxod2, dyod2, dxda2, dyda2, dxao2, dyao2;
3720  double apexlen, orglen, destlen, minedge;
3721  double angle;
3722  double area=0.0;
3723  double dist1, dist2;
3724  subseg sptr; /* Temporary variable used by tspivot(). */
3725  triangle ptr; /* Temporary variable used by oprev() and dnext(). */
3726 
3727  org(*testtri, torg);
3728  dest(*testtri, tdest);
3729  apex(*testtri, tapex);
3730  dxod = torg[0] - tdest[0];
3731  dyod = torg[1] - tdest[1];
3732  dxda = tdest[0] - tapex[0];
3733  dyda = tdest[1] - tapex[1];
3734  dxao = tapex[0] - torg[0];
3735  dyao = tapex[1] - torg[1];
3736  dxod2 = dxod * dxod;
3737  dyod2 = dyod * dyod;
3738  dxda2 = dxda * dxda;
3739  dyda2 = dyda * dyda;
3740  dxao2 = dxao * dxao;
3741  dyao2 = dyao * dyao;
3742  /* Find the lengths of the triangle's three edges. */
3743  apexlen = dxod2 + dyod2;
3744  orglen = dxda2 + dyda2;
3745  destlen = dxao2 + dyao2;
3746 
3747  if ((apexlen < orglen) && (apexlen < destlen))
3748  {
3749  /* The edge opposite the apex is shortest. */
3750  minedge = apexlen;
3751  /* Find the square of the cosine of the angle at the apex. */
3752  angle = dxda * dxao + dyda * dyao;
3753  angle = angle * angle / (orglen * destlen);
3754  base1 = torg;
3755  base2 = tdest;
3756  otricopy(*testtri, tri1);
3757  }
3758  else if (orglen < destlen)
3759  {
3760  /* The edge opposite the origin is shortest. */
3761  minedge = orglen;
3762  /* Find the square of the cosine of the angle at the origin. */
3763  angle = dxod * dxao + dyod * dyao;
3764  angle = angle * angle / (apexlen * destlen);
3765  base1 = tdest;
3766  base2 = tapex;
3767  lnext(*testtri, tri1);
3768  }
3769  else
3770  {
3771  /* The edge opposite the destination is shortest. */
3772  minedge = destlen;
3773  /* Find the square of the cosine of the angle at the destination. */
3774  angle = dxod * dxda + dyod * dyda;
3775  angle = angle * angle / (apexlen * orglen);
3776  base1 = tapex;
3777  base2 = torg;
3778  lprev(*testtri, tri1);
3779  }
3780 
3781  if (b->usertest)
3782  {
3783  if (b->usertest)
3784  {
3785  /* Check whether the user thinks this triangle is too large. */
3786  if (triunsuitable(torg, tdest, tapex, area))
3787  {
3788  enqueuebadtri(m, b, testtri, minedge, tapex, torg, tdest);
3789  return;
3790  }
3791  }
3792  }
3793 
3794  /* Check whether the angle is smaller than permitted. */
3795  if (angle > b->goodangle)
3796  {
3797  /* Use the rules of Miller, Pav, and Walkington to decide that certain
3798  */
3799  /* triangles should not be split, even if they have bad angles. */
3800  /* A skinny triangle is not split if its shortest edge subtends a */
3801  /* small input angle, and both endpoints of the edge lie on a */
3802  /* concentric circular shell. For convenience, I make a small */
3803  /* adjustment to that rule: I check if the endpoints of the edge */
3804  /* both lie in segment interiors, equidistant from the apex where */
3805  /* the two segments meet. */
3806  /* First, check if both points lie in segment interiors. */
3807  if ((vertextype(base1) == SEGMENTVERTEX) &&
3808  (vertextype(base2) == SEGMENTVERTEX))
3809  {
3810  /* Check if both points lie in a common segment. If they do, the */
3811  /* skinny triangle is enqueued to be split as usual. */
3812  tspivot(tri1, testsub);
3813  if (testsub.ss == m->dummysub)
3814  {
3815  /* No common segment. Find a subsegment that contains `torg'.
3816  */
3817  otricopy(tri1, tri2);
3818  do
3819  {
3820  oprevself(tri1);
3821  tspivot(tri1, testsub);
3822  } while (testsub.ss == m->dummysub);
3823  /* Find the endpoints of the containing segment. */
3824  segorg(testsub, org1);
3825  segdest(testsub, dest1);
3826  /* Find a subsegment that contains `tdest'. */
3827  do
3828  {
3829  dnextself(tri2);
3830  tspivot(tri2, testsub);
3831  } while (testsub.ss == m->dummysub);
3832  /* Find the endpoints of the containing segment. */
3833  segorg(testsub, org2);
3834  segdest(testsub, dest2);
3835  /* Check if the two containing segments have an endpoint in
3836  * common. */
3837  joinvertex = (vertex)NULL;
3838  if ((dest1[0] == org2[0]) && (dest1[1] == org2[1]))
3839  {
3840  joinvertex = dest1;
3841  }
3842  else if ((org1[0] == dest2[0]) && (org1[1] == dest2[1]))
3843  {
3844  joinvertex = org1;
3845  }
3846  if (joinvertex != (vertex)NULL)
3847  {
3848  /* Compute the distance from the common endpoint (of the two
3849  */
3850  /* segments) to each of the endpoints of the shortest
3851  * edge. */
3852  dist1 = ((base1[0] - joinvertex[0]) *
3853  (base1[0] - joinvertex[0]) +
3854  (base1[1] - joinvertex[1]) *
3855  (base1[1] - joinvertex[1]));
3856  dist2 = ((base2[0] - joinvertex[0]) *
3857  (base2[0] - joinvertex[0]) +
3858  (base2[1] - joinvertex[1]) *
3859  (base2[1] - joinvertex[1]));
3860  /* If the two distances are equal, don't split the triangle.
3861  */
3862  if ((dist1 < 1.001 * dist2) && (dist1 > 0.999 * dist2))
3863  {
3864  /* Return now to avoid enqueueing the bad triangle. */
3865  return;
3866  }
3867  }
3868  }
3869  }
3870 
3871  /* Add this triangle to the list of bad triangles. */
3872  enqueuebadtri(m, b, testtri, minedge, tapex, torg, tdest);
3873  }
3874 }
#define segdest(osub, vertexptr)
#define SEGMENTVERTEX
int triunsuitable(vertex triorg, vertex tridest, vertex triapex, double area)
#define segorg(osub, vertexptr)
void enqueuebadtri(struct mesh *m, struct behavior *b, struct otri *enqtri, double minedge, vertex enqapex, vertex enqorg, vertex enqdest)
#define lprev(otri1, otri2)
#define vertextype(vx)
#define apex(otri, vertexptr)
#define dnextself(otri)
#define oprevself(otri)
#define otricopy(otri1, otri2)
#define tspivot(otri, osub)
#define lnext(otri1, otri2)
#define dest(otri, vertexptr)
#define org(otri, vertexptr)
void Nektar::NekMeshUtils::DelaunayTriangle::transfernodes ( struct mesh m,
struct behavior b,
double *  pointlist,
double *  pointattriblist,
int *  pointmarkerlist,
int  numberofpoints,
int  numberofpointattribs 
)
private

Definition at line 8441 of file Triangle/Triangle.cpp.

References initializevertexpool(), INPUTVERTEX, Nektar::NekMeshUtils::mesh::invertices, Nektar::NekMeshUtils::mesh::mesh_dim, Nektar::NekMeshUtils::mesh::nextras, poolalloc(), Nektar::NekMeshUtils::mesh::readnodefile, setvertexmark, setvertextype, triexit(), Nektar::NekMeshUtils::mesh::vertices, Nektar::NekMeshUtils::behavior::weighted, Nektar::NekMeshUtils::mesh::xmax, Nektar::NekMeshUtils::mesh::xmin, Nektar::NekMeshUtils::mesh::xminextreme, Nektar::NekMeshUtils::mesh::ymax, and Nektar::NekMeshUtils::mesh::ymin.

Referenced by triangulate().

8448 {
8449  vertex vertexloop;
8450  double x, y;
8451  int i, j;
8452  int coordindex;
8453  int attribindex;
8454 
8455  m->invertices = numberofpoints;
8456  m->mesh_dim = 2;
8457  m->nextras = numberofpointattribs;
8458  m->readnodefile = 0;
8459  if (m->invertices < 3)
8460  {
8461  printf("Error: Input must have at least three input vertices.\n");
8462  triexit(1);
8463  }
8464  if (m->nextras == 0)
8465  {
8466  b->weighted = 0;
8467  }
8468 
8469  initializevertexpool(m, b);
8470 
8471  /* Read the vertices. */
8472  coordindex = 0;
8473  attribindex = 0;
8474  for (i = 0; i < m->invertices; i++)
8475  {
8476  vertexloop = (vertex)poolalloc(&m->vertices);
8477  /* Read the vertex coordinates. */
8478  x = vertexloop[0] = pointlist[coordindex++];
8479  y = vertexloop[1] = pointlist[coordindex++];
8480  /* Read the vertex attributes. */
8481  for (j = 0; j < numberofpointattribs; j++)
8482  {
8483  vertexloop[2 + j] = pointattriblist[attribindex++];
8484  }
8485  if (pointmarkerlist != (int *)NULL)
8486  {
8487  /* Read a vertex marker. */
8488  setvertexmark(vertexloop, pointmarkerlist[i]);
8489  }
8490  else
8491  {
8492  /* If no markers are specified, they default to zero. */
8493  setvertexmark(vertexloop, 0);
8494  }
8495  setvertextype(vertexloop, INPUTVERTEX);
8496  /* Determine the smallest and largest x and y coordinates. */
8497  if (i == 0)
8498  {
8499  m->xmin = m->xmax = x;
8500  m->ymin = m->ymax = y;
8501  }
8502  else
8503  {
8504  m->xmin = (x < m->xmin) ? x : m->xmin;
8505  m->xmax = (x > m->xmax) ? x : m->xmax;
8506  m->ymin = (y < m->ymin) ? y : m->ymin;
8507  m->ymax = (y > m->ymax) ? y : m->ymax;
8508  }
8509  }
8510 
8511  /* Nonexistent x value used as a flag to mark circle events in sweepline */
8512  /* Delaunay algorithm. */
8513  m->xminextreme = 10 * m->xmin - 9 * m->xmax;
8514 }
void * poolalloc(struct memorypool *pool)
#define setvertextype(vx, value)
void initializevertexpool(struct mesh *m, struct behavior *b)
#define INPUTVERTEX
#define setvertexmark(vx, value)
void Nektar::NekMeshUtils::DelaunayTriangle::traversalinit ( struct memorypool pool)
private

Definition at line 781 of file Triangle/Triangle.cpp.

References Nektar::NekMeshUtils::memorypool::alignbytes, Nektar::NekMeshUtils::memorypool::firstblock, Nektar::NekMeshUtils::memorypool::itemsfirstblock, Nektar::NekMeshUtils::memorypool::pathblock, Nektar::NekMeshUtils::memorypool::pathitem, and Nektar::NekMeshUtils::memorypool::pathitemsleft.

Referenced by divconqdelaunay(), makevertexmap(), numbernodes(), plague(), regionplague(), splitencsegs(), tallyencs(), tallyfaces(), writeelements(), writenodes(), and writepoly().

782 {
783  unsigned long alignptr;
784 
785  /* Begin the traversal in the first block. */
786  pool->pathblock = pool->firstblock;
787  /* Find the first item in the block. Increment by the size of (void *). */
788  alignptr = (unsigned long)(pool->pathblock + 1);
789  /* Align with item on an `alignbytes'-byte boundary. */
790  pool->pathitem = (void *)(alignptr + (unsigned long)pool->alignbytes -
791  (alignptr % (unsigned long)pool->alignbytes));
792  /* Set the number of items left in the current block. */
793  pool->pathitemsleft = pool->itemsfirstblock;
794 }
void * Nektar::NekMeshUtils::DelaunayTriangle::traverse ( struct memorypool pool)
private

Definition at line 810 of file Triangle/Triangle.cpp.

References Nektar::NekMeshUtils::memorypool::alignbytes, Nektar::NekMeshUtils::memorypool::itembytes, Nektar::NekMeshUtils::memorypool::itemsperblock, Nektar::NekMeshUtils::memorypool::nextitem, Nektar::NekMeshUtils::memorypool::pathblock, Nektar::NekMeshUtils::memorypool::pathitem, and Nektar::NekMeshUtils::memorypool::pathitemsleft.

Referenced by badsubsegtraverse(), plague(), regionplague(), subsegtraverse(), triangletraverse(), and vertextraverse().

811 {
812  void *newitem;
813  unsigned long alignptr;
814 
815  /* Stop upon exhausting the list of items. */
816  if (pool->pathitem == pool->nextitem)
817  {
818  return (void *)NULL;
819  }
820 
821  /* Check whether any untraversed items remain in the current block. */
822  if (pool->pathitemsleft == 0)
823  {
824  /* Find the next block. */
825  pool->pathblock = (void **)*(pool->pathblock);
826  /* Find the first item in the block. Increment by the size of (void *).
827  */
828  alignptr = (unsigned long)(pool->pathblock + 1);
829  /* Align with item on an `alignbytes'-byte boundary. */
830  pool->pathitem = (void *)(alignptr + (unsigned long)pool->alignbytes -
831  (alignptr % (unsigned long)pool->alignbytes));
832  /* Set the number of items left in the current block. */
833  pool->pathitemsleft = pool->itemsperblock;
834  }
835 
836  newitem = pool->pathitem;
837  /* Find the next item in the block. */
838  pool->pathitem = (void *)((char *)pool->pathitem + pool->itembytes);
839  pool->pathitemsleft--;
840  return newitem;
841 }
void Nektar::NekMeshUtils::DelaunayTriangle::triangledealloc ( struct mesh m,
triangle dyingtriangle 
)
private

Definition at line 1044 of file Triangle/Triangle.cpp.

References killtri, pooldealloc(), and Nektar::NekMeshUtils::mesh::triangles.

Referenced by deletevertex(), plague(), removeghosts(), and undovertex().

1045 {
1046  /* Mark the triangle as dead. This makes it possible to detect dead */
1047  /* triangles when traversing the list of all triangles. */
1048  killtri(dyingtriangle);
1049  pooldealloc(&m->triangles, (void *)dyingtriangle);
1050 }
#define killtri(tria)
void pooldealloc(struct memorypool *pool, void *dyingitem)
void Nektar::NekMeshUtils::DelaunayTriangle::triangledeinit ( struct mesh m,
struct behavior b 
)
private

Definition at line 1227 of file Triangle/Triangle.cpp.

References Nektar::NekMeshUtils::mesh::badsubsegs, Nektar::NekMeshUtils::mesh::badtriangles, Nektar::NekMeshUtils::mesh::dummysubbase, Nektar::NekMeshUtils::mesh::dummytribase, Nektar::NekMeshUtils::mesh::flipstackers, Nektar::NekMeshUtils::behavior::minangle, pooldeinit(), Nektar::NekMeshUtils::behavior::quality, Nektar::NekMeshUtils::mesh::subsegs, Nektar::NekMeshUtils::mesh::triangles, trifree(), Nektar::NekMeshUtils::behavior::usertest, Nektar::NekMeshUtils::behavior::usesegments, and Nektar::NekMeshUtils::mesh::vertices.

Referenced by triangulate().

1228 {
1229  pooldeinit(&m->triangles);
1230  trifree((void *)m->dummytribase);
1231  if (b->usesegments)
1232  {
1233  pooldeinit(&m->subsegs);
1234  trifree((void *)m->dummysubbase);
1235  }
1236  pooldeinit(&m->vertices);
1237  if (b->quality)
1238  {
1239  pooldeinit(&m->badsubsegs);
1240  if ((b->minangle > 0.0) || b->usertest)
1241  {
1242  pooldeinit(&m->badtriangles);
1243  pooldeinit(&m->flipstackers);
1244  }
1245  }
1246 }
void pooldeinit(struct memorypool *pool)
void Nektar::NekMeshUtils::DelaunayTriangle::triangleinit ( struct mesh m)
private

Definition at line 3381 of file Triangle/Triangle.cpp.

References Nektar::NekMeshUtils::mesh::badsubsegs, Nektar::NekMeshUtils::mesh::badtriangles, Nektar::NekMeshUtils::mesh::checkquality, Nektar::NekMeshUtils::mesh::checksegments, Nektar::NekMeshUtils::mesh::circletopcount, Nektar::NekMeshUtils::mesh::circumcentercount, Nektar::NekMeshUtils::mesh::counterclockcount, exactinit(), Nektar::NekMeshUtils::mesh::flipstackers, Nektar::NekMeshUtils::mesh::hyperbolacount, Nektar::NekMeshUtils::mesh::incirclecount, Nektar::NekMeshUtils::mesh::orient3dcount, poolzero(), randomseed, Nektar::NekMeshUtils::mesh::recenttri, Nektar::NekMeshUtils::mesh::samples, Nektar::NekMeshUtils::mesh::splaynodes, Nektar::NekMeshUtils::mesh::subsegs, Nektar::NekMeshUtils::otri::tri, Nektar::NekMeshUtils::mesh::triangles, Nektar::NekMeshUtils::mesh::undeads, Nektar::NekMeshUtils::mesh::vertices, and Nektar::NekMeshUtils::mesh::viri.

Referenced by triangulate().

3382 {
3383  poolzero(&m->vertices);
3384  poolzero(&m->triangles);
3385  poolzero(&m->subsegs);
3386  poolzero(&m->viri);
3387  poolzero(&m->badsubsegs);
3388  poolzero(&m->badtriangles);
3389  poolzero(&m->flipstackers);
3390  poolzero(&m->splaynodes);
3391 
3392  m->recenttri.tri = (triangle *)NULL; /* No triangle has been visited yet. */
3393  m->undeads = 0; /* No eliminated input vertices yet. */
3394  m->samples = 1; /* Point location should take at least one sample. */
3395  m->checksegments = 0; /* There are no segments in the triangulation yet. */
3396  m->checkquality = 0; /* The quality triangulation stage has not begun. */
3397  m->incirclecount = m->counterclockcount = m->orient3dcount = 0;
3398  m->hyperbolacount = m->circletopcount = m->circumcentercount = 0;
3399  randomseed = 1;
3400 
3401  exactinit(); /* Initialize exact arithmetic constants. */
3402 }
void poolzero(struct memorypool *pool)
triangle * Nektar::NekMeshUtils::DelaunayTriangle::triangletraverse ( struct mesh m)
private

Definition at line 1058 of file Triangle/Triangle.cpp.

References deadtri, traverse(), and Nektar::NekMeshUtils::mesh::triangles.

Referenced by makevertexmap(), tallyfaces(), and writeelements().

1059 {
1060  triangle *newtriangle;
1061 
1062  do
1063  {
1064  newtriangle = (triangle *)traverse(&m->triangles);
1065  if (newtriangle == (triangle *)NULL)
1066  {
1067  return (triangle *)NULL;
1068  }
1069  } while (deadtri(newtriangle)); /* Skip dead ones. */
1070  return newtriangle;
1071 }
void * traverse(struct memorypool *pool)
#define deadtri(tria)
void Nektar::NekMeshUtils::DelaunayTriangle::triangulate ( char *  triswitches)

Definition at line 8777 of file Triangle/Triangle.cpp.

References carveholes(), Nektar::NekMeshUtils::mesh::checksegments, delaunay(), Nektar::NekMeshUtils::mesh::edges, Nektar::NekMeshUtils::mesh::eextras, enforcequality(), formskeleton(), Nektar::NekMeshUtils::triangulateio::holelist, Nektar::NekMeshUtils::mesh::holes, Nektar::NekMeshUtils::mesh::hullsize, Nektar::NekMeshUtils::mesh::infvertex1, Nektar::NekMeshUtils::mesh::infvertex2, Nektar::NekMeshUtils::mesh::infvertex3, Nektar::NekMeshUtils::memorypool::items, Nektar::NekMeshUtils::behavior::jettison, minus1mod3, Nektar::NekMeshUtils::mesh::nextras, Nektar::NekMeshUtils::triangulateio::numberofcorners, Nektar::NekMeshUtils::triangulateio::numberofedges, Nektar::NekMeshUtils::triangulateio::numberofholes, Nektar::NekMeshUtils::triangulateio::numberofpointattributes, Nektar::NekMeshUtils::triangulateio::numberofpoints, Nektar::NekMeshUtils::triangulateio::numberofregions, Nektar::NekMeshUtils::triangulateio::numberofsegments, Nektar::NekMeshUtils::triangulateio::numberoftriangleattributes, Nektar::NekMeshUtils::triangulateio::numberoftriangles, out, parsecommandline(), plus1mod3, Nektar::NekMeshUtils::triangulateio::pointattributelist, Nektar::NekMeshUtils::triangulateio::pointlist, Nektar::NekMeshUtils::triangulateio::pointmarkerlist, Nektar::NekMeshUtils::behavior::poly, Nektar::NekMeshUtils::behavior::quality, Nektar::NekMeshUtils::triangulateio::regionlist, Nektar::NekMeshUtils::mesh::regions, Nektar::NekMeshUtils::triangulateio::segmentlist, Nektar::NekMeshUtils::triangulateio::segmentmarkerlist, Nektar::NekMeshUtils::mesh::steinerleft, Nektar::NekMeshUtils::mesh::subsegs, transfernodes(), Nektar::NekMeshUtils::triangulateio::triangleattributelist, triangledeinit(), triangleinit(), Nektar::NekMeshUtils::triangulateio::trianglelist, Nektar::NekMeshUtils::mesh::triangles, Nektar::NekMeshUtils::mesh::undeads, Nektar::NekMeshUtils::behavior::usesegments, Nektar::NekMeshUtils::mesh::vertices, writeelements(), writenodes(), and writepoly().

8778 {
8779  struct mesh m;
8780  struct behavior b;
8781  double *holearray; /* Array of holes. */
8782  double
8783  *regionarray; /* Array of regional attributes and area constraints. */
8784 
8785  plus1mod3[0]= 1;
8786  plus1mod3[1]= 2;
8787  plus1mod3[2]= 0;
8788  minus1mod3[0] = 2;
8789  minus1mod3[1] = 0;
8790  minus1mod3[2] = 1;
8791 
8792  triangleinit(&m);
8793 
8794  parsecommandline(1, &triswitches, &b);
8795 
8796  m.steinerleft = -1;
8797 
8798  transfernodes(&m,
8799  &b,
8800  in.pointlist,
8801  in.pointattributelist,
8802  in.pointmarkerlist,
8803  in.numberofpoints,
8804  in.numberofpointattributes);
8805 
8806 
8807  m.hullsize = delaunay(&m, &b); /* Triangulate the vertices. */
8808 
8809  /* Ensure that no vertex can be mistaken for a triangular bounding */
8810  /* box vertex in insertvertex(). */
8811  m.infvertex1 = (vertex)NULL;
8812  m.infvertex2 = (vertex)NULL;
8813  m.infvertex3 = (vertex)NULL;
8814 
8815  if (b.usesegments)
8816  {
8817  m.checksegments = 1; /* Segments will be introduced next. */
8818 
8819  formskeleton(&m,
8820  &b,
8821  in.segmentlist,
8822  in.segmentmarkerlist,
8823  in.numberofsegments);
8824  }
8825 
8826  if (b.poly && (m.triangles.items > 0))
8827  {
8828  holearray = in.holelist;
8829  m.holes = in.numberofholes;
8830  regionarray = in.regionlist;
8831  m.regions = in.numberofregions;
8832 
8833  /* Carve out holes and concavities. */
8834  carveholes(&m, &b, holearray, m.holes, regionarray, m.regions);
8835  }
8836  else
8837  {
8838  /* Without a PSLG, there can be no holes or regional attributes */
8839  /* or area constraints. The following are set to zero to avoid */
8840  /* an accidental free() later. */
8841  m.holes = 0;
8842  m.regions = 0;
8843  }
8844 
8845  if (b.quality && (m.triangles.items > 0))
8846  {
8847  enforcequality(&m, &b); /* Enforce angle and area constraints. */
8848  }
8849 
8850  /* Calculate the number of edges. */
8851  m.edges = (3l * m.triangles.items + m.hullsize) / 2l;
8852 
8853  if (b.jettison)
8854  {
8855  out.numberofpoints = m.vertices.items - m.undeads;
8856  }
8857  else
8858  {
8859  out.numberofpoints = m.vertices.items;
8860  }
8861  out.numberofpointattributes = m.nextras;
8862  out.numberoftriangles = m.triangles.items;
8863  out.numberofcorners = 3;
8864  out.numberoftriangleattributes = m.eextras;
8865  out.numberofedges = m.edges;
8866  if (b.usesegments)
8867  {
8868  out.numberofsegments = m.subsegs.items;
8869  }
8870  else
8871  {
8872  out.numberofsegments = m.hullsize;
8873  }
8874 
8875  /* writenodes() numbers the vertices too. */
8876  writenodes(&m,
8877  &b,
8878  &out.pointlist,
8880  &out.pointmarkerlist);
8881 
8883 
8884  /* The -c switch (convex switch) causes a PSLG to be written */
8885  /* even if none was read. */
8886  if (b.poly)
8887  {
8888 
8890  out.numberofholes = m.holes;
8891  out.numberofregions = m.regions;
8892  if (b.poly)
8893  {
8894  out.holelist = in.holelist;
8895  out.regionlist = in.regionlist;
8896  }
8897  else
8898  {
8899  out.holelist = (double *)NULL;
8900  out.regionlist = (double *)NULL;
8901  }
8902  }
8903 
8904  triangledeinit(&m, &b);
8905 }
void triangledeinit(struct mesh *m, struct behavior *b)
void writepoly(struct mesh *m, struct behavior *b, int **segmentlist, int **segmentmarkerlist)
void writenodes(struct mesh *m, struct behavior *b, double **pointlist, double **pointattriblist, int **pointmarkerlist)
void formskeleton(struct mesh *m, struct behavior *b, int *segmentlist, int *segmentmarkerlist, int numberofsegments)
void writeelements(struct mesh *m, struct behavior *b, int **trianglelist, double **triangleattriblist)
void carveholes(struct mesh *m, struct behavior *b, double *holelist, int holes, double *regionlist, int regions)
long delaunay(struct mesh *m, struct behavior *b)
void transfernodes(struct mesh *m, struct behavior *b, double *pointlist, double *pointattriblist, int *pointmarkerlist, int numberofpoints, int numberofpointattribs)
void enforcequality(struct mesh *m, struct behavior *b)
void parsecommandline(int argc, char **argv, struct behavior *b)
void Nektar::NekMeshUtils::DelaunayTriangle::triangulatepolygon ( struct mesh m,
struct behavior b,
struct otri firstedge,
struct otri lastedge,
int  edgecount,
int  doflip,
int  triflaws 
)
private

Definition at line 5257 of file Triangle/Triangle.cpp.

References apex, dest, flip(), incircle(), onext, onextself, oprev, otricopy, sym, and testtriangle().

Referenced by deletevertex().

5264 {
5265  struct otri testtri;
5266  struct otri besttri;
5267  struct otri tempedge;
5268  vertex leftbasevertex, rightbasevertex;
5269  vertex testvertex;
5270  vertex bestvertex;
5271  int bestnumber;
5272  int i;
5273  triangle ptr; /* Temporary variable used by sym(), onext(), and oprev(). */
5274 
5275  /* Identify the base vertices. */
5276  apex(*lastedge, leftbasevertex);
5277  dest(*firstedge, rightbasevertex);
5278 
5279  /* Find the best vertex to connect the base to. */
5280  onext(*firstedge, besttri);
5281  dest(besttri, bestvertex);
5282  otricopy(besttri, testtri);
5283  bestnumber = 1;
5284  for (i = 2; i <= edgecount - 2; i++)
5285  {
5286  onextself(testtri);
5287  dest(testtri, testvertex);
5288  /* Is this a better vertex? */
5289  if (incircle(
5290  m, b, leftbasevertex, rightbasevertex, bestvertex, testvertex) >
5291  0.0)
5292  {
5293  otricopy(testtri, besttri);
5294  bestvertex = testvertex;
5295  bestnumber = i;
5296  }
5297  }
5298 
5299  if (bestnumber > 1)
5300  {
5301  /* Recursively triangulate the smaller polygon on the right. */
5302  oprev(besttri, tempedge);
5304  m, b, firstedge, &tempedge, bestnumber + 1, 1, triflaws);
5305  }
5306  if (bestnumber < edgecount - 2)
5307  {
5308  /* Recursively triangulate the smaller polygon on the left. */
5309  sym(besttri, tempedge);
5311  m, b, &besttri, lastedge, edgecount - bestnumber, 1, triflaws);
5312  /* Find `besttri' again; it may have been lost to edge flips. */
5313  sym(tempedge, besttri);
5314  }
5315  if (doflip)
5316  {
5317  /* Do one final edge flip. */
5318  flip(m, b, &besttri);
5319  if (triflaws)
5320  {
5321  /* Check the quality of the newly committed triangle. */
5322  sym(besttri, testtri);
5323  testtriangle(m, b, &testtri);
5324  }
5325  }
5326  /* Return the base triangle. */
5327  otricopy(besttri, *lastedge);
5328 }
#define onextself(otri)
double incircle(struct mesh *m, struct behavior *b, vertex pa, vertex pb, vertex pc, vertex pd)
void triangulatepolygon(struct mesh *m, struct behavior *b, struct otri *firstedge, struct otri *lastedge, int edgecount, int doflip, int triflaws)
#define sym(otri1, otri2)
void testtriangle(struct mesh *m, struct behavior *b, struct otri *testtri)
void flip(struct mesh *m, struct behavior *b, struct otri *flipedge)
#define onext(otri1, otri2)
#define apex(otri, vertexptr)
#define oprev(otri1, otri2)
#define otricopy(otri1, otri2)
#define dest(otri, vertexptr)
void Nektar::NekMeshUtils::DelaunayTriangle::triexit ( int  status)
private

Definition at line 420 of file Triangle/Triangle.cpp.

Referenced by internalerror(), splitencsegs(), transfernodes(), and trimalloc().

421 {
422  exit(status);
423 }
void Nektar::NekMeshUtils::DelaunayTriangle::trifree ( void memptr)

Definition at line 438 of file Triangle/Triangle.cpp.

Referenced by carveholes(), divconqdelaunay(), pooldeinit(), and triangledeinit().

439 {
440  free(memptr);
441 }
void * Nektar::NekMeshUtils::DelaunayTriangle::trimalloc ( int  size)
private

Definition at line 425 of file Triangle/Triangle.cpp.

References triexit().

Referenced by carveholes(), divconqdelaunay(), dummyinit(), poolalloc(), poolinit(), writeelements(), writenodes(), and writepoly().

426 {
427  void *memptr;
428 
429  memptr = (void *)malloc((unsigned int)size);
430  if (memptr == (void *)NULL)
431  {
432  printf("Error: Out of memory.\n");
433  triexit(1);
434  }
435  return (memptr);
436 }
int Nektar::NekMeshUtils::DelaunayTriangle::triunsuitable ( vertex  triorg,
vertex  tridest,
vertex  triapex,
double  area 
)
private

Definition at line 379 of file Triangle/Triangle.cpp.

Referenced by testtriangle().

380 {
381  double dxoa, dxda, dxod;
382  double dyoa, dyda, dyod;
383  double oalen, dalen, odlen;
384  double maxlen;
385 
386  dxoa = triorg[0] - triapex[0];
387  dyoa = triorg[1] - triapex[1];
388  dxda = tridest[0] - triapex[0];
389  dyda = tridest[1] - triapex[1];
390  dxod = triorg[0] - tridest[0];
391  dyod = triorg[1] - tridest[1];
392  /* Find the squares of the lengths of the triangle's three edges. */
393  oalen = dxoa * dxoa + dyoa * dyoa;
394  dalen = dxda * dxda + dyda * dyda;
395  odlen = dxod * dxod + dyod * dyod;
396  /* Find the square of the length of the longest edge. */
397  maxlen = (dalen > oalen) ? dalen : oalen;
398  maxlen = (odlen > maxlen) ? odlen : maxlen;
399 
400  if (maxlen > 0.05 * (triorg[0] * triorg[0] + triorg[1] * triorg[1]) + 0.02)
401  {
402  return 1;
403  }
404  else
405  {
406  return 0;
407  }
408 }
void Nektar::NekMeshUtils::DelaunayTriangle::undovertex ( struct mesh m,
struct behavior b 
)
private

Definition at line 5424 of file Triangle/Triangle.cpp.

References bond, decode, dest, dnext, dprev, Nektar::NekMeshUtils::mesh::dummytri, Nektar::NekMeshUtils::flipstacker::flippedtri, Nektar::NekMeshUtils::mesh::lastflip, lnextself, lprev, lprevself, onext, Nektar::NekMeshUtils::flipstacker::prevflip, setapex, setorg, sym, Nektar::NekMeshUtils::otri::tri, triangledealloc(), tsbond, tspivot, and unflip().

Referenced by splittriangle().

5425 {
5426  struct otri fliptri;
5427  struct otri botleft, botright, topright;
5428  struct otri botlcasing, botrcasing, toprcasing;
5429  struct otri gluetri;
5430  struct osub botlsubseg, botrsubseg, toprsubseg;
5431  vertex botvertex, rightvertex;
5432  triangle ptr; /* Temporary variable used by sym(). */
5433  subseg sptr; /* Temporary variable used by tspivot(). */
5434 
5435  /* Walk through the list of transformations (flips and a vertex insertion)
5436  */
5437  /* in the reverse of the order in which they were done, and undo them. */
5438  while (m->lastflip != (struct flipstacker *)NULL)
5439  {
5440  /* Find a triangle involved in the last unreversed transformation. */
5441  decode(m->lastflip->flippedtri, fliptri);
5442 
5443  /* We are reversing one of three transformations: a trisection of one
5444  */
5445  /* triangle into three (by inserting a vertex in the triangle), a */
5446  /* bisection of two triangles into four (by inserting a vertex in an
5447  */
5448  /* edge), or an edge flip. */
5449  if (m->lastflip->prevflip == (struct flipstacker *)NULL)
5450  {
5451  /* Restore a triangle that was split into three triangles, */
5452  /* so it is again one triangle. */
5453  dprev(fliptri, botleft);
5454  lnextself(botleft);
5455  onext(fliptri, botright);
5456  lprevself(botright);
5457  sym(botleft, botlcasing);
5458  sym(botright, botrcasing);
5459  dest(botleft, botvertex);
5460 
5461  setapex(fliptri, botvertex);
5462  lnextself(fliptri);
5463  bond(fliptri, botlcasing);
5464  tspivot(botleft, botlsubseg);
5465  tsbond(fliptri, botlsubseg);
5466  lnextself(fliptri);
5467  bond(fliptri, botrcasing);
5468  tspivot(botright, botrsubseg);
5469  tsbond(fliptri, botrsubseg);
5470 
5471  /* Delete the two spliced-out triangles. */
5472  triangledealloc(m, botleft.tri);
5473  triangledealloc(m, botright.tri);
5474  }
5475  else if (m->lastflip->prevflip == (struct flipstacker *)1)
5476  {
5477  /* Restore two triangles that were split into four triangles, */
5478  /* so they are again two triangles. */
5479  lprev(fliptri, gluetri);
5480  sym(gluetri, botright);
5481  lnextself(botright);
5482  sym(botright, botrcasing);
5483  dest(botright, rightvertex);
5484 
5485  setorg(fliptri, rightvertex);
5486  bond(gluetri, botrcasing);
5487  tspivot(botright, botrsubseg);
5488  tsbond(gluetri, botrsubseg);
5489 
5490  /* Delete the spliced-out triangle. */
5491  triangledealloc(m, botright.tri);
5492 
5493  sym(fliptri, gluetri);
5494  if (gluetri.tri != m->dummytri)
5495  {
5496  lnextself(gluetri);
5497  dnext(gluetri, topright);
5498  sym(topright, toprcasing);
5499 
5500  setorg(gluetri, rightvertex);
5501  bond(gluetri, toprcasing);
5502  tspivot(topright, toprsubseg);
5503  tsbond(gluetri, toprsubseg);
5504 
5505  /* Delete the spliced-out triangle. */
5506  triangledealloc(m, topright.tri);
5507  }
5508 
5509  /* This is the end of the list, sneakily encoded. */
5510  m->lastflip->prevflip = (struct flipstacker *)NULL;
5511  }
5512  else
5513  {
5514  /* Undo an edge flip. */
5515  unflip(m, b, &fliptri);
5516  }
5517 
5518  /* Go on and process the next transformation. */
5519  m->lastflip = m->lastflip->prevflip;
5520  }
5521 }
#define bond(otri1, otri2)
#define setapex(otri, vertexptr)
#define decode(ptr, otri)
void triangledealloc(struct mesh *m, triangle *dyingtriangle)
#define setorg(otri, vertexptr)
#define sym(otri1, otri2)
#define tsbond(otri, osub)
#define lprev(otri1, otri2)
void unflip(struct mesh *m, struct behavior *b, struct otri *flipedge)
#define lnextself(otri)
#define dnext(otri1, otri2)
#define lprevself(otri)
#define onext(otri1, otri2)
#define tspivot(otri, osub)
#define dest(otri, vertexptr)
#define dprev(otri1, otri2)
void Nektar::NekMeshUtils::DelaunayTriangle::unflip ( struct mesh m,
struct behavior b,
struct otri flipedge 
)
private

Definition at line 4525 of file Triangle/Triangle.cpp.

References apex, bond, Nektar::NekMeshUtils::mesh::checksegments, dest, Nektar::NekMeshUtils::mesh::dummysub, lnext, lprev, org, setapex, setdest, setorg, Nektar::NekMeshUtils::osub::ss, sym, tsbond, tsdissolve, and tspivot.

Referenced by undovertex().

4526 {
4527  struct otri botleft, botright;
4528  struct otri topleft, topright;
4529  struct otri top;
4530  struct otri botlcasing, botrcasing;
4531  struct otri toplcasing, toprcasing;
4532  struct osub botlsubseg, botrsubseg;
4533  struct osub toplsubseg, toprsubseg;
4534  vertex leftvertex, rightvertex, botvertex;
4535  vertex farvertex;
4536  triangle ptr; /* Temporary variable used by sym(). */
4537  subseg sptr; /* Temporary variable used by tspivot(). */
4538 
4539  /* Identify the vertices of the quadrilateral. */
4540  org(*flipedge, rightvertex);
4541  dest(*flipedge, leftvertex);
4542  apex(*flipedge, botvertex);
4543  sym(*flipedge, top);
4544  apex(top, farvertex);
4545 
4546  /* Identify the casing of the quadrilateral. */
4547  lprev(top, topleft);
4548  sym(topleft, toplcasing);
4549  lnext(top, topright);
4550  sym(topright, toprcasing);
4551  lnext(*flipedge, botleft);
4552  sym(botleft, botlcasing);
4553  lprev(*flipedge, botright);
4554  sym(botright, botrcasing);
4555  /* Rotate the quadrilateral one-quarter turn clockwise. */
4556  bond(topleft, toprcasing);
4557  bond(botleft, toplcasing);
4558  bond(botright, botlcasing);
4559  bond(topright, botrcasing);
4560 
4561  if (m->checksegments)
4562  {
4563  /* Check for subsegments and rebond them to the quadrilateral. */
4564  tspivot(topleft, toplsubseg);
4565  tspivot(botleft, botlsubseg);
4566  tspivot(botright, botrsubseg);
4567  tspivot(topright, toprsubseg);
4568  if (toplsubseg.ss == m->dummysub)
4569  {
4570  tsdissolve(botleft);
4571  }
4572  else
4573  {
4574  tsbond(botleft, toplsubseg);
4575  }
4576  if (botlsubseg.ss == m->dummysub)
4577  {
4578  tsdissolve(botright);
4579  }
4580  else
4581  {
4582  tsbond(botright, botlsubseg);
4583  }
4584  if (botrsubseg.ss == m->dummysub)
4585  {
4586  tsdissolve(topright);
4587  }
4588  else
4589  {
4590  tsbond(topright, botrsubseg);
4591  }
4592  if (toprsubseg.ss == m->dummysub)
4593  {
4594  tsdissolve(topleft);
4595  }
4596  else
4597  {
4598  tsbond(topleft, toprsubseg);
4599  }
4600  }
4601 
4602  /* New vertex assignments for the rotated quadrilateral. */
4603  setorg(*flipedge, botvertex);
4604  setdest(*flipedge, farvertex);
4605  setapex(*flipedge, leftvertex);
4606  setorg(top, farvertex);
4607  setdest(top, botvertex);
4608  setapex(top, rightvertex);
4609 }
#define setdest(otri, vertexptr)
#define bond(otri1, otri2)
#define setapex(otri, vertexptr)
#define tsdissolve(otri)
#define setorg(otri, vertexptr)
#define sym(otri1, otri2)
#define tsbond(otri, osub)
#define lprev(otri1, otri2)
#define apex(otri, vertexptr)
#define tspivot(otri, osub)
#define lnext(otri1, otri2)
#define dest(otri, vertexptr)
#define org(otri, vertexptr)
void Nektar::NekMeshUtils::DelaunayTriangle::vertexdealloc ( struct mesh m,
vertex  dyingvertex 
)
private

Definition at line 1114 of file Triangle/Triangle.cpp.

References DEADVERTEX, pooldealloc(), setvertextype, and Nektar::NekMeshUtils::mesh::vertices.

Referenced by conformingedge(), deletevertex(), and splittriangle().

1115 {
1116  /* Mark the vertex as dead. This makes it possible to detect dead */
1117  /* vertices when traversing the list of all vertices. */
1118  setvertextype(dyingvertex, DEADVERTEX);
1119  pooldealloc(&m->vertices, (void *)dyingvertex);
1120 }
#define setvertextype(vx, value)
void pooldealloc(struct memorypool *pool, void *dyingitem)
#define DEADVERTEX
void Nektar::NekMeshUtils::DelaunayTriangle::vertexmedian ( vertex sortarray,
int  arraysize,
int  median,
int  axis 
)
private

Definition at line 5647 of file Triangle/Triangle.cpp.

References randomnation().

Referenced by alternateaxes().

5648 {
5649  int left, right;
5650  int pivot;
5651  double pivot1, pivot2;
5652  vertex temp;
5653 
5654  if (arraysize == 2)
5655  {
5656  /* Recursive base case. */
5657  if ((sortarray[0][axis] > sortarray[1][axis]) ||
5658  ((sortarray[0][axis] == sortarray[1][axis]) &&
5659  (sortarray[0][1 - axis] > sortarray[1][1 - axis])))
5660  {
5661  temp = sortarray[1];
5662  sortarray[1] = sortarray[0];
5663  sortarray[0] = temp;
5664  }
5665  return;
5666  }
5667  /* Choose a random pivot to split the array. */
5668  pivot = (int)randomnation((unsigned int)arraysize);
5669  pivot1 = sortarray[pivot][axis];
5670  pivot2 = sortarray[pivot][1 - axis];
5671  /* Split the array. */
5672  left = -1;
5673  right = arraysize;
5674  while (left < right)
5675  {
5676  /* Search for a vertex whose x-coordinate is too large for the left. */
5677  do
5678  {
5679  left++;
5680  } while ((left <= right) && ((sortarray[left][axis] < pivot1) ||
5681  ((sortarray[left][axis] == pivot1) &&
5682  (sortarray[left][1 - axis] < pivot2))));
5683  /* Search for a vertex whose x-coordinate is too small for the right. */
5684  do
5685  {
5686  right--;
5687  } while ((left <= right) && ((sortarray[right][axis] > pivot1) ||
5688  ((sortarray[right][axis] == pivot1) &&
5689  (sortarray[right][1 - axis] > pivot2))));
5690  if (left < right)
5691  {
5692  /* Swap the left and right vertices. */
5693  temp = sortarray[left];
5694  sortarray[left] = sortarray[right];
5695  sortarray[right] = temp;
5696  }
5697  }
5698  /* Unlike in vertexsort(), at most one of the following */
5699  /* conditionals is true. */
5700  if (left > median)
5701  {
5702  /* Recursively shuffle the left subset. */
5703  vertexmedian(sortarray, left, median, axis);
5704  }
5705  if (right < median - 1)
5706  {
5707  /* Recursively shuffle the right subset. */
5708  vertexmedian(&sortarray[right + 1],
5709  arraysize - right - 1,
5710  median - right - 1,
5711  axis);
5712  }
5713 }
void vertexmedian(vertex *sortarray, int arraysize, int median, int axis)
unsigned long randomnation(unsigned int choices)
void Nektar::NekMeshUtils::DelaunayTriangle::vertexsort ( vertex sortarray,
unsigned int  arraysize 
)
private

Definition at line 5572 of file Triangle/Triangle.cpp.

References randomnation().

Referenced by divconqdelaunay().

5573 {
5574  int left, right;
5575  int pivot;
5576  double pivotx, pivoty;
5577  vertex temp;
5578 
5579  if (arraysize == 2)
5580  {
5581  /* Recursive base case. */
5582  if ((sortarray[0][0] > sortarray[1][0]) ||
5583  ((sortarray[0][0] == sortarray[1][0]) &&
5584  (sortarray[0][1] > sortarray[1][1])))
5585  {
5586  temp = sortarray[1];
5587  sortarray[1] = sortarray[0];
5588  sortarray[0] = temp;
5589  }
5590  return;
5591  }
5592  /* Choose a random pivot to split the array. */
5593  pivot = (int)randomnation((unsigned int)arraysize);
5594  pivotx = sortarray[pivot][0];
5595  pivoty = sortarray[pivot][1];
5596  /* Split the array. */
5597  left = -1;
5598  right = arraysize;
5599  while (left < right)
5600  {
5601  /* Search for a vertex whose x-coordinate is too large for the left. */
5602  do
5603  {
5604  left++;
5605  } while ((left <= right) && ((sortarray[left][0] < pivotx) ||
5606  ((sortarray[left][0] == pivotx) &&
5607  (sortarray[left][1] < pivoty))));
5608  /* Search for a vertex whose x-coordinate is too small for the right. */
5609  do
5610  {
5611  right--;
5612  } while ((left <= right) && ((sortarray[right][0] > pivotx) ||
5613  ((sortarray[right][0] == pivotx) &&
5614  (sortarray[right][1] > pivoty))));
5615  if (left < right)
5616  {
5617  /* Swap the left and right vertices. */
5618  temp = sortarray[left];
5619  sortarray[left] = sortarray[right];
5620  sortarray[right] = temp;
5621  }
5622  }
5623  if (left > 1)
5624  {
5625  /* Recursively sort the left subset. */
5626  vertexsort(sortarray, left);
5627  }
5628  if (right < arraysize - 2)
5629  {
5630  /* Recursively sort the right subset. */
5631  vertexsort(&sortarray[right + 1], arraysize - right - 1);
5632  }
5633 }
void vertexsort(vertex *sortarray, unsigned int arraysize)
unsigned long randomnation(unsigned int choices)
vertex Nektar::NekMeshUtils::DelaunayTriangle::vertextraverse ( struct mesh m)
private

Definition at line 1128 of file Triangle/Triangle.cpp.

References DEADVERTEX, traverse(), vertextype, and Nektar::NekMeshUtils::mesh::vertices.

Referenced by divconqdelaunay(), numbernodes(), and writenodes().

1129 {
1130  vertex newvertex;
1131 
1132  do
1133  {
1134  newvertex = (vertex)traverse(&m->vertices);
1135  if (newvertex == (vertex)NULL)
1136  {
1137  return (vertex)NULL;
1138  }
1139  } while (vertextype(newvertex) == DEADVERTEX); /* Skip dead ones. */
1140  return newvertex;
1141 }
void * traverse(struct memorypool *pool)
#define vertextype(vx)
#define DEADVERTEX
void Nektar::NekMeshUtils::DelaunayTriangle::writeelements ( struct mesh m,
struct behavior b,
int **  trianglelist,
double **  triangleattriblist 
)
private

Definition at line 8634 of file Triangle/Triangle.cpp.

References apex, dest, Nektar::NekMeshUtils::mesh::eextras, elemattribute, Nektar::NekMeshUtils::memorypool::items, org, Nektar::NekMeshUtils::otri::orient, traversalinit(), Nektar::NekMeshUtils::otri::tri, Nektar::NekMeshUtils::mesh::triangles, triangletraverse(), trimalloc(), and vertexmark.

Referenced by triangulate().

8638 {
8639  int *tlist;
8640  double *talist;
8641  int vertexindex;
8642  int attribindex;
8643  struct otri triangleloop;
8644  vertex p1, p2, p3;
8645  long elementnumber;
8646  int i;
8647 
8648  /* Allocate memory for output triangles if necessary. */
8649  if (*trianglelist == (int *)NULL)
8650  {
8651  *trianglelist = (int *)trimalloc(
8652  (int)(m->triangles.items * 3 *
8653  sizeof(int)));
8654  }
8655  /* Allocate memory for output triangle attributes if necessary. */
8656  if ((m->eextras > 0) && (*triangleattriblist == (double *)NULL))
8657  {
8658  *triangleattriblist = (double *)trimalloc(
8659  (int)(m->triangles.items * m->eextras * sizeof(double)));
8660  }
8661  tlist = *trianglelist;
8662  talist = *triangleattriblist;
8663  vertexindex = 0;
8664  attribindex = 0;
8665 
8666  traversalinit(&m->triangles);
8667  triangleloop.tri = triangletraverse(m);
8668  triangleloop.orient = 0;
8669  elementnumber = 0;
8670  while (triangleloop.tri != (triangle *)NULL)
8671  {
8672  org(triangleloop, p1);
8673  dest(triangleloop, p2);
8674  apex(triangleloop, p3);
8675 
8676  tlist[vertexindex++] = vertexmark(p1);
8677  tlist[vertexindex++] = vertexmark(p2);
8678  tlist[vertexindex++] = vertexmark(p3);
8679 
8680 
8681 
8682  for (i = 0; i < m->eextras; i++)
8683  {
8684  talist[attribindex++] = elemattribute(triangleloop, i);
8685  }
8686 
8687  triangleloop.tri = triangletraverse(m);
8688  elementnumber++;
8689  }
8690 }
#define vertexmark(vx)
void traversalinit(struct memorypool *pool)
#define apex(otri, vertexptr)
triangle * triangletraverse(struct mesh *m)
#define elemattribute(otri, attnum)
#define dest(otri, vertexptr)
#define org(otri, vertexptr)
void Nektar::NekMeshUtils::DelaunayTriangle::writenodes ( struct mesh m,
struct behavior b,
double **  pointlist,
double **  pointattriblist,
int **  pointmarkerlist 
)
private

Definition at line 8525 of file Triangle/Triangle.cpp.

References Nektar::NekMeshUtils::memorypool::items, Nektar::NekMeshUtils::behavior::jettison, Nektar::NekMeshUtils::mesh::nextras, setvertexmark, traversalinit(), trimalloc(), Nektar::NekMeshUtils::mesh::undeads, UNDEADVERTEX, vertexmark, vertextraverse(), vertextype, and Nektar::NekMeshUtils::mesh::vertices.

Referenced by triangulate().

8530 {
8531  double *plist;
8532  double *palist;
8533  int *pmlist;
8534  int coordindex;
8535  int attribindex;
8536  vertex vertexloop;
8537  long outvertices;
8538  int vertexnumber;
8539  int i;
8540 
8541  if (b->jettison)
8542  {
8543  outvertices = m->vertices.items - m->undeads;
8544  }
8545  else
8546  {
8547  outvertices = m->vertices.items;
8548  }
8549 
8550  /* Allocate memory for output vertices if necessary. */
8551  if (*pointlist == (double *)NULL)
8552  {
8553  *pointlist =
8554  (double *)trimalloc((int)(outvertices * 2 * sizeof(double)));
8555  }
8556  /* Allocate memory for output vertex attributes if necessary. */
8557  if ((m->nextras > 0) && (*pointattriblist == (double *)NULL))
8558  {
8559  *pointattriblist = (double *)trimalloc(
8560  (int)(outvertices * m->nextras * sizeof(double)));
8561  }
8562  /* Allocate memory for output vertex markers if necessary. */
8563  if (*pointmarkerlist == (int *)NULL)
8564  {
8565  *pointmarkerlist = (int *)trimalloc((int)(outvertices * sizeof(int)));
8566  }
8567  plist = *pointlist;
8568  palist = *pointattriblist;
8569  pmlist = *pointmarkerlist;
8570  coordindex = 0;
8571  attribindex = 0;
8572 
8573  traversalinit(&m->vertices);
8574  vertexnumber = 0;
8575  vertexloop = vertextraverse(m);
8576  while (vertexloop != (vertex)NULL)
8577  {
8578  if (!b->jettison || (vertextype(vertexloop) != UNDEADVERTEX))
8579  {
8580  /* X and y coordinates. */
8581  plist[coordindex++] = vertexloop[0];
8582  plist[coordindex++] = vertexloop[1];
8583  /* Vertex attributes. */
8584  for (i = 0; i < m->nextras; i++)
8585  {
8586  palist[attribindex++] = vertexloop[2 + i];
8587  }
8588 
8589  /* Copy the boundary marker. */
8590  pmlist[vertexnumber] = vertexmark(vertexloop);
8591 
8592  setvertexmark(vertexloop, vertexnumber);
8593  vertexnumber++;
8594  }
8595  vertexloop = vertextraverse(m);
8596  }
8597 }
#define vertexmark(vx)
#define UNDEADVERTEX
void traversalinit(struct memorypool *pool)
#define vertextype(vx)
#define setvertexmark(vx, value)
void Nektar::NekMeshUtils::DelaunayTriangle::writepoly ( struct mesh m,
struct behavior b,
int **  segmentlist,
int **  segmentmarkerlist 
)
private

Definition at line 8698 of file Triangle/Triangle.cpp.

References Nektar::NekMeshUtils::memorypool::items, mark, sdest, sorg, Nektar::NekMeshUtils::osub::ss, Nektar::NekMeshUtils::osub::ssorient, Nektar::NekMeshUtils::mesh::subsegs, subsegtraverse(), traversalinit(), trimalloc(), and vertexmark.

Referenced by triangulate().

8702 {
8703  int *slist;
8704  int *smlist;
8705  int index;
8706  struct osub subsegloop;
8707  vertex endpoint1, endpoint2;
8708  long subsegnumber;
8709 
8710  /* Allocate memory for output segments if necessary. */
8711  if (*segmentlist == (int *)NULL)
8712  {
8713  *segmentlist =
8714  (int *)trimalloc((int)(m->subsegs.items * 2 * sizeof(int)));
8715  }
8716  /* Allocate memory for output segment markers if necessary. */
8717  if (*segmentmarkerlist == (int *)NULL)
8718  {
8719  *segmentmarkerlist =
8720  (int *)trimalloc((int)(m->subsegs.items * sizeof(int)));
8721  }
8722  slist = *segmentlist;
8723  smlist = *segmentmarkerlist;
8724  index = 0;
8725 
8726  traversalinit(&m->subsegs);
8727  subsegloop.ss = subsegtraverse(m);
8728  subsegloop.ssorient = 0;
8729  subsegnumber = 0;
8730  while (subsegloop.ss != (subseg *)NULL)
8731  {
8732  sorg(subsegloop, endpoint1);
8733  sdest(subsegloop, endpoint2);
8734  /* Copy indices of the segment's two endpoints. */
8735  slist[index++] = vertexmark(endpoint1);
8736  slist[index++] = vertexmark(endpoint2);
8737 
8738  /* Copy the boundary marker. */
8739  smlist[subsegnumber] = mark(subsegloop);
8740 
8741  subsegloop.ss = subsegtraverse(m);
8742  subsegnumber++;
8743  }
8744 }
#define vertexmark(vx)
void traversalinit(struct memorypool *pool)
#define mark(osub)
#define sdest(osub, vertexptr)
#define sorg(osub, vertexptr)

Friends And Related Function Documentation

friend class MemoryManager< DelaunayTriangle >
friend

Definition at line 954 of file Triangle/Triangle.h.

Member Data Documentation

double Nektar::NekMeshUtils::DelaunayTriangle::ccwerrboundA
private

Definition at line 1057 of file Triangle/Triangle.h.

Referenced by counterclockwise(), and exactinit().

double Nektar::NekMeshUtils::DelaunayTriangle::ccwerrboundB
private

Definition at line 1057 of file Triangle/Triangle.h.

Referenced by counterclockwiseadapt(), and exactinit().

double Nektar::NekMeshUtils::DelaunayTriangle::ccwerrboundC
private

Definition at line 1057 of file Triangle/Triangle.h.

Referenced by counterclockwiseadapt(), and exactinit().

double Nektar::NekMeshUtils::DelaunayTriangle::epsilon
private

Definition at line 1055 of file Triangle/Triangle.h.

Referenced by exactinit().

double Nektar::NekMeshUtils::DelaunayTriangle::iccerrboundA
private

Definition at line 1058 of file Triangle/Triangle.h.

Referenced by exactinit(), and incircle().

double Nektar::NekMeshUtils::DelaunayTriangle::iccerrboundB
private

Definition at line 1058 of file Triangle/Triangle.h.

Referenced by exactinit(), and incircleadaptTRI().

double Nektar::NekMeshUtils::DelaunayTriangle::iccerrboundC
private

Definition at line 1058 of file Triangle/Triangle.h.

Referenced by exactinit(), and incircleadaptTRI().

int Nektar::NekMeshUtils::DelaunayTriangle::minus1mod3[3]
private

Definition at line 1068 of file Triangle/Triangle.h.

Referenced by triangulate().

double Nektar::NekMeshUtils::DelaunayTriangle::o3derrboundA
private

Definition at line 1059 of file Triangle/Triangle.h.

Referenced by exactinit(), and orient3d().

double Nektar::NekMeshUtils::DelaunayTriangle::o3derrboundB
private

Definition at line 1059 of file Triangle/Triangle.h.

Referenced by exactinit(), and orient3dadapt().

double Nektar::NekMeshUtils::DelaunayTriangle::o3derrboundC
private

Definition at line 1059 of file Triangle/Triangle.h.

Referenced by exactinit(), and orient3dadapt().

struct triangulateio in Nektar::NekMeshUtils::DelaunayTriangle::out
int Nektar::NekMeshUtils::DelaunayTriangle::plus1mod3[3]
private

Definition at line 1067 of file Triangle/Triangle.h.

Referenced by triangulate().

unsigned long Nektar::NekMeshUtils::DelaunayTriangle::randomseed
private

Definition at line 1063 of file Triangle/Triangle.h.

Referenced by randomnation(), and triangleinit().

double Nektar::NekMeshUtils::DelaunayTriangle::resulterrbound
private
double Nektar::NekMeshUtils::DelaunayTriangle::splitter
private

Definition at line 1054 of file Triangle/Triangle.h.

Referenced by exactinit().