Giter Club home page Giter Club logo

meshing.jl's People

Contributors

drelatgithub avatar femtocleaner[bot] avatar github-actions[bot] avatar juliatagbot avatar pauljurczak avatar rdeits avatar simondanisch avatar sjkelly avatar staticfloat avatar thchr avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

meshing.jl's Issues

Tag v0.1.0?

Any objections to me tagging a v0.1.0 release (which will add Julia v0.6 support and drop Julia v0.5)?

Axis Arrays and NRRD

The NRRD format is commonly used for dicom data exports. The NRRD FileIO loader produces an axis array, which is similar to the SDF format, but significantly more mature and feature-rich. In order to be useful for the julia medical/imaging communities, it might be good to have support for Axis Arrays to make the pipeline to a mesh far simpler.

documentation?

Does this package have documentation? Where can I find it?

I could contribute Marching Tetrahedra on Tetmeshes.

Hi, I have this method for extracting plane cuts and isosurfaces from general tetmeshes:

https://github.com/j-fu/GridVisualize.jl/blob/698fb552e250e32a2a5e9a69ff46b0dd28f32db8/src/common.jl#L413

The output can also creates a GeometryBasics.Mesh which can be used with Makie:

https://github.com/j-fu/GridVisualize.jl/blob/698fb552e250e32a2a5e9a69ff46b0dd28f32db8/src/makie.jl#L873

There is also "marching_triangles" for isoline calculation.

In the moment, these are not exported, but they are used by other packages (PlutoVista.jl) or projects (@jlchan). Logically, they should reside outside of GridVisualize.jl, and I have the impression that Meshing.jl could be the right place (though I find the package name a bit misleading...). So before creating another package I would like to discuss to move these into Meshing.jl and export them.

A couple of points:

  • I would like to keep the current mostly array based API and internal coding, a wrapper taking GeometryBasics.Mesh appears to be not too hard to create. The main reason for this is that I consider the current state of GeometryBasics.jl / Meshes.jl etc not settled.
  • I think I already have commit access as a member of JuliaGeometry (maintaining Triangulate.jl a and co-maintaining TetGen.jl) and I would care about maintaining the corresponding part of the code.

How do you look at this ?

isosurface(x,y,z,V) and rotations

After digging into Contour and discussing with some collaborators, the isosurface(x,y,z, V) idiom is somewhat common. Moreso those coming from Matlab, but there are other benefits. One could apply a rotation to the points before meshing occurs and retain the signed distance array/levelset.

Makie error when plotting meshes

I apologize if this is the wrong place for this issue. I pulled this MWE from the tests so that runs on Meshing#master but doesn't plot.

julia> A = rand(20,20,20);

julia> m = GeometryBasics.mesh(A,MarchingTetrahedra(1.0),origin=Point(Float32(0),Float32(0),Float32(0)),widths=Point(
Float32(1),Float32(1),Float32(1)));

julia> Makie.mesh(m)
┌ Warning: No strict ticks found
└ @ PlotUtils ~/.julia/packages/PlotUtils/Zg3aP/src/ticks.jl:283
┌ Warning: No strict ticks found
└ @ PlotUtils ~/.julia/packages/PlotUtils/Zg3aP/src/ticks.jl:283
┌ Warning: No strict ticks found
└ @ PlotUtils ~/.julia/packages/PlotUtils/Zg3aP/src/ticks.jl:283
ArgumentError: At least one finite value must be provided to formatter.with ticks: [-Inf, Inf]
ArgumentError: At least one finite value must be provided to formatter.with ticks: [-Inf, Inf]
ArgumentError: At least one finite value must be provided to formatter.with ticks: [-Inf, Inf]
┌ Warning: No strict ticks found
└ @ PlotUtils ~/.julia/packages/PlotUtils/Zg3aP/src/ticks.jl:283
┌ Warning: No strict ticks found
└ @ PlotUtils ~/.julia/packages/PlotUtils/Zg3aP/src/ticks.jl:283
┌ Warning: No strict ticks found
└ @ PlotUtils ~/.julia/packages/PlotUtils/Zg3aP/src/ticks.jl:283
ArgumentError: At least one finite value must be provided to formatter.with ticks: [-Inf, Inf]
ArgumentError: At least one finite value must be provided to formatter.with ticks: [-Inf, Inf]
ArgumentError: At least one finite value must be provided to formatter.with ticks: [-Inf, Inf]
┌ Warning: limits of scene contain non finite values: Float32[Inf, Inf, Inf] .. Float32[NaN, NaN, NaN]
└ @ AbstractPlotting ~/.julia/packages/AbstractPlotting/jOgYQ/src/scenes.jl:586
┌ Warning: No strict ticks found
└ @ PlotUtils ~/.julia/packages/PlotUtils/Zg3aP/src/ticks.jl:283
┌ Warning: No strict ticks found
└ @ PlotUtils ~/.julia/packages/PlotUtils/Zg3aP/src/ticks.jl:283
┌ Warning: No strict ticks found
└ @ PlotUtils ~/.julia/packages/PlotUtils/Zg3aP/src/ticks.jl:283
ArgumentError: At least one finite value must be provided to formatter.with ticks: [-Inf, Inf]
ArgumentError: At least one finite value must be provided to formatter.with ticks: [-Inf, Inf]
ArgumentError: At least one finite value must be provided to formatter.with ticks: [-Inf, Inf]
1   : #version 410
2   :
3   :
4   : in dvec3 vertices;
5   : uniform vec4 vertex_color;
6   : uniform vec2 texturecoordinates;
7   : in vec3 normals;
8   :
9   : uniform vec3 lightposition;
10  : uniform mat4 projection, view, model;
11  : void render(vec4 vertices, vec3 normals, mat4 viewmodel, mat4 projection, vec3 lightposition);
12  :
13  : uniform uint objectid;
14  : flat out uvec2 o_id;
15  : out vec2 o_uv;
16  : out vec4 o_color;
17  :
18  : vec3 to_3d(vec2 v){return vec3(v, 0);}
19  : vec3 to_3d(vec3 v){return v;}
20  :
21  : vec2 to_2d(float v){return vec2(v, 0);}
22  : vec2 to_2d(vec2 v){return v;}
23  :
24  : vec4 to_color(vec3 c){return vec4(c, 1);}
25  : vec4 to_color(vec4 c){return c;}
26  :
27  : void main()
28  : {
29  :     o_id = uvec2(objectid, gl_VertexID+1);
30  :     vec2 tex_uv = to_2d(texturecoordinates);
31  :     o_uv = vec2(1.0 - tex_uv.y, tex_uv.x);
32  :     o_color = to_color(vertex_color);
33  :     vec3 v = to_3d(vertices);
34  :     render(model * vec4(v, 1), (model * vec4(normals, 0)).xyz, view, projection, lightposition);
35  : }
36  :
┌ Warning: shader /Users/zchristensen/.julia/packages/GLMakie/S9Zib/src/GLVisualize/assets/shader/standard.vert didn'
t compile.
│ ERROR: 0:33: No matching function for call to to_3d(dvec3)
│ ERROR: 0:34: Use of undeclared identifier 'v'
└ @ GLMakie.GLAbstraction ~/.julia/packages/GLMakie/S9Zib/src/GLAbstraction/GLShader.jl:139
1   : #version 410
2   :
3   :
4   : in dvec3 vertices;
5   : uniform vec4 vertex_color;
6   : uniform vec2 texturecoordinates;
7   : in vec3 normals;
8   :
9   : uniform vec3 lightposition;
10  : uniform mat4 projection, view, model;
11  : void render(vec4 vertices, vec3 normals, mat4 viewmodel, mat4 projection, vec3 lightposition);
12  :
13  : uniform uint objectid;
14  : flat out uvec2 o_id;
15  : out vec2 o_uv;
16  : out vec4 o_color;
17  :
18  : vec3 to_3d(vec2 v){return vec3(v, 0);}
19  : vec3 to_3d(vec3 v){return v;}
20  :
21  : vec2 to_2d(float v){return vec2(v, 0);}
22  : vec2 to_2d(vec2 v){return v;}
23  :
24  : vec4 to_color(vec3 c){return vec4(c, 1);}
25  : vec4 to_color(vec4 c){return c;}
26  :
27  : void main()
28  : {
29  :     o_id = uvec2(objectid, gl_VertexID+1);
30  :     vec2 tex_uv = to_2d(texturecoordinates);
31  :     o_uv = vec2(1.0 - tex_uv.y, tex_uv.x);
32  :     o_color = to_color(vertex_color);
33  :     vec3 v = to_3d(vertices);
34  :     render(model * vec4(v, 1), (model * vec4(normals, 0)).xyz, view, projection, lightposition);
35  : }
36  :
┌ Warning: shader /Users/zchristensen/.julia/packages/GLMakie/S9Zib/src/GLVisualize/assets/shader/standard.vert didn'
t compile.
│ ERROR: 0:33: No matching function for call to to_3d(dvec3)
│ ERROR: 0:34: Use of undeclared identifier 'v'
└ @ GLMakie.GLAbstraction ~/.julia/packages/GLMakie/S9Zib/src/GLAbstraction/GLShader.jl:139
Error showing value of type Scene:
ERROR: program 34 not linked. Error in:
/Users/zchristensen/.julia/packages/GLMakie/S9Zib/src/GLVisualize/assets/shader/fragment_output.frag or /Users/zchris
tensen/.julia/packages/GLMakie/S9Zib/src/GLVisualize/assets/shader/util.vert or /Users/zchristensen/.julia/packages/G
LMakie/S9Zib/src/GLVisualize/assets/shader/standard.vert or /Users/zchristensen/.julia/packages/GLMakie/S9Zib/src/GLV
isualize/assets/shader/standard.frag
ERROR: One or more attached shaders not successfully compiled

Stacktrace:
 [1] error(::String, ::String, ::String, ::String) at ./error.jl:42
 [2] compile_program(::Array{GLMakie.GLAbstraction.Shader,1}, ::Array{Tuple{Int64,String},1}) at /Users/zchristensen/
.julia/packages/GLMakie/S9Zib/src/GLAbstraction/GLShader.jl:197
 [3] (::GLMakie.GLAbstraction.var"#62#67"{Dict{Symbol,Any},NTuple{4,String},Dict{String,String},Array{Array{String,1}
,1},Array{Array{String,1},1}})() at /Users/zchristensen/.julia/packages/GLMakie/S9Zib/src/GLAbstraction/GLShader.jl:2
62
 [4] get!(::GLMakie.GLAbstraction.var"#62#67"{Dict{Symbol,Any},NTuple{4,String},Dict{String,String},Array{Array{Strin
g,1},1},Array{Array{String,1},1}}, ::Dict{Any,GLMakie.GLAbstraction.GLProgram}, ::Tuple{NTuple{4,String},Array{Array{
String,1},1}}) at ./dict.jl:452
 [5] gl_convert(::GLMakie.GLVisualize.GLVisualizeShader, ::Dict{Symbol,Any}) at /Users/zchristensen/.julia/packages/G
LMakie/S9Zib/src/GLAbstraction/GLShader.jl:254
 [6] GLMakie.GLAbstraction.RenderObject(::Dict{Symbol,Any}, ::GLMakie.GLVisualize.GLVisualizeShader, ::GLMakie.GLAbst
raction.StandardPrerender, ::Nothing, ::GeometryBasics.HyperRectangle{3,Float32}, ::Nothing) at /Users/zchristensen/.
julia/packages/GLMakie/S9Zib/src/GLAbstraction/GLTypes.jl:327
 [7] assemble_robj(::Dict{Symbol,Any}, ::GLMakie.GLVisualize.GLVisualizeShader, ::GeometryBasics.HyperRectangle{3,Flo
at32}, ::UInt32, ::Nothing, ::Nothing) at /Users/zchristensen/.julia/packages/GLMakie/S9Zib/src/GLVisualize/visualize
_interface.jl:96
 [8] assemble_shader(::Dict{Symbol,Any}) at /Users/zchristensen/.julia/packages/GLMakie/S9Zib/src/GLVisualize/visuali
ze_interface.jl:117
 [9] visualize(::Any, ::Any, ::Any) at /Users/zchristensen/.julia/packages/GLMakie/S9Zib/src/GLVisualize/visualize_in
terface.jl:166
 [10] (::GLMakie.var"#108#112"{Mesh{...}})(::Dict{Symbol,Any}) at /Users/zchristensen/.julia/packages/GLMakie/S9Zib/s
rc/drawing_primitives.jl:384
 [11] (::GLMakie.var"#56#63"{GLMakie.var"#108#112"{Mesh{...}},GLMakie.Screen,Scene,Mesh{...}})() at /Users/zchristens
en/.julia/packages/GLMakie/S9Zib/src/drawing_primitives.jl:68
 [12] get!(::GLMakie.var"#56#63"{GLMakie.var"#108#112"{Mesh{...}},GLMakie.Screen,Scene,Mesh{...}}, ::Dict{UInt64,GLMa
kie.GLAbstraction.RenderObject}, ::UInt64) at ./dict.jl:452
 [13] cached_robj!(::GLMakie.var"#108#112"{Mesh{...}}, ::GLMakie.Screen, ::Scene, ::Mesh{...}) at /Users/zchristensen
/.julia/packages/GLMakie/S9Zib/src/drawing_primitives.jl:41
 [14] draw_atomic at /Users/zchristensen/.julia/packages/GLMakie/S9Zib/src/drawing_primitives.jl:349 [inlined]
 [15] insert!(::GLMakie.Screen, ::Scene, ::Mesh{...}) at /Users/zchristensen/.julia/packages/GLMakie/S9Zib/src/drawin
g_primitives.jl:158
 [16] insertplots!(::GLMakie.Screen, ::Scene) at /Users/zchristensen/.julia/packages/GLMakie/S9Zib/src/screen.jl:53
 [17] backend_display(::GLMakie.Screen, ::Scene) at /Users/zchristensen/.julia/packages/GLMakie/S9Zib/src/screen.jl:1
23
 [18] backend_display at /Users/zchristensen/.julia/packages/GLMakie/S9Zib/src/gl_backend.jl:59 [inlined]
 [19] display(::AbstractPlotting.PlotDisplay, ::Scene) at /Users/zchristensen/.julia/packages/AbstractPlotting/jOgYQ/
src/display.jl:45
 [20] display(::Any) at ./multimedia.jl:323
 [21] #invokelatest#1 at ./essentials.jl:712 [inlined]
 [22] invokelatest at ./essentials.jl:711 [inlined]
 [23] print_response(::IO, ::Any, ::Bool, ::Bool, ::Any) at /Users/julia/buildbot/worker/package_macos64/build/usr/sh
are/julia/stdlib/v1.4/REPL/src/REPL.jl:161
 [24] print_response(::REPL.AbstractREPL, ::Any, ::Bool, ::Bool) at /Users/julia/buildbot/worker/package_macos64/buil
d/usr/share/julia/stdlib/v1.4/REPL/src/REPL.jl:146
 [25] (::REPL.var"#do_respond#38"{Bool,REPL.var"#48#57"{REPL.LineEditREPL,REPL.REPLHistoryProvider},REPL.LineEditREPL
,REPL.LineEdit.Prompt})(::Any, ::Any, ::Any) at /Users/julia/buildbot/worker/package_macos64/build/usr/share/julia/st
dlib/v1.4/REPL/src/REPL.jl:729
 [26] #invokelatest#1 at ./essentials.jl:712 [inlined]
 [27] invokelatest at ./essentials.jl:711 [inlined]
 [28] run_interface(::REPL.Terminals.TextTerminal, ::REPL.LineEdit.ModalInterface, ::REPL.LineEdit.MIState) at /Users
/julia/buildbot/worker/package_macos64/build/usr/share/julia/stdlib/v1.4/REPL/src/LineEdit.jl:2354
 [29] run_frontend(::REPL.LineEditREPL, ::REPL.REPLBackendRef) at /Users/julia/buildbot/worker/package_macos64/build/
usr/share/julia/stdlib/v1.4/REPL/src/REPL.jl:1055
 [30] run_repl(::REPL.AbstractREPL, ::Any) at /Users/julia/buildbot/worker/package_macos64/build/usr/share/julia/stdl
ib/v1.4/REPL/src/REPL.jl:206
 [31] (::Base.var"#764#766"{Bool,Bool,Bool,Bool})(::Module) at ./client.jl:383
 [32] #invokelatest#1 at ./essentials.jl:712 [inlined]
 [33] invokelatest at ./essentials.jl:711 [inlined]
 [34] run_main_repl(::Bool, ::Bool, ::Bool, ::Bool, ::Bool) at ./client.jl:367
 [35] exec_options(::Base.JLOptions) at ./client.jl:305
 [36] _start() at ./client.jl:484

GeometryBasics example errors

When I run the first example in https://juliageometry.github.io/Meshing.jl/dev/api/#Quick-Start-GeometryBasics-1 using the following code https://gist.github.com/jlchan/833c7b085149500bbd2e79c7a227cf07, I get an error.

ERROR: LoadError: MethodError: no method matching (AbstractMesh{GeometryBasics.Ngon{Dim, Float32, 3, PointMeta{Dim, Float32, Pointf{Dim}, (:normals,), Tuple{Vec{3, Float32}}}}} where Dim)(::var"#15#16", ::Rect3{Float64}, ::MarchingCubes{Float64})
Stacktrace:
 [1] top-level scope
   @ ~/Downloads/test.jl:9
in expression starting at /Users/jessechan/Downloads/test.jl:9

I'm using Julia 1.6.3 if that helps.

Benchmarks

It would be helpful to have some basic benchmarks to aid optimizations.

v0.5.0 Punchlist

  • Non-pirating function (isosurface?)
  • Method Symmetry
  • Non-SDF Call Variant
  • Support different sign conventions
  • Function sampling using marching Tetrahedra
  • docs

Non-pirating function

Currently GeometryTypes has to also be imported to even call the Meshing functions. A non-type pirate variant of the function would allow this. The intneral of MarchingTetrahedra use an isosurface function There are three options.

  • return (Vector{SVector}, Vector{SVector})
  • return (Vector{Point}, Vector{Face})
  • return SimpleMesh

With the work to make the internals more generic, I think the first could be a good default, with an option for the second with different function arguments. Construction of a mesh from (Vector{Point}, Vector{Face}) is trivial and fast.

Method Symmetry and Non-SDF call Variant

This is part of the above. MarchingTetrahedra will take a 3D array rather than SDF. This should allow simple compatibility with Medical imagry, NRRD/AxisArrays without direct dependence on these packages.

Support different sign conventions

Some of the NRRD data (all?) I have encountered uses positive signs for the interior of the isosurface. This should be a switch in all functions.

Docs

For clarity, the docs should be finished before tag.

Isocaps

This came up on slack. In some cases a user may always want a manifold surface from the isosurface extraction routing. We can generate "isocaps" that close the ends of the surface where it intersect with the bounding box to ensure that the surface is manifold for 3d printing or visualization of cross sections.

Interpolation Mechanisms

Currently each algorithm has its own mechanism for interpolating the edge crossing in a voxel. It may be useful in some visualization paradigms to just deliver the midpoint in each scenario for higher performance. Conversely, in the function variants we can use root finding for even higher precision.

Example:gyroid does not run

I'm new, so sorry if this is known. I'm on JuliaPro, have cloned 0.5.4 after 0.5.3 in the package repository didn't work but I still get:

LoadError: MethodError: no method matching AbstractArray{GeometryBasics.Ngon{Dim,Float32,3,PointMeta{Dim,Float32,Point{Dim,Float32},(:normals,),Tuple{Vec{3,Float32}}}},1} where Dim(::var"#13#14", ::GeometryBasics.HyperRectangle{3,Float64}, ::MarchingCubes{Float64})

Generic Typing and computation

I have been thinking about a good way to allow for congruity of SDF types and Mesh types. Part of the current issue is that one may generate an SDF using Float32, but the internal computations for Meshing are Float64 converted back to Float32. Similarly, all direct samplings of a function pass Float64.

Geometry Types exports facetype and vertextype. These can be used to determine the sampling/interpolation types. If vertextype is nothing, in the case of an SDF we will use a Point of the same type as the sampling data.

If neither are specified, such as just calling HomogenousMesh(x -> norm(dot(x)) - 1, MarchingCubes()) we default to Float32 points for performance and better GPU interop.

TODO: In the case of faces I am not sure if Int32 or Int64 for Faces is preferable for GPU/Makie/Plots.

Normals:

I think there are mechanism for specifying normals in Geometry types. Since we may add ForwardDiff in the future for root finding, the computation of true normals on a smooth function should be possible to do in one pass.

Tests failing

There does not currently seem to be a constructor for HomogenousMesh with just the vertex and face arrays as inputs, causing this error message:

ERROR: LoadError: MethodError: `convert` has no method matching convert(::Type{GeometryTypes.HomogenousMesh{FixedSizeArrays.Point{3,Float64},GeometryTypes.Face{3,Int64,0},NormalT,TexCoordT,ColorT,AttribT,AttribIDT}}, ::Array{FixedSizeArrays.Point{3,Float64},1}, ::Array{GeometryTypes.Face{3,Int64,0},1}, ::Array{Any,1}, ::Array{Any,1}, ::Type{Void}, ::Type{Void}, ::Array{Any,1})
This may have arisen from a call to the constructor GeometryTypes.HomogenousMesh{FixedSizeArrays.Point{3,Float64},GeometryTypes.Face{3,Int64,0},NormalT,TexCoordT,ColorT,AttribT,AttribIDT}(...),
since type constructors fall back to convert methods.
Closest candidates are:
  call{T<:GeometryTypes.AbstractMesh{VertT,FaceT}}(::Type{T<:GeometryTypes.AbstractMesh{VertT,FaceT}}, !Matched::GeometryTypes.GeometryPrimitive{N,T}, ::Any...)
  call{M<:GeometryTypes.HomogenousMesh{VertT,FaceT,NormalT,TexCoordT,ColorT,AttribT,AttribIDT},VT,FT<:GeometryTypes.Face{N,T,IndexOffset}}(::Type{M<:GeometryTypes.HomogenousMesh{VertT,FaceT,NormalT,TexCoordT,ColorT,AttribT,AttribIDT}}, ::Array{FixedSizeArrays.Point{3,VT},1}, ::Array{FT<:GeometryTypes.Face{N,T,IndexOffset},1})
  call{HM<:GeometryTypes.HomogenousMesh{VertT,FaceT,NormalT,TexCoordT,ColorT,AttribT,AttribIDT},ConstAttrib}(::Type{HM<:GeometryTypes.HomogenousMesh{VertT,FaceT,NormalT,TexCoordT,ColorT,AttribT,AttribIDT}}, !Matched::GeometryTypes.AbstractMesh{VertT,FaceT}, ::ConstAttrib)
  ...
 in marching_cubes at /Users/james/.julia/v0.4/Meshing/src/marching_cubes.jl:386
 in marching_cubes at /Users/james/.julia/v0.4/Meshing/src/marching_cubes.jl:292
 in include at /Applications/Julia-0.4.5.app/Contents/Resources/julia/lib/julia/sys.dylib
 in include_from_node1 at /Applications/Julia-0.4.5.app/Contents/Resources/julia/lib/julia/sys.dylib
 in process_options at /Applications/Julia-0.4.5.app/Contents/Resources/julia/lib/julia/sys.dylib
 in _start at /Applications/Julia-0.4.5.app/Contents/Resources/julia/lib/julia/sys.dylib
while loading /Users/james/.julia/v0.4/Meshing/test/runtests.jl, in expression starting on line 40

Regression in Naive Surface Nets

using Meshing
using GeometryTypes
using LinearAlgebra: dot, norm
using FileIO

f(v) = sqrt(sum(dot(v,v))) - 1
sdf = SignedDistanceField(f,HyperRectangle(Vec(-1,-1,-1.), Vec(2,2,2.)))

mc = HomogenousMesh(sdf, MarchingCubes())
mt = HomogenousMesh(sdf, MarchingTetrahedra())
ns = HomogenousMesh(sdf, NaiveSurfaceNets())

# save the Sphere as a PLY file
save("sphere_mc.ply",mc)
save("sphere_mt.ply",mt)
save("sphere_ns.ply",ns)

image

Helpful Errors

  • when Quad faces are called on MarchingTetrahedra, MarchingCubes.
  • when Integer points are requested (#42)

Fully de-duplicate vertices in MarchingCube algorithm

Recently I started using Meshing.isosurface(), with MarchingCubes as method. The docs say that
setting reduceverts=true (default: true) will merge vertices within a voxel to reduce mesh size by around 30%
and with slight performance improvement.

I called both Meshing.isosurface() and skimage.measure.marching_cubes_lewiner(), a Python function from scikit-image,
to extrude a brain within a volumetric data of size (91, 109, 91).
The number of vertices of the corresponding mesh, returned by Meshing function is (345752) almost 4 times greater
than that returned by skimage function (86473).
345752/86473 = 3.99, i.e. it is exaggerated.

Here are the two blocks of code:

using Meshing
using NPZ           
brain_vol = npzread("MNI152.npy") # https://github.com/empet/Datasets/blob/master/MNI152.npy
verts, triangles =  isosurface(brain_vol, MarchingCubes(iso=1.25, reduceverts=true, eps=1e-05))
length(verts),  length(triangles)
(345752, 172932) 
            
#unique vertices:
uni_verts = unique(i -> verts[i], 1:length(verts))
length(uni_verts)
89264 

respectively:

import numpy as np
from skimage import measure            
brain_vol= np.load("MNI152.npy")
verts, triangles = measure.marching_cubes_lewiner(brain_vol, 1.25)[:2] 
len(verts), len(triangles)
(86473, 173070)

The corresponding Jupyter Notebook has the size of 111MB, vs 25MB, when using Python scikit-image.
Otherwise the mesh plot is great in both cases:
iso-brain

varg passed incorrectly in GeometryTypes API

via slack:

julia> GLNormalMesh(A,MarchingTetrahedra(1.0),origin=Point(Float32(0),Float32(0),Float32(0)),widths=Point(Float32(1),Float32(1),Float32(1)))      
ERROR: MethodError: no method matching isosurface(::Array{Float64,3}, ::MarchingTetrahedra{Float64}, ::Type{Point{3,Float32}}, ::Type{Face{3,OffsetInteger{-1,UInt32}}}, ::Pair{Symbol,Point{3,Float32}}, ::Pair{Symbol,Point{3,Float32}})
Closest candidates are:
  isosurface(::AbstractArray{T,3}, ::MarchingTetrahedra, ::Type{VertType}, ::Type{FaceType}; origin, widths) where {T, VertType, FaceType} at C:\Users\kd2cc\.julia\dev\Meshing\src\marching_tetrahedra.jl:138
  isosurface(::AbstractArray{T,3}, ::MarchingTetrahedra, ::Type{VertType}) where {T, VertType} at C:\Users\kd2cc\.julia\dev\Meshing\src\marching_tetrahedra.jl:138
  isosurface(::AbstractArray{T,3}, ::MarchingCubes, ::Type{VertType}, ::Type{FaceType}; origin, widths) where {T, VertType, FaceType} at C:\Users\kd2cc\.julia\dev\Meshing\src\marching_cubes.jl:14

tests on 0.7 produces internal errors

Under 0.7, linux ubunu

julia> versioninfo()
Julia Version 0.7.1-pre.0
Commit 36cddc1006 (2018-08-09 00:19 UTC)
Platform Info:
  OS: Linux (x86_64-unknown-linux-gnu)
  CPU: Intel(R) Core(TM) i7-6700HQ CPU @ 2.60GHz
  WORD_SIZE: 64
  LIBM: libopenlibm
  LLVM: libLLVM-6.0.0 (ORCJIT, skylake)
Environment:
  JULIA_DIR = $HOME/Julia/julia
  JULIADEFAULTVERSION = 0.7
  JULIACURRENTVERSION = 0.7
  JULIAPYTHON =$HOME/.julia/packages/Conda/m7vem/deps/usr/bin/python2.7
  JULIACONDA = $HOME/.julia/packages/Conda/m7vem/deps/usr/bin/conda
  JULIACONDA_DIR = $HOME/.julia/packages/Conda/m7vem/deps/usr/
  JULIAPYTHON_DIR = $HOME/.julia/packages/Conda/m7vem/deps/usr/bin/
  JULIA_NUM_THREADS = 4

testing Meshingproduces internal errors (while tests are passed successfully)

(v0.7) pkg> test Meshing
   Testing Meshing
 Resolving package versions...
    Status `/tmp/tmp0YFuw9/Manifest.toml`
  [9e28174c] BinDeps v0.8.10
  [b99e7846] BinaryProvider v0.4.2
  [3da002f7] ColorTypes v0.7.4
  [bbf7d656] CommonSubexpressions v0.2.0
  [34da2185] Compat v1.1.0
  [163ba53b] DiffResults v0.0.3
  [b552c78f] DiffRules v0.0.7
  [53c48c17] FixedPointNumbers v0.5.2
  [f6369f11] ForwardDiff v0.7.5
  [4d00f742] GeometryTypes v0.6.2
  [c8e1da08] IterTools v1.0.0
  [e6723b4c] Meshing v0.4.0
  [77ba4419] NaNMath v0.3.2
  [276daf66] SpecialFunctions v0.7.0
  [90137ffa] StaticArrays v0.8.3
  [30578b45] URIParser v0.4.0
  [2a0f44e3] Base64  [`~/Julia/julia-release-0.7/usr/bin/../share/julia/stdlib/v0.7/Base64`]
  [ade2ca70] Dates  [`~/Julia/julia-release-0.7/usr/bin/../share/julia/stdlib/v0.7/Dates`]
  [8bb1440f] DelimitedFiles  [`~/Julia/julia-release-0.7/usr/bin/../share/julia/stdlib/v0.7/DelimitedFiles`]
  [8ba89e20] Distributed  [`~/Julia/julia-release-0.7/usr/bin/../share/julia/stdlib/v0.7/Distributed`]
  [b77e0a4c] InteractiveUtils  [`~/Julia/julia-release-0.7/usr/bin/../share/julia/stdlib/v0.7/InteractiveUtils`]
  [76f85450] LibGit2  [`~/Julia/julia-release-0.7/usr/bin/../share/julia/stdlib/v0.7/LibGit2`]
  [8f399da3] Libdl  [`~/Julia/julia-release-0.7/usr/bin/../share/julia/stdlib/v0.7/Libdl`]
  [37e2e46d] LinearAlgebra  [`~/Julia/julia-release-0.7/usr/bin/../share/julia/stdlib/v0.7/LinearAlgebra`]
  [56ddb016] Logging  [`~/Julia/julia-release-0.7/usr/bin/../share/julia/stdlib/v0.7/Logging`]
  [d6f4376e] Markdown  [`~/Julia/julia-release-0.7/usr/bin/../share/julia/stdlib/v0.7/Markdown`]
  [a63ad114] Mmap  [`~/Julia/julia-release-0.7/usr/bin/../share/julia/stdlib/v0.7/Mmap`]
  [44cfe95a] Pkg  [`~/Julia/julia-release-0.7/usr/bin/../share/julia/stdlib/v0.7/Pkg`]
  [de0858da] Printf  [`~/Julia/julia-release-0.7/usr/bin/../share/julia/stdlib/v0.7/Printf`]
  [9abbd945] Profile  [`~/Julia/julia-release-0.7/usr/bin/../share/julia/stdlib/v0.7/Profile`]
  [3fa0cd96] REPL  [`~/Julia/julia-release-0.7/usr/bin/../share/julia/stdlib/v0.7/REPL`]
  [9a3f8284] Random  [`~/Julia/julia-release-0.7/usr/bin/../share/julia/stdlib/v0.7/Random`]
  [ea8e919c] SHA  [`~/Julia/julia-release-0.7/usr/bin/../share/julia/stdlib/v0.7/SHA`]
  [9e88b42a] Serialization  [`~/Julia/julia-release-0.7/usr/bin/../share/julia/stdlib/v0.7/Serialization`]
  [1a1011a3] SharedArrays  [`~/Julia/julia-release-0.7/usr/bin/../share/julia/stdlib/v0.7/SharedArrays`]
  [6462fe0b] Sockets  [`~/Julia/julia-release-0.7/usr/bin/../share/julia/stdlib/v0.7/Sockets`]
  [2f01184e] SparseArrays  [`~/Julia/julia-release-0.7/usr/bin/../share/julia/stdlib/v0.7/SparseArrays`]
  [10745b16] Statistics  [`~/Julia/julia-release-0.7/usr/bin/../share/julia/stdlib/v0.7/Statistics`]
  [8dfed614] Test  [`~/Julia/julia-release-0.7/usr/bin/../share/julia/stdlib/v0.7/Test`]
  [cf7118a7] UUIDs  [`~/Julia/julia-release-0.7/usr/bin/../share/julia/stdlib/v0.7/UUIDs`]
  [4ec0a83e] Unicode  [`~/Julia/julia-release-0.7/usr/bin/../share/julia/stdlib/v0.7/Unicode`]
Internal error: encountered unexpected error in runtime:
TypeError(func=:<:, context="", expected=Type{T} where T, got=_)
rec_backtrace at $HOME/Julia/julia-release-0.7/src/stackwalk.c:94
record_backtrace at $HOME/Julia/julia-release-0.7/src/task.c:246
jl_throw at $HOME/Julia/julia-release-0.7/src/task.c:577
jl_type_error_rt at $HOME/Julia/julia-release-0.7/src/rtutils.c:118
jl_type_error at $HOME/Julia/julia-release-0.7/src/rtutils.c:124
jl_f_issubtype at $HOME/Julia/julia-release-0.7/src/builtins.c:414
...

GeometryBasics Normal Calculations/general API for specifying normals

We have mostly relied on the GeometryTypes API to generate normals. In GB we can do the same, but we shouldn't fix the calls to Mesh. E.g. GLNormalMesh3D should work.

Similarly I have been getting good results using autodiff to make normals on functions, so it would be nice to have an explicit API for passing a normal function to the meshing process.

example from README.md broken

The example given in README

using Meshing
using GeometryTypes
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
m = GLNormalMesh(HyperRectangle(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)

causes the following error

MethodError: no method matching GLNormalMesh(::getfield(Main, Symbol("##3#4")), ::HyperRectangle{3,Float64}, ::MarchingCubes{Float64})
Closest candidates are:
  GLNormalMesh(::Any, ::Any, ::Any, !Matched::Any, !Matched::Any, !Matched::Any, !Matched::Any) where {VertT, FaceT, NormalT, TexCoordT, ColorT, AttribT, AttribIDT} at /home/jgraw/.julia/packages/GeometryTypes/ETYtg/src/types.jl:167
  GLNormalMesh(!Matched::GeometryPrimitive, ::Any...) where T<:AbstractMesh at /home/jgraw/.julia/packages/GeometryTypes/ETYtg/src/primitives.jl:14
  GLNormalMesh(!Matched::AbstractMesh, ::ConstAttrib) where {HM<:HomogenousMesh, ConstAttrib} at /home/jgraw/.julia/packages/GeometryTypes/ETYtg/src/meshes.jl:132
  ...

Apparently, GLNormalMesh does not provide the convenience of constructing a SignedDistanceField automatically. Constructing the SDF manually works:

using Meshing
using GeometryTypes
using LinearAlgebra
using FileIO

# Mesh an equation of sphere in the Axis-Aligned Bounding box starting
# at -1,-1,-1 and widths of 2,2,2
sdf = SignedDistanceField(HyperRectangle(Vec3f0(-1), Vec3f0(2))) do v
    return v ⋅ v - 1
end
m = GLNormalMesh(sdf, MarchingTetrahedra())

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

In addition the example requires MeshIO.jl which should be noted as a prerequisite for the example.

On the scope of this package

Hello I´m trying to mesh a 3d object that I have as a triangulated surface (each face is given by 3 points), here is an example of how it looks like:

eros

I want to get a 3d mesh with tetrahedron of the whole volume to model the internal mass distribution. I thought that maybe this package would do the trick, but reading carefully the documentation provided I currently understand that this is only possible if you have an implicit function of the surface that encloses the 3d body (using the SignedDistanceField function). Am I wrong in this supposition or there is more functionality to Meshing.jl?

Gracefully handle requests for integer points

Caused by #35. In this case I was loading an NRRD file with Int16 data, which is not handled by the current system well.

ERROR: LoadError: InexactError: Int16(0.019569471624266144)
...
 [7] marching_cubes(::GeometryTypes.SignedDistanceField{3,Int64,Int16}, 
::Type{GeometryTypes.Point{3,Int16}}, ::Type{GeometryTypes.Face{3,Int64}}, ::Float64, 
::Type{GeometryTypes.HomogenousMesh}, ::Float64, ::Bool) at /home/steve/.julia/dev/Meshing/src/marching_cubes.jl:33

It might be good to make this a warning with deference to Float64.

Naive methods and parallelizations?

Hello,
I am using Meshing to create hypercomplex fractals and high dimension cellular automata
Is it possible to have the isosurface as simple squares perpendicular to the axes(so draw rectangular boxes, no other gradients)? If this is possible, can we parallelize it?

TagBot trigger issue

This issue is used to trigger TagBot; feel free to unsubscribe.

If you haven't already, you should update your TagBot.yml to include issue comment triggers.
Please see this post on Discourse for instructions and more details.

If you'd like for me to do this for you, comment TagBot fix on this issue.
I'll open a PR within a few hours, please be patient!

Order of points in triangles

Hello. I am currently using MarchingCubes and MarchingTetrahedra.

I would like to know the order of points in a face. In order word, Is that counter-clock wise or clock wise with respect to normal vector?

Thank you for your time in advance.

What is in the name?

I like what the package does, I really do. The name, however, promises too much. "Meshing" seems to say "I do meshing". This implies not only producing meshes in different dimensions (boundary and interior of domains), but also producing meshes with some guarantees on shape (in some measure: aspect ratios, dihedral angles, ...).

Perhaps this is coming, but if not, then the name is slightly misleading.

Threaded Meshing

From what I can tell this should be possible in at least MarchingCubes and NaiveSurfaceNets. There are some other optimizations from the NaiveSurfaceNet implementation I would also like to apply to MarchingCubes and Marching Tetrahedra.

marching_cubes shifts the coordinate origin

applying marching_cubes to an SignedDistanceField over a HyperRectangle, the resulting vertices ignore the origin of the HyperRectangle, resulting in result shifted by that origin :/

Float32 support

The following works fine:

HomogenousMesh(SignedDistanceField(HyperRectangle(Vec(0,0,0), Vec(1, 1, 1)), 
               randn(10, 10, 10)))

This one doesn't:

HomogenousMesh(SignedDistanceField(HyperRectangle(Vec(0,0,0), Vec(1, 1, 1)), 
        randn(Float32, 10, 10, 10)))

I get the following error:

MethodError: no method matching marchingTetrahedra(::Array{Float32,3}, ::Float64, ::Float64, ::Type{Int64})
Closest candidates are:
  marchingTetrahedra{T<:Real,IT<:Integer}(::AbstractArray{T<:Real,3}, ::T<:Real, ::T<:Real, ::Type{IT<:Integer})

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.