Skip to content

Commit

Permalink
Merge pull request #96 from JuliaGeometry/sjk/nodep2
Browse files Browse the repository at this point in the history
sjk/nodep2
  • Loading branch information
sjkelly authored Jul 7, 2024
2 parents 2e89b3b + 8831634 commit 0564487
Show file tree
Hide file tree
Showing 15 changed files with 174 additions and 826 deletions.
4 changes: 0 additions & 4 deletions bench/Project.toml

This file was deleted.

27 changes: 0 additions & 27 deletions bench/iso_masjk.jl

This file was deleted.

3 changes: 1 addition & 2 deletions docs/make.jl
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,7 @@ makedocs(
modules = [Meshing],
pages = ["Index" => "index.md",
"API" => "api.md",
"Examples" => "examples.md",
"Internals" => "internals.md"]
"Examples" => "examples.md"]
)

deploydocs(
Expand Down
32 changes: 1 addition & 31 deletions docs/src/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,24 +22,6 @@ A = rand(50,50,50) # 3D Matrix
points,faces = isosurface(A, MarchingCubes(iso=1))
```

Alternatively, we can use the `isosurface` API to sample a function, avoiding allocations:

```julia
using Meshing
using LinearAlgebra
using StaticArrays

points, faces = isosurface(origin=SVector(-1,-1,-1.), widths = SVector(2,2,2.), samples = (40,40,40)) do v
sqrt(sum(dot(v,v))) - 1
end

# by default MarchingCubes() is used, but we may specify a different algorithm as follows

points, faces = isosurface(MarchingTetrahedra(), origin=SVector(-1,-1,-1.), widths = SVector(2,2,2.), samples = (40,40,40)) do v
sqrt(sum(dot(v,v))) - 1
end
```

## Isosurface

`isosurface` is the common and generic API for isosurface extraction with any type of abstract vector/vertex/face type.
Expand All @@ -48,30 +30,19 @@ end
isosurface
```


## Meshing Algorithms

Three meshing algorithms exist:

* `MarchingCubes()`
* `MarchingTetrahedra()`
* `NaiveSurfaceNets()`

Each takes optional `iso`, `eps`, and `insidepositive` parameters, e.g. `MarchingCubes(iso=0.0,eps=1e-6,insidepositive=false)`.
Each takes optional `iso` and `eps` parameters, e.g. `MarchingCubes(iso=0.0,eps=1e-6)`.

Here `iso` controls the offset for the boundary detection. By default this is set to 0. `eps` is the detection tolerance for a voxel edge intersection.
`insidepositive` sets the sign convention for inside/outside the surface (default: false).

Users must construct an algorithm type and use it as an argument to a GeometryTypes mesh call or `isosurface` call.

Below is a comparison of the algorithms:

| Algorithm Type | Face Type | Unique Vertices | Performance | Interpolation |
|---------------------|-----------|-----------------|-------------|-------------------|
| Naive Surface Nets | Quad | Yes | ~1x | Voxel Edge Weight |
| Marching Cubes | Triangle | No/Partial | 1x | Linear on Edge |
| Marching Tetrahedra | Triangle | Yes | 3x | Linear on Edge |

Visual Comparison:
From left: Marching Cubes, Naive Surface Nets, Marching Tetrahedra

Expand All @@ -80,6 +51,5 @@ From left: Marching Cubes, Naive Surface Nets, Marching Tetrahedra
```@docs
MarchingCubes
MarchingTetrahedra
NaiveSurfaceNets
Meshing.AbstractMeshingAlgorithm
```
65 changes: 15 additions & 50 deletions docs/src/examples.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,31 +5,29 @@
The file for this example can be found here: [http://www.slicer.org/slicerWiki/images/0/00/CTA-cardio.nrrd](http://www.slicer.org/slicerWiki/images/0/00/CTA-cardio.nrrd)

```julia

using Meshing
using FileIO
using NRRD
using Meshing
using MeshIO
using WGLMakie
using Downloads
using GeometryBasics

nrrd = Downloads.download("http://www.slicer.org/slicerWiki/images/0/00/CTA-cardio.nrrd")

# load the file as an AxisArray
ctacardio = load("CTA-cardio.nrrd")
ctacardio = load(nrrd)

# use marching cubes with isolevel at 100
algo = MarchingCubes(iso=100, insidepositive=true)
#algo = MarchingCubes(iso=100)
# use marching tetrahedra with iso at 100
# algo = MarchingTetrahedra(iso=100, insidepositive=true)
# use Naive Surface Nets with iso at 100
# algo = NaiveSurfaceNets(iso=100, insidepositive=true)
algo = MarchingTetrahedra(iso=100)


# generate the mesh using marching cubes
mc = Mesh(ctacardio, algo)
vts, fcs = isosurface(ctacardio, algo)

# we can call isosurface to get a vector of points and vector of faces indexing to the points
# vertices, faces = isosurface(ctacardio, algo, Point{3,Float32}, TriangleFace{Int})
WGLMakie.mesh(vts, map(v -> GeometryBasics.TriangleFace(v...), fcs))

# save the file as a PLY file (change extension to save as STL, OBJ, OFF)
save("ctacardio_mc.ply", mc)
```

![cta cardio](./img/ctacardio.png)
Expand Down Expand Up @@ -60,44 +58,11 @@ Makie.mesh(gy_mesh, color=[norm(v) for v in coordinates(gy_mesh)])
![gyroid](./img/gyroid.png)


```julia
using Meshing
using GeometryBasics
using LinearAlgebra: dot, norm
using FileIO

# Mesh an equation of sphere in the Axis-Aligned Bounding box starting
# at -1,-1,-1 and widths of 2,2,2 using Marching Cubes
m = GLNormalMesh(Rect(Vec(-1,-1,-1.), Vec(2,2,2.)), MarchingCubes()) do v
sqrt(sum(dot(v,v))) - 1
end

# save the Sphere as a PLY file
save("sphere.ply",m)
```

For a full listing of concrete `AbstractMesh` types see [GeometryBasics.jl mesh documentation](http://juliageometry.github.io/GeometryBasics.jl/latest/types.html#Meshes-1).

Alternatively, we can use the `isosurface` API to sample a function:

```julia
using Meshing
using LinearAlgebra
using StaticArrays

points, faces = isosurface(origin=SVector(-1,-1,-1.), widths = SVector(2,2,2.), samples = (40,40,40)) do v
sqrt(sum(dot(v,v))) - 1
end

# by default MarchingCubes() is used, but we may specify a different algorithm as follows

points, faces = isosurface(MarchingTetrahedra(), origin=SVector(-1,-1,-1.), widths = SVector(2,2,2.), samples = (40,40,40)) do v
sqrt(sum(dot(v,v))) - 1
end
```

## Isocaps

We do not provide an equivalent to `isocaps` in Matlab, though
a similar result may be achieved by setting the boundary to a large value:

```julia
using GeometryTypes

Expand All @@ -120,4 +85,4 @@ gy_mesh = GLNormalMesh(A, MarchingCubes())
import Makie
using LinearAlgebra
Makie.mesh(gy_mesh, color=[norm(v) for v in gy_mesh.vertices])
```
```
1 change: 0 additions & 1 deletion docs/src/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ Algorithms included:

* [Marching Tetrahedra](https://en.wikipedia.org/wiki/Marching_tetrahedra)
* [Marching Cubes](https://en.wikipedia.org/wiki/Marching_cubes)
* [Naive Surface Nets](https://0fps.net/2012/07/12/smooth-voxel-terrain-part-2/)

## What is isosurface extraction?

Expand Down
58 changes: 0 additions & 58 deletions docs/src/internals.md

This file was deleted.

10 changes: 1 addition & 9 deletions src/Meshing.jl
Original file line number Diff line number Diff line change
@@ -1,18 +1,10 @@
module Meshing

"""
_DEFAULT_SAMPLES = (24,24,24)
Global default sampling count for functions.
"""
const _DEFAULT_SAMPLES = (24,24,24)

include("algorithmtypes.jl")
include("common.jl")
include("marching_tetrahedra.jl")
include("marching_cubes.jl")
include("roots.jl")
include("adaptive.jl")
include("isosurface.jl")

export isosurface,
MarchingCubes,
Expand Down
Loading

0 comments on commit 0564487

Please sign in to comment.