2025-02-11 13:00:54 +01:00
2022-03-18 10:29:21 +01:00
2025-02-11 13:00:54 +01:00
2025-02-11 13:00:54 +01:00
2022-09-09 21:19:58 +02:00

meshrefine

Constrained Delaunay mesh refinement.

[[TOC]]

Installing the code

You can find (a) compiled version(s) in stokes:/work/bast/meshrefine/builds but just in case you want to build yourself, this is how:

# clone the code
$ git clone git@gitlab.com:oceanbox/meshrefine.git
$ cd meshrefine

# this is only needed if you don't have Rust installed
$ nix-env -iA nixos.cargo nixos.rustc

# finally, we compile the code
$ cargo build --release

This compiles a binary called meshrefine into $PWD/target/release/.

How to run it

The binary has the following options:

USAGE:
    meshrefine [OPTIONS]

OPTIONS:
    -a, --min-angle <MIN_ANGLE>
    -b, --boundary <BOUNDARY>
    -d, --delta-t <DELTA_T>                              [default: 0.1]
    -f, --fscale <FSCALE>                                [default: 1]
    -h, --help                                           Print help information
    -i, --islands <ISLANDS>
        --ld <LD>                                        [default: 10000]
        --lr <LR>                                        [default: 4000]
    -m, --num-repair-steps <NUM_REPAIR_STEPS>
    -n, --num-relaxation-steps <NUM_RELAXATION_STEPS>    [default: 0]
    -o, --output-file <OUTPUT_FILE>
    -r, --resolution-field <RESOLUTION_FIELD>
        --rmax <RMAX>                                    [default: 800]
        --rw <RW>                                        [default: 400]
    -s, --scaling <SCALING>                              [default: 10]
    -v, --vertices <VERTICES>
    -V, --version                                        Print version information

See also the examples folder.

The format of the boundary and islands files is unchanged w.r.t. the other meshing codes. Also the distance function signature is unchanged.

You may want to adjust the minimum angle (--min-angle). The smaller, the sooner the grid is done. The larger, the better quality grid, but at some point you will notice that code does not finish and then the minimum angle was too large. It works well until 31 or 32 degrees.

While the mesh is refining, the code produces the following output:

number of triangles: bad=202849, good=151393
number of triangles: bad=202855, good=151395
number of triangles: bad=202854, good=151395
number of triangles: bad=202853, good=151395
number of triangles: bad=202852, good=151395
number of triangles: bad=202851, good=151395
number of triangles: bad=202850, good=151395
number of triangles: bad=202849, good=151395
number of triangles: bad=202848, good=151395
...

The number of bad triangles should go down. If it goes up, you can abort it with CTRL-C and then you need to adjust the minimum angle and/or the distance function.

Algorithm

Basically a reimplementation of https://www.cs.cmu.edu/~quake/triangle.html with a customized triangle acceptance function based on the resolution.

Advantages of the algorithm:

  • Preserves the boundary perfectly
  • Guarantees a minimum angle
  • Takes seconds to minutes on a normal computer (code is not parallelized yet)

Disadvantages:

  • Currently does not look at area differences
  • May produce too many triangles (no cutoff for too small triangles, we can add that if we want that)

Steps:

  1. The code starts by running a constrained Delaunay algorithm to preserve boundary edges.
  2. The code then identifies all bad triangles. Bad triangles are triangles with too small minimum angle or where longest side is longer than the resolution at the triangle centroid.
  3. It then starts repairing triangles starting from the worst (this is defined as the triangle with the largest circumradius, we can redefine that).
  4. It repairs by creating smaller triangles which are again checked for their quality and if they are bad, they are placed on a priority queue for repair.
  5. Code continues until no bad triangles are left for repair.

Lower bound on triangle size:

  • The code accepts triangles if their longest side is 0.2 times shortest edge of input polygons. This is to not get too many too tiny triangles when trying to make sure that all of them are above certain minimum angle.

Mesh improvement using mesh relaxation

After the mesh refinement steps (above), if --num-relaxation-steps is set and larger than 0, the code will run a series of iterations to relax vertex coordinates according to forces acting on vertices. For these steps the code uses --delta-t and --fscale and this algorithm corresponds to the Distmesh algorithm with the modification that all boundary vertices are fixed.

Visualize the result

This code produces a grid file, for instance grid.txt which I look at in my browser using https://gitlab.com/oceanbox/makai.

Resolution field

If a resolution field file is provided, the code will interpolate the data using bilinear interpolation using the library bilinear and resolution in a point is then defined as the minimum of the resolution coming from the distance function and the resolution approximated using the interpolation.

The file format for the resolution field file:

ox oy       # origin
sx sy       # step along x and y
xi yi z     # index along x (counting starts with 0), index along y (counting starts with 0), and value
xi yi z
...         # as many of these as we like
  • Only non-negative indices are allowed.
  • We don't have to give all values in places where the matrix has "holes". This can be relevant "on land" where we might not have meaningful data.
  • The rows with indices and values can come in any order.
  • It does not matter how many spaces are between numbers.

Example for a 3x2 grid:

0.0 0.0
1.0 1.0
0 0  2.01
0 1  2.13
1 0  2.27
1 1  2.31
2 0  3.40
2 1  4.52

When interpolating, the code first finds the right "tile", then checks that we have data available for all 4 corners. If yes, then the value is interpolated and used. If one or more of the 4 corner values are missing, then this tile is not considered and does not contribute to the resolution.

How to triangulate a set of vertices

Maybe you have polygons for boundary and islands and a set of vertices "in water" and want to Delaunay-triangulate them without any mesh refinement and without any mesh relaxation.

You can do it like this:

#!/usr/bin/env bash

set -euf -o pipefail

binary=$PWD/../../target/release/meshrefine

time $binary --boundary=boundary.txt \
             --islands=islands.txt \
             --vertices=vertices.txt \
             --num-repair-steps=0 \
             --output-file=grid.txt

Here we have set the number of repair steps to 0 and we provide a --vertices file which contains a list of vertices (x and y coordinates on each line).

You can find an example for this in folder examples/delaunay-only.

Description
Constrained Delaunay mesh refinement.
Readme 2.1 MiB
Languages
Rust 100%