📄 triangle.c
字号:
/* exterior boundary or hole boundary. *//* *//* A subsegment consists of a list of four vertices--the vertices of the *//* subsegment, and the vertices of the segment it is a part of--a list of *//* two adjoining subsegments, and a list of two adjoining triangles. One *//* of the two adjoining triangles may not be present (though there should *//* always be one), and neighboring subsegments might not be present. *//* Subsegments also store a user-defined integer "boundary marker". *//* Typically, this integer is used to indicate what boundary conditions are *//* to be applied at that location in a finite element simulation. *//* *//* Like triangles, subsegments maintain information about the relative *//* orientation of neighboring objects. *//* *//* Vertices are relatively simple. A vertex is a list of floating-point *//* numbers, starting with the x, and y coordinates, followed by an *//* arbitrary number of optional user-defined floating-point attributes, *//* followed by an integer boundary marker. During the segment insertion *//* phase, there is also a pointer from each vertex to a triangle that may *//* contain it. Each pointer is not always correct, but when one is, it *//* speeds up segment insertion. These pointers are assigned values once *//* at the beginning of the segment insertion phase, and are not used or *//* updated except during this phase. Edge flipping during segment *//* insertion will render some of them incorrect. Hence, don't rely upon *//* them for anything. *//* *//* Other than the exception mentioned above, vertices have no information *//* about what triangles, subfacets, or subsegments they are linked to. *//* *//*****************************************************************************//*****************************************************************************//* *//* Handles *//* *//* The oriented triangle (`otri') and oriented subsegment (`osub') data *//* structures defined below do not themselves store any part of the mesh. *//* The mesh itself is made of `triangle's, `subseg's, and `vertex's. *//* *//* Oriented triangles and oriented subsegments will usually be referred to *//* as "handles." A handle is essentially a pointer into the mesh; it *//* allows you to "hold" one particular part of the mesh. Handles are used *//* to specify the regions in which one is traversing and modifying the mesh.*//* A single `triangle' may be held by many handles, or none at all. (The *//* latter case is not a memory leak, because the triangle is still *//* connected to other triangles in the mesh.) *//* *//* An `otri' is a handle that holds a triangle. It holds a specific edge *//* of the triangle. An `osub' is a handle that holds a subsegment. It *//* holds either the left or right side of the subsegment. *//* *//* Navigation about the mesh is accomplished through a set of mesh *//* manipulation primitives, further below. Many of these primitives take *//* a handle and produce a new handle that holds the mesh near the first *//* handle. Other primitives take two handles and glue the corresponding *//* parts of the mesh together. The orientation of the handles is *//* important. For instance, when two triangles are glued together by the *//* bond() primitive, they are glued at the edges on which the handles lie. *//* *//* Because vertices have no information about which triangles they are *//* attached to, I commonly represent a vertex by use of a handle whose *//* origin is the vertex. A single handle can simultaneously represent a *//* triangle, an edge, and a vertex. *//* *//*****************************************************************************//* The triangle data structure. Each triangle contains three pointers to *//* adjoining triangles, plus three pointers to vertices, plus three *//* pointers to subsegments (declared below; these pointers are usually *//* `dummysub'). It may or may not also contain user-defined attributes *//* and/or a floating-point "area constraint." It may also contain extra *//* pointers for nodes, when the user asks for high-order elements. *//* Because the size and structure of a `triangle' is not decided until *//* runtime, I haven't simply declared the type `triangle' as a struct. */typedef REAL **triangle; /* Really: typedef triangle *triangle *//* An oriented triangle: includes a pointer to a triangle and orientation. *//* The orientation denotes an edge of the triangle. Hence, there are *//* three possible orientations. By convention, each edge always points *//* counterclockwise about the corresponding triangle. */struct otri { triangle *tri; int orient; /* Ranges from 0 to 2. */};/* The subsegment data structure. Each subsegment contains two pointers to *//* adjoining subsegments, plus four pointers to vertices, plus two *//* pointers to adjoining triangles, plus one boundary marker, plus one *//* segment number. */typedef REAL **subseg; /* Really: typedef subseg *subseg *//* An oriented subsegment: includes a pointer to a subsegment and an *//* orientation. The orientation denotes a side of the edge. Hence, there *//* are two possible orientations. By convention, the edge is always *//* directed so that the "side" denoted is the right side of the edge. */struct osub { subseg *ss; int ssorient; /* Ranges from 0 to 1. */};/* The vertex data structure. Each vertex is actually an array of REALs. *//* The number of REALs is unknown until runtime. An integer boundary *//* marker, and sometimes a pointer to a triangle, is appended after the *//* REALs. */typedef REAL *vertex;/* A queue used to store encroached subsegments. Each subsegment's vertices *//* are stored so that we can check whether a subsegment is still the same. */struct badsubseg { subseg encsubseg; /* An encroached subsegment. */ vertex subsegorg, subsegdest; /* Its two vertices. */};/* A queue used to store bad triangles. The key is the square of the cosine *//* of the smallest angle of the triangle. Each triangle's vertices are *//* stored so that one can check whether a triangle is still the same. */struct badtriang { triangle poortri; /* A skinny or too-large triangle. */ REAL key; /* cos^2 of smallest (apical) angle. */ vertex triangorg, triangdest, triangapex; /* Its three vertices. */ struct badtriang *nexttriang; /* Pointer to next bad triangle. */};/* A stack of triangles flipped during the most recent vertex insertion. *//* The stack is used to undo the vertex insertion if the vertex encroaches *//* upon a subsegment. */struct flipstacker { triangle flippedtri; /* A recently flipped triangle. */ struct flipstacker *prevflip; /* Previous flip in the stack. */};/* A node in a heap used to store events for the sweepline Delaunay *//* algorithm. Nodes do not point directly to their parents or children in *//* the heap. Instead, each node knows its position in the heap, and can *//* look up its parent and children in a separate array. The `eventptr' *//* points either to a `vertex' or to a triangle (in encoded format, so *//* that an orientation is included). In the latter case, the origin of *//* the oriented triangle is the apex of a "circle event" of the sweepline *//* algorithm. To distinguish site events from circle events, all circle *//* events are given an invalid (smaller than `xmin') x-coordinate `xkey'. */struct event { REAL xkey, ykey; /* Coordinates of the event. */ VOID *eventptr; /* Can be a vertex or the location of a circle event. */ int heapposition; /* Marks this event's position in the heap. */};/* A node in the splay tree. Each node holds an oriented ghost triangle *//* that represents a boundary edge of the growing triangulation. When a *//* circle event covers two boundary edges with a triangle, so that they *//* are no longer boundary edges, those edges are not immediately deleted *//* from the tree; rather, they are lazily deleted when they are next *//* encountered. (Since only a random sample of boundary edges are kept *//* in the tree, lazy deletion is faster.) `keydest' is used to verify *//* that a triangle is still the same as when it entered the splay tree; if *//* it has been rotated (due to a circle event), it no longer represents a *//* boundary edge and should be deleted. */struct splaynode { struct otri keyedge; /* Lprev of an edge on the front. */ vertex keydest; /* Used to verify that splay node is still live. */ struct splaynode *lchild, *rchild; /* Children in splay tree. */};/* A type used to allocate memory. firstblock is the first block of items. *//* nowblock is the block from which items are currently being allocated. *//* nextitem points to the next slab of free memory for an item. *//* deaditemstack is the head of a linked list (stack) of deallocated items *//* that can be recycled. unallocateditems is the number of items that *//* remain to be allocated from nowblock. *//* *//* Traversal is the process of walking through the entire list of items, and *//* is separate from allocation. Note that a traversal will visit items on *//* the "deaditemstack" stack as well as live items. pathblock points to *//* the block currently being traversed. pathitem points to the next item *//* to be traversed. pathitemsleft is the number of items that remain to *//* be traversed in pathblock. *//* *//* alignbytes determines how new records should be aligned in memory. *//* itembytes is the length of a record in bytes (after rounding up). *//* itemsperblock is the number of items allocated at once in a single *//* block. itemsfirstblock is the number of items in the first block, *//* which can vary from the others. items is the number of currently *//* allocated items. maxitems is the maximum number of items that have *//* been allocated at once; it is the current number of items plus the *//* number of records kept on deaditemstack. */struct memorypool { VOID **firstblock, **nowblock; VOID *nextitem; VOID *deaditemstack; VOID **pathblock; VOID *pathitem; int alignbytes; int itembytes; int itemsperblock; int itemsfirstblock; long items, maxitems; int unallocateditems; int pathitemsleft;};/* Global constants. */REAL splitter; /* Used to split REAL factors for exact multiplication. */REAL epsilon; /* Floating-point machine epsilon. */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -