|
![]() 2) mesh simple.poly -v40
|
"Anisotropic" means that it is possible to specify the desired shape and size of triangles in different portions of the mesh.
![]() mesh simple.poly -hstretch -v402) mesh simple.poly -left -left -top -top -v40
|
"Refinement" means that the mesh is produced by inserting new vertices repeatedly.
![]() mesh simple.poly -v162) mesh simple.poly -v173) mesh simple.poly -v18
|
mesh, which is freely available. mesh was designed for unix-compatible platforms but should compile on any system supporting ANSI C. All the meshes that appear in this document were computed using this program (the command line is shown below every picture).
Program:
| mesh.c | the mesh generator | |
| transform.c | anisotropic transformation functions | |
| mesh.h | program header | |
| mesh.build | the compile script for unix systems |
Some input files:
| simple.poly | |
| square.poly |
Relevant links
| More input files can be obtained from this directory. | |
| Description of the file formats: .poly .node .ele | |
| The Show Me visualization program to view the input and output files. |
% mesh
usage: mesh -option1 -option2 [...] file.node file.poly [...]
.node files will be triangulated (output: .ele)
.poly files will be meshed (output: .node and .ele)
meshing options:
-g grading mesh (size of triangles irrelevent)
-a# angle lower bound in degrees, only with -g option (default 30.0)
-v# vertex upper bound (default 1000, ~184 K RAM)
-c convex hull edges become segments
anisotropy options: (can be combined!)
affecting shape:
-hstretch, -vstretch, -dstretch, -sink, -swirl
affecting size:
-hline, -vline, -dline, -center, -perimeter
-left, -right, -top, -bottom
user specified:
-custom (the function 'T_custom' in 'transform.c')
When used on .node files, mesh becomes a simple anisotropic point-set triangulator. Furthermore, when no anisotropy option is used, mesh naturally returns the Delaunay triangulation of the point-set.
![]() mesh spiral.node2) mesh spiral.node -hstretch3) mesh spiral.node -vstretch
|
-g option on, mesh will only try to obtain nicely shaped triangles (and not try to obtain triangles of the same size). This is useful when an application requires small triangles only close to the boundary.
![]() mesh superior.poly -g2) mesh superior.poly
|
mesh square.poly [option] -v200
![]() |
![]() -hstretch |
![]() -vstretch |
![]() -dstretch |
![]() -sink |
![]() -swirl |
![]() -hline |
![]() -vline |
![]() -dline |
![]() -center |
![]() -perimeter |
![]() -left |
![]() -right |
![]() -top |
![]() -bottom |
![]() -custom |
-sink -swirl were also added. This is a small hack used to break the symmetry of the square. (The two options -sink and -swirl cancel each other but introduce numerical instability.) Otherwise we get artificially regular patterns like this one:
![]() |
transform.c.)
![]() mesh square.poly -v200 -center -center -center2) mesh square.poly -v200 -sink -sink3) mesh square.poly -v200 -hline -hline -vline -vline -perimeter -perimeter -perimeter
|
mesh acts like Ruppert's Delaunay refinement algorithm for triangular mesh generation [1], as described in Section 3.4 of the course lecture notes.When anisotropy is used, each point (x,y) in the plane is assigned a linear transformation T:R2->R2 that describes how the plane should stretch in the neighborhood of (x,y).
The minimum distorted angle of a triangle is defined to be the smallest angle of the triangle when distorted by the linear transformation assigned to its centroid.
![]() |
The initial triangulation is computed by inserting vertices incrementally into a large bounding triangle. The convex hull edges are guaranteed to appear because I force any flip that would reduce the number of triangles that touch the vertices of the bounding triangle. (I'm unsure whether doing this completely solves all the problems inherent to the bounding triangle approach.)
Then, the program locks every segment, determines what is the interior region, and starts attacking internal triangles of low quality by refinement (i.e. by inserting new vertices).
When grading is used, the quality of a triangle is defined to be its minimum distorted angle. When grading is not used, large triangles are penalized by dividing the minimum angle by the (distorted) perimeter of the triangle, squared. The power at which the perimeter is raised controls how much importance is given to the size of the triangle versus its shape. The current value was arbitrarily chosen to give pleasing results.
In Ruppert's algorithm, low quality triangles are removed by inserting a vertex at the circumcenter of the triangle. In the isotropic case, the triangle is Delaunay, therefore its circumcircle is empty and the circumcenter is a good place to insert a vertex. Furthermore, a Lemma guarantees that the circumcenter falls in the inside region (using the fact that the input is segment-bounded and that no segment is encroached). However in the anisotropic case there are some problems: the circumcircle is not necessarily empty. The circumcenter may fall arbitrarily close to another vertex or edge, or may even fall in the outside region. The program solves these problems by checking if the nearest neighbor of the circumcenter is a vertex of the triangle in question (as it would be in the isotropic case). If this does not hold, then we walk toward the centroid of the triangle and try again. After some number of consecutive failures, the program finally uses the centroid.
I also implemented the modifications for handling small angles, otherwise the program cannot mesh any interesting geometries.
| [1] | Jim Ruppert. A Delaunay Refinement Algorithm for Quality 2-Dimensional Mesh Generation. Journal or Algorithms 18(3):548-585, May 1995. |
mesh is probably best at dealing with complicated geometries. I invite you to look at the following "meshing art gallery" and see if you like the results obtained for the type of problems that interests you.
![]() mesh A.poly -bottom -bottom -v400 |
![]() mesh key.poly -g -a20 |
![]() mesh trix.poly -swirl -v300 |
![]() mesh square.poly -custom -v1000 |
![]() mesh simple.poly -dline -dline -v1000 |
![]() mesh point.poly -sink -perimeter -v400 |
mesh generates meshes in time that is roughly quadratic on the size of the output. This is because the code is somewhat sloppy on running time. I may improve the time complexity to a more respectable O(n log n) in the future.
command time mesh simple.poly -v125 0.016 s mesh simple.poly -v250 0.041 s mesh simple.poly -v500 0.113 s mesh simple.poly -v1000 0.337 s mesh simple.poly -v2000 1.071 s mesh simple.poly -v4000 4.081 s mesh simple.poly -v8000 19.713 s mesh simple.poly -v16000 91.383 s
Last updated: December 4, 1999