Meshes.jl
Computational geometry and meshing algorithms in Julia.
Overview
Meshes.jl provides efficient implementations of concepts from computational geometry. It promotes rigorous mathematical definitions of spatial discretizations (a.k.a. meshes) that are adequate for describing general manifolds embedded in $\R^n$, including surfaces described with spherical coordinates, and geometries described with multiple coordinate reference systems.
Unlike other existing efforts in the Julia ecosystem, this project is being carefully designed to facilitate the use of meshes across different scientific domains. We follow a strict set of good software engineering practices, and are quite pedantic in our test suite to make sure that all our implementations are free of bugs in both single and double floating point precision. Additionally, we guarantee type stability.
The design of this project was motivated by various issues encountered with past attempts to represent geometry, which have been originally designed for visualization purposes (e.g. GeometryTypes.jl, GeometryBasics.jl) or specifically for finite element analysis (e.g. JuAFEM.jl, MeshCore.jl). We hope to provide a smoother experience with mesh representations that are adequate for finite finite element analysis, advanced geospatial modeling and visualization, not just one domain.
For advanced data science with geospatial data (i.e., tables over meshes), consider the GeoStats.jl framework. It provides sophisticated methods for estimating (interpolating), simulating and learning geospatial functions over Meshes.jl meshes.
If you have questions or would like to brainstorm ideas in general, don't hesitate to start a thread in our zulip channel.
Installation
Get the latest stable release with Julia's package manager:
] add Meshes
Quick example
Although we didn't have time to document the functionality of the package properly, we still would like to illustrate some important features. For more information on available functionality, please consult the Reference guide and the suite of tests in the package.
In all examples we assume the following packages are loaded:
using Meshes, MeshViz
import WGLMakie as Mke
Points and vectors
A Point
is defined by its coordinates in a global reference system. The type of the coordinates is determined automatically based on the specified literals, or is forced to a specific type using helper constructors (e.g. Point2
, Point3
, Point2f
, Point3f
). Integer
coordinates are converted to Float64
to fulfill the requirements of most geometric processing algorithms, which would be undefined in a discrete scale.
A vector Vec
follows the same pattern. It can be constructed with the generic Vec
constructor or with the variants Vec2
and Vec3
for double precision and Vec2f
and Vec3f
for single precision.
# 2D points
A = Point(0.0, 1.0) # double precision as expected
B = Point(0f0, 1f0) # single precision as expected
C = Point(0, 0) # Integer is converted to Float64 by design
D = Point2(0, 1) # explicitly ask for double precision
E = Point2f(0, 1) # explicitly ask for single precision
# 3D points
F = Point(1.0, 2.0, 3.0) # double precision as expected
G = Point(1f0, 2f0, 3f0) # single precision as expected
H = Point(1, 2, 3) # Integer is converted to Float64 by design
I = Point3(1, 2, 3) # explicitly ask for double precision
J = Point3f(1, 2, 3) # explicitly ask for single precision
for P in (A,B,C,D,E,F,G,H,I,J)
println("Coordinate type: ", coordtype(P))
println("Embedding dimension: ", embeddim(P))
end
Coordinate type: Float64
Embedding dimension: 2
Coordinate type: Float32
Embedding dimension: 2
Coordinate type: Float64
Embedding dimension: 2
Coordinate type: Float64
Embedding dimension: 2
Coordinate type: Float32
Embedding dimension: 2
Coordinate type: Float64
Embedding dimension: 3
Coordinate type: Float32
Embedding dimension: 3
Coordinate type: Float64
Embedding dimension: 3
Coordinate type: Float64
Embedding dimension: 3
Coordinate type: Float32
Embedding dimension: 3
Points can be subtracted to produce a vector:
B - A
2-element Vec2 with indices SOneTo(2):
0.0
0.0
They can't be added, but their coordinates can:
coordinates(F) + coordinates(H)
3-element Vec3 with indices SOneTo(3):
2.0
4.0
6.0
We can add a point to a vector though, and get a new point:
F + Vec(1, 1, 1)
Point(2.0, 3.0, 4.0)
And finally, we can create points at random with:
ps = rand(Point2, 10)
10-element Vector{Point2}:
Point(0.3360643147169985, 0.7928926466306162)
Point(0.8686808651168616, 0.957174538160743)
Point(0.16234607993863348, 0.9722719505401646)
Point(0.885772336901338, 0.9209469473225652)
Point(0.15655981410696085, 0.8706983124011528)
Point(0.4283623563871075, 0.1944565394382286)
Point(0.6326613986823666, 0.7117297197495006)
Point(0.07934984912519438, 0.6973420163491991)
Point(0.314804424966064, 0.812280511604748)
Point(0.6008947341014004, 0.36311925293945735)
Primitives
Primitive geometries such as Box
, Ball
, Sphere
, Cylinder
are those geometries that can be efficiently represented in a computer without discretization. We can construct such geometries using clean syntax:
b = Box((0.0, 0.0, 0.0), (1.0, 1.0, 1.0))
viz(b)