Meshing a surface built from "skin curve" takes forever (I don't think it should). Possible bug detected also

Hi there,

I am using Trelis 17.0. I am trying to mesh an irregular (but flattish) surface for which I have a regular point cloud (it is already meshed actually!)

Here is a toy script that reproduce the issues (you may want to run until the first save in terminal version, it is much quicker this way)

import cubit
import random

# Generate rough surface from a regular mesh of sample points
listOfVertices = []
listOfCurves = []
for i in range(50):
    for j in range(50):
        randz = 0.2*(random.random()-0.5)  # Random z coordinate to mimic my data
        cubit.cmd("create vertex "+str(i)+" "+str(j)+" "+str(randz))
        listOfVertices.append(cubit.get_last_id('vertex'))
    listOfVerticesStr = " ".join(str(e) for e in listOfVertices)  # From e.g. [0,1,2] get "0 1 2"
    cubit.cmd("create curve spline location vertex "+listOfVerticesStr+" delete")
    listOfCurves.append(cubit.get_last_id('curve'))
    listOfVertices = []
listOfCurvesStr = " ".join(str(e) for e in listOfCurves) # From e.g. [0,1,2] get "0 1 2"
cubit.cmd("create surface skin curve "+listOfCurvesStr)
cubit.cmd("delete curve "+listOfCurvesStr)

# Here we have generated the rough surface...
# There is a first problem here. Let us save it first:
cubit.cmd("save trelis './example.trelis' overwrite journal")  # This weighs 3.6 Mb... looks huge to me but I can admit this 

# Let's webcut it now
cubit.cmd("webcut body 1 with plane yplane offset 45")  # Takes a lot of time... but ok
cubit.cmd("webcut body 2 with plane xplane offset 45")
cubit.cmd("delete surface 2 5")  # Delete big surfaces and keep the small one
cubit.cmd("compress")

# Alright, here we end up with a tiny slice of the initial surface, let save it to file...
cubit.cmd("save trelis './example_2.trelis' overwrite journal")  # This weighs: ...7.1 Mb!!??

# This looks like a bug, you tell me.

# Ok anyways, now let's forget this and get back to the initial surface
cubit.cmd("reset")
cubit.cmd("open './example.trelis'")  # Takes a lot of time but ok...

# Let's mesh it
cubit.cmd("surface 1 size 0.5")  # Nothing crazy here...
cubit.cmd("mesh surface 1")  # This takes ~10min and this duration evolves exponentially with the number of points used to describe the initial surface... which makes it completely intractable for any realistic purpose. I have tried other meshing schemes as well: same

# It does it eventually though... but this is not over. Working with the mesh is impossible anyways
# Checking quality metrics, for example, takes (at least) 20 min...

Is it any workaround for this? How can I get a usable mesh for my point cloud without having to use “skin curve”?

Thank you very much for your help,

Alexis
Marine Physical Laboratory
Scripps Institution of Oceanography

Hi @abottero! Your question intrigued me, because I once had a very similar project where I wrote a similar script (though in Cubit, not Trelis). I copied your script and tried running it in Trelis 17.1 and I don’t seem to have the performance issues you’ve mentioned, though I did notice a bit of a difference between my workstation and Surface Book. I put timers around some of the critical sections, see my times and intermediate results on my workstation:

image

In all, your script runs in about 21 seconds for me. This has me wondering whether an update to the recently released Trelis version 17.1 might be a solution for you.

Additional notes, I’ve noticed that setting

echo off
info off
undo off

seems to help with performance if I’m accessing Trelis over a remote connection (first two commands), while definitely helping (last command) with performance when my current directory (temp-file save location) is on a network drive.

Hi @gvernon,

Thank you for your answer! This is weird… The full script runs in ~30 min on my machine (not the least powerful one!). Maybe the problem is only in the linux version? Anyways I will update to 17.1 and check.

Thank you

@abottero

Out of curiosity, I added a loop around your code to increase the number of points from 2:100 to explore the scaling behavior of the mapped surface meshing:

image

Variates are \mathit{N} and \mathit{N}^2 where \mathit{N} is the number of univariate points and \mathit{N}^2 the total number of points used to construct the spline surface. Trendlines are quartic (blue dots) and quadratic (orange dots) polynomial fits with intercepts at 0.

I do wonder if there’s some room for improvement for your use case, I would naively assume that it would be possible to simply utilize the Bezier cells of the spline surface to build the mesh, which should (I think) avoid any need to constantly query the surface in order to place the nodes on the surface and (I think) this would be very fast.

@randy, thoughts?

Using any technique to minimize geometry queries will help on these long operations. We might want to bring @caleb or @florian into this discussion.

@gvernon are you suggesting a meshing algorithm for this specific use case, or a method to improve the speed of the python file? I’m not sure I understand.

Hi all,

Thank you so much for your help on this! I will test the version 17.1 today. Getting meshing times similar to the ones you are showing would already be a huge improvement in my case!
My final objective still looks out of reach with this strategy though (surface described by 1000x1000 points). I don’t know the workflow under the hood but I thought maybe this library could be of interest https://bufferkdtree.readthedocs.io/en/stable/
It is amazingly efficient. We used it successfully in our research to interpolate 3d functions from coarse 3d grids to fine 3d grids with millions of points.

In the meantime I came out with another strategy, stripe by stripe:

Create first line of vertices -> create spline
Create second line of vertices -> create second spline
Link splines starting points together, link end points together
Create the surface from bounding curves -> we get a stripe
Move on to the next stripe

Once all the “stripes” are created: mesh them.

This works well. The complexity looks linear. But then I end up with a patchwork of hundreds of surfaces that I can’t combine. I can create a mesh based geometry to obtain something that looks perfect but is using the Facets geometry engine so I can’t do anything with it (create volumes etc… even copying a vertex is impossible)
Note that if the stripes are united before being meshed it does not work: small curves are created and the resulting mesh is of very bad quality.

I am stuck in this dead end for days… :frowning:

I still have the solution to write the mesh by hand, linking the points four by four and then extrude them but damn…

Thank you very much

@caleb Yes, I am suggesting an algorithm for this and similar use cases.

Some of my thoughts are:

  1. Could mapped meshing of a spline surface be parallelized (CPU/GPU)? Maybe via an optional argument?
  2. Would Bezier extraction / projection be plausible and more efficient? Does it make sense to expose this in a spline-curve / spline-surface meshing algorithm?
  3. Instead of a find_closest_point() sort of method for placing the mesh nodes, could Trelis instead project along an axis or surface normal? For example, a perfectly flat rectangle (yellow) can be meshed very quickly. Imagine that we then just want to make a “copy” mesh on the green surface, where the x,y values are fixed to the yellow surface values and we just want to project in the z-direction. Would this be faster than finding the absolute closest point? One could imagine that instead of a bumpy plane, that we have a bumpy cylinder or sphere (project along surface normal in those cases)

EDIT 07/30:

As an additional comment, @caleb, I think my thought is that “mapped” surface meshing could maybe have an optional argument to utilize Bezier extraction / the underlying spline parameterization - and perhaps this might be more efficient / parallelizable.

Ok, here is what I have done to be able to do what I wanted (meshing an object including a rough surface composed of several million points).

  1. From a x y z regularly sampled point cloud use a python home made script to create an ASCII .stl file (https://en.wikipedia.org/wiki/STL_(file_format)) the geometry must formed a closed (watertight) VOLUME, if only the surface is created it will be difficult to use in Trelis (facet geometry engine). The resulting .stl file weighs several Gb.
    Remark: I have tried to import this ASCII stl to Trelis and export it to binary stl but the resulting file is not usable then (bug?).
  2. Import the .stl file to Trelis: ‘import stl file.stl feature_angle 135.00 merge’.
    This takes several hours (maybe this could be parallelized? Paraview load the same .stl in a few seconds). The volume can then be webcuted after running “set geometry engine facet” and “Set Developer Commands On”. Other volumes can be added and merged.
  3. Mesh the volumes (this is very quick now)

It would be interesting to have a built-in usable solution in Trelis to avoid having to go through an intermediary .stl file. As is, meshing the spline surfaces is completely impossible when having million of points.

Thank you very much for your help

Thanks for sharing that workflow. STL support could use a boost in Trelis, to be sure.