Skip to content

Latest commit

 

History

History
374 lines (308 loc) · 11 KB

README.md

File metadata and controls

374 lines (308 loc) · 11 KB

Triangle and tetrahedron mesh generators

codecov

This project presents a Rust code to generate triangle and tetrahedron meshes by calling Triangle and Tetgen (1.4).

A critical aspect of this crate is that all the data structures accessed by the C-code are allocated on the "C-side" by (carefully) using "malloc/new." 😅 We then make use of Valgrind and tests to make sure that all is (hopefully) well.

The code should work fine in multithreaded applications (not exhaustively verified, though!). See, for example, the comprehensive tests in mem_check_triangle_build.rs and mem_check_tetgen_build.rs

The resulting Rust interface to Triangle and Tetgen is a lightweight, low-level set of functions. However, other projects could use this interface to make higher-level functions.

For example, this crate is used by Gemlab: Geometry, meshes, and numerical integration for finite element analyses.

Documentation

Tritet documentation on docs.rs

Installation

Install some libraries:

sudo apt install build-essential

Crates.io

👆 Check the crate version and update your Cargo.toml accordingly:

[dependencies]
tritet = "*"

Examples

Note: set SAVE_FIGURE to true to generate the figures.

2D Delaunay triangulation

use plotpy::Plot;
use tritet::{StrError, Triangle};

const SAVE_FIGURE: bool = false;

fn main() -> Result<(), StrError> {
    // allocate data for 10 points
    let mut triangle = Triangle::new(10, None, None, None)?;

    // set points
    triangle
        .set_point(0, 0.478554, 0.00869692)?
        .set_point(1, 0.13928, 0.180603)?
        .set_point(2, 0.578587, 0.760349)?
        .set_point(3, 0.903726, 0.975904)?
        .set_point(4, 0.0980015, 0.981755)?
        .set_point(5, 0.133721, 0.348832)?
        .set_point(6, 0.648071, 0.369534)?
        .set_point(7, 0.230951, 0.558482)?
        .set_point(8, 0.0307942, 0.459123)?
        .set_point(9, 0.540745, 0.331184)?;

    // generate Delaunay triangulation
    triangle.generate_delaunay(false)?;

    // draw triangles
    if SAVE_FIGURE {
        let mut plot = Plot::new();
        triangle.draw_triangles(&mut plot, true, true, true, true, None, None, None);
        plot.set_equal_axes(true)
            .set_figure_size_points(600.0, 600.0)
            .save("/tmp/tritet/doc_triangle_delaunay_1.svg")?;
    }
    Ok(())
}

doc_triangle_delaunay_1.svg

2D Voronoi tessellation

use plotpy::Plot;
use tritet::{StrError, Triangle};

const SAVE_FIGURE: bool = false;

fn main() -> Result<(), StrError> {
    // allocate data for 10 points
    let mut triangle = Triangle::new(10, None, None, None)?;

    // set points
    triangle
        .set_point(0, 0.478554, 0.00869692)?
        .set_point(1, 0.13928, 0.180603)?
        .set_point(2, 0.578587, 0.760349)?
        .set_point(3, 0.903726, 0.975904)?
        .set_point(4, 0.0980015, 0.981755)?
        .set_point(5, 0.133721, 0.348832)?
        .set_point(6, 0.648071, 0.369534)?
        .set_point(7, 0.230951, 0.558482)?
        .set_point(8, 0.0307942, 0.459123)?
        .set_point(9, 0.540745, 0.331184)?;

    // generate Voronoi tessellation
    triangle.generate_voronoi(false)?;

    // draw Voronoi diagram
    if SAVE_FIGURE {
        let mut plot = Plot::new();
        triangle.draw_voronoi(&mut plot);
        plot.set_equal_axes(true)
            .set_figure_size_points(600.0, 600.0)
            .save("/tmp/tritet/doc_triangle_voronoi_1.svg")?;
    }
    Ok(())
}

doc_triangle_voronoi_1.svg

2D mesh generation

use plotpy::Plot;
use tritet::{StrError, Triangle};

const SAVE_FIGURE: bool = false;

fn main() -> Result<(), StrError> {
    // allocate data for 12 points, 10 segments, 2 regions, and 1 hole
    let mut triangle = Triangle::new(12, Some(10), Some(2), Some(1))?;

    // set points
    triangle
        .set_point(0, 0.0, 0.0)?
        .set_point(1, 1.0, 0.0)?
        .set_point(2, 1.0, 1.0)?
        .set_point(3, 0.0, 1.0)?
        .set_point(4, 0.2, 0.2)?
        .set_point(5, 0.8, 0.2)?
        .set_point(6, 0.8, 0.8)?
        .set_point(7, 0.2, 0.8)?
        .set_point(8, 0.0, 0.5)?
        .set_point(9, 0.2, 0.5)?
        .set_point(10, 0.8, 0.5)?
        .set_point(11, 1.0, 0.5)?;

    // set segments
    triangle
        .set_segment(0, 0, 1)?
        .set_segment(1, 1, 2)?
        .set_segment(2, 2, 3)?
        .set_segment(3, 3, 0)?
        .set_segment(4, 4, 5)?
        .set_segment(5, 5, 6)?
        .set_segment(6, 6, 7)?
        .set_segment(7, 7, 4)?
        .set_segment(8, 8, 9)?
        .set_segment(9, 10, 11)?;

    // set regions
    triangle
        .set_region(0, 0.1, 0.1, 1, None)?
        .set_region(1, 0.1, 0.9, 2, None)?;

    // set holes
    triangle.set_hole(0, 0.5, 0.5)?;

    // generate o2 mesh without constraints
    triangle.generate_mesh(false, true, None, None)?;
    assert_eq!(triangle.ntriangle(), 14);

    // draw mesh
    if SAVE_FIGURE {
        let mut plot = Plot::new();
        triangle.draw_triangles(&mut plot, true, true, true, true, None, None, None);
        plot.set_equal_axes(true)
            .set_figure_size_points(600.0, 600.0)
            .save("/tmp/tritet/doc_triangle_mesh_1.svg")?;
    }
    Ok(())
}

doc_triangle_mesh_1.svg

3D Delaunay triangulation

use plotpy::Plot;
use tritet::{StrError, Tetgen};

const SAVE_FIGURE: bool = false;

fn main() -> Result<(), StrError> {
    // allocate data for 8 points
    let mut tetgen = Tetgen::new(8, None, None, None)?;

    // set points
    tetgen
        .set_point(0, 0.0, 0.0, 0.0)?
        .set_point(1, 1.0, 0.0, 0.0)?
        .set_point(2, 1.0, 1.0, 0.0)?
        .set_point(3, 0.0, 1.0, 0.0)?
        .set_point(4, 0.0, 0.0, 1.0)?
        .set_point(5, 1.0, 0.0, 1.0)?
        .set_point(6, 1.0, 1.0, 1.0)?
        .set_point(7, 0.0, 1.0, 1.0)?;

    // generate Delaunay triangulation
    tetgen.generate_delaunay(false)?;

    // draw edges of tetrahedra
    if SAVE_FIGURE {
        let mut plot = Plot::new();
        tetgen.draw_wireframe(&mut plot, true, true, true, true, None, None, None);
        plot.set_equal_axes(true)
            .set_figure_size_points(600.0, 600.0)
            .save("/tmp/tritet/example_tetgen_delaunay_1.svg")?;
    }
    Ok(())
}

example_tetgen_delaunay_1.svg

3D mesh generation

Note: set SAVE_VTU_FILE to true to generate Paraview file.

use plotpy::Plot;
use tritet::{write_tet_vtu, StrError, Tetgen};

const SAVE_VTU_FILE: bool = false;
const SAVE_FIGURE: bool = false;

fn main() -> Result<(), StrError> {
    // allocate data for 16 points and 12 facets
    // (one cube/hole inside another cube)
    let mut tetgen = Tetgen::new(
        16,
        Some(vec![
            4, 4, 4, 4, 4, 4, // inner cube
            4, 4, 4, 4, 4, 4, // outer cube
        ]),
        Some(1),
        Some(1),
    )?;

    // inner cube
    tetgen
        .set_point(0, 0.0, 0.0, 0.0)?
        .set_point(1, 1.0, 0.0, 0.0)?
        .set_point(2, 1.0, 1.0, 0.0)?
        .set_point(3, 0.0, 1.0, 0.0)?
        .set_point(4, 0.0, 0.0, 1.0)?
        .set_point(5, 1.0, 0.0, 1.0)?
        .set_point(6, 1.0, 1.0, 1.0)?
        .set_point(7, 0.0, 1.0, 1.0)?;

    // outer cube
    tetgen
        .set_point(8, -1.0, -1.0, -1.0)?
        .set_point(9, 2.0, -1.0, -1.0)?
        .set_point(10, 2.0, 2.0, -1.0)?
        .set_point(11, -1.0, 2.0, -1.0)?
        .set_point(12, -1.0, -1.0, 2.0)?
        .set_point(13, 2.0, -1.0, 2.0)?
        .set_point(14, 2.0, 2.0, 2.0)?
        .set_point(15, -1.0, 2.0, 2.0)?;

    // inner cube
    tetgen
        .set_facet_point(0, 0, 0)?
        .set_facet_point(0, 1, 4)?
        .set_facet_point(0, 2, 7)?
        .set_facet_point(0, 3, 3)?;
    tetgen
        .set_facet_point(1, 0, 1)?
        .set_facet_point(1, 1, 2)?
        .set_facet_point(1, 2, 6)?
        .set_facet_point(1, 3, 5)?;
    tetgen
        .set_facet_point(2, 0, 0)?
        .set_facet_point(2, 1, 1)?
        .set_facet_point(2, 2, 5)?
        .set_facet_point(2, 3, 4)?;
    tetgen
        .set_facet_point(3, 0, 2)?
        .set_facet_point(3, 1, 3)?
        .set_facet_point(3, 2, 7)?
        .set_facet_point(3, 3, 6)?;
    tetgen
        .set_facet_point(4, 0, 0)?
        .set_facet_point(4, 1, 3)?
        .set_facet_point(4, 2, 2)?
        .set_facet_point(4, 3, 1)?;
    tetgen
        .set_facet_point(5, 0, 4)?
        .set_facet_point(5, 1, 5)?
        .set_facet_point(5, 2, 6)?
        .set_facet_point(5, 3, 7)?;

    // outer cube
    tetgen
        .set_facet_point(6, 0, 8 + 0)?
        .set_facet_point(6, 1, 8 + 4)?
        .set_facet_point(6, 2, 8 + 7)?
        .set_facet_point(6, 3, 8 + 3)?;
    tetgen
        .set_facet_point(7, 0, 8 + 1)?
        .set_facet_point(7, 1, 8 + 2)?
        .set_facet_point(7, 2, 8 + 6)?
        .set_facet_point(7, 3, 8 + 5)?;
    tetgen
        .set_facet_point(8, 0, 8 + 0)?
        .set_facet_point(8, 1, 8 + 1)?
        .set_facet_point(8, 2, 8 + 5)?
        .set_facet_point(8, 3, 8 + 4)?;
    tetgen
        .set_facet_point(9, 0, 8 + 2)?
        .set_facet_point(9, 1, 8 + 3)?
        .set_facet_point(9, 2, 8 + 7)?
        .set_facet_point(9, 3, 8 + 6)?;
    tetgen
        .set_facet_point(10, 0, 8 + 0)?
        .set_facet_point(10, 1, 8 + 3)?
        .set_facet_point(10, 2, 8 + 2)?
        .set_facet_point(10, 3, 8 + 1)?;
    tetgen
        .set_facet_point(11, 0, 8 + 4)?
        .set_facet_point(11, 1, 8 + 5)?
        .set_facet_point(11, 2, 8 + 6)?
        .set_facet_point(11, 3, 8 + 7)?;

    // set region and hole
    tetgen.set_region(0, -0.9, -0.9, -0.9, 1, None)?;
    tetgen.set_hole(0, 0.5, 0.5, 0.5)?;

    // generate mesh
    tetgen.generate_mesh(false, false, None, None)?;

    // generate file for Paraview
    if SAVE_VTU_FILE {
        write_tet_vtu(&tetgen, "/tmp/tritet/example_tetgen_mesh_1.vtu")?;
    }

    // draw edges of tetrahedra
    if SAVE_FIGURE {
        let mut plot = Plot::new();
        tetgen.draw_wireframe(&mut plot, true, true, true, true, None, None, None);
        plot.set_equal_axes(true)
            .set_figure_size_points(600.0, 600.0)
            .save("/tmp/tritet/example_tetgen_mesh_1.svg")?;
    }
    Ok(())
}

example_tetgen_mesh_1.png