Question

How to convert a geological voxel model to brep solids or csg?


Badge

We have a geological 3D (voxel) model that contains the geological formation code for each voxel. The voxel model can be stored as csv file that contains xcoord, ycoord, zcoord and the formation code of each voxel. The x, y and z coordinates represent the voxel centers. We are able to generate a vectorized representation of each voxel cell (see image) , this is however very heavy. The goal is to create a brep solid or csg that represents all voxels containing the same formation code and sharing at least one common edge or side. These Solids may contain holes, where another formation is present. Formations may occur multiple times spatially disconnected. In this way we want to reduce the amount of elements/features and the size for visualization purposes.

Kind regards,

Philip


20 replies

Userlevel 2
Badge +17

Hi @philip_wehrens, just an idea.

  1. Decompose every voxel into individual Faces.
  2. Filter out duplicate faces with SurfaceOnSurfaceOverlayer + Tester (test if overlap count is equal to 1).
  3. Aggregate exterior boundary faces with the Aggregator and then transform the aggregate faces to a BRep Solid with the GeometryCoercer.

I think it works theoretically, but I don't know the performance could satisfy your requirement.

Badge

Thank you very much @takashi,

I tried your method. It does produce a resultfme-solid-issues.pptx. However, the size of the 3D pdf is not reduced since the BREP solid still consist of a lot of surfaces (compositesurface). I think i need to dissolve the "boundary" faces. I did this by splitting the boundary surfaces into orientation groups via the bounds extractor. I end up with 3 groups; horizontal boundary surfaces, vertical east-west and vertical north-south surfaces. I coerce them all to polygons (for the dissolver) and rotate the vertical ones into a horizontal orientation. I then dissolve per orientation and group by plane (constant x or y) and geological formation. I rotate them back to the original orientation and convert them back from polygon to face by the face replacer. Then I continue with your workflow by aggregating and coercing to brep solid. Although the result has the right amount of solids and the right geometry, plus the amount of surfaces is greatly reduced, some of the faces look really strange. These are not valid solids according to the geometry validator. Attached is a ppt showing some of the details. Do you have any more ideas how to proceed?

Userlevel 2
Badge +17

Hi @philip_wehrens,

Please try the FME Hub transformer SolidDissolver. This transformer basically aggregates the voxels and uses this aggregate to clip a bounding cube. The resulting solid is clean, but this can take a long time to finish. The transformer allows you to group the voxels by attributes.

Userlevel 2
Badge +17

Thank you very much @takashi,

I tried your method. It does produce a resultfme-solid-issues.pptx. However, the size of the 3D pdf is not reduced since the BREP solid still consist of a lot of surfaces (compositesurface). I think i need to dissolve the "boundary" faces. I did this by splitting the boundary surfaces into orientation groups via the bounds extractor. I end up with 3 groups; horizontal boundary surfaces, vertical east-west and vertical north-south surfaces. I coerce them all to polygons (for the dissolver) and rotate the vertical ones into a horizontal orientation. I then dissolve per orientation and group by plane (constant x or y) and geological formation. I rotate them back to the original orientation and convert them back from polygon to face by the face replacer. Then I continue with your workflow by aggregating and coercing to brep solid. Although the result has the right amount of solids and the right geometry, plus the amount of surfaces is greatly reduced, some of the faces look really strange. These are not valid solids according to the geometry validator. Attached is a ppt showing some of the details. Do you have any more ideas how to proceed?

How about remove excess vertices with the Generalizer (Douglas algorithm) after dissolving?

 

 

Userlevel 2
Badge +17

Thank you very much @takashi,

I tried your method. It does produce a resultfme-solid-issues.pptx. However, the size of the 3D pdf is not reduced since the BREP solid still consist of a lot of surfaces (compositesurface). I think i need to dissolve the "boundary" faces. I did this by splitting the boundary surfaces into orientation groups via the bounds extractor. I end up with 3 groups; horizontal boundary surfaces, vertical east-west and vertical north-south surfaces. I coerce them all to polygons (for the dissolver) and rotate the vertical ones into a horizontal orientation. I then dissolve per orientation and group by plane (constant x or y) and geological formation. I rotate them back to the original orientation and convert them back from polygon to face by the face replacer. Then I continue with your workflow by aggregating and coercing to brep solid. Although the result has the right amount of solids and the right geometry, plus the amount of surfaces is greatly reduced, some of the faces look really strange. These are not valid solids according to the geometry validator. Attached is a ppt showing some of the details. Do you have any more ideas how to proceed?

In fact, your attached slides doesn't describe details required to find a solution. e.g.

 

  • What issue did the GeometryValicator detect on the resulting solids?
  • Have you set the Group By parameter in the Dissolvers?
  • Aren't there some gap between adjacent vertices caused by data accuracy?

 

Badge

Hi @philip_wehrens,

Please try the FME Hub transformer SolidDissolver. This transformer basically aggregates the voxels and uses this aggregate to clip a bounding cube. The resulting solid is clean, but this can take a long time to finish. The transformer allows you to group the voxels by attributes.

Hi @DaveAtSafe,

 

The SolidDissolver was my first attempt acctually. It works really well for small datasets. I tested it without problems on 10 to 50.000 voxels. The problem is that i have more than a million voxels. After 2 days running the SolidDissolver still wasn't finished (I think its the clipper) so i terminated the process and started looking for a faster method.

 

 

Userlevel 2
Badge +17
Hi @DaveAtSafe,

 

The SolidDissolver was my first attempt acctually. It works really well for small datasets. I tested it without problems on 10 to 50.000 voxels. The problem is that i have more than a million voxels. After 2 days running the SolidDissolver still wasn't finished (I think its the clipper) so i terminated the process and started looking for a faster method.

 

 

Hi @philip_wehrens,

 

Yeah, the solid clipping is pretty slow right now. I wonder if tiling might help. Maybe try merging 100*100 voxel sets, then merging those results together.

 

Badge +2

I've created an example that splits the voxel model into layers (by elevation) and then builds a solid for each code for each layer. Not perfect, but hopefully it will reduce the overall number of solids.

I tried the SolidDissolver to try an dissolve between the layers and it was too slow.

Workspace: raster-to-voxel.fmw

I don't have a classified 3D voxel dataset, so the collapsed bookmark creates one out of a classified raster.

Userlevel 2
Badge +17

Hi @philip_wehrens, just an idea.

  1. Decompose every voxel into individual Faces.
  2. Filter out duplicate faces with SurfaceOnSurfaceOverlayer + Tester (test if overlap count is equal to 1).
  3. Aggregate exterior boundary faces with the Aggregator and then transform the aggregate faces to a BRep Solid with the GeometryCoercer.

I think it works theoretically, but I don't know the performance could satisfy your requirement.

This is an implementation example, including the original idea and process for dissolving faces for each side.

 

dissolve-adjacent-voxels.fmwt (FME 2018.0.1.1)

 

 

Badge

I've created an example that splits the voxel model into layers (by elevation) and then builds a solid for each code for each layer. Not perfect, but hopefully it will reduce the overall number of solids.

I tried the SolidDissolver to try an dissolve between the layers and it was too slow.

Workspace: raster-to-voxel.fmw

I don't have a classified 3D voxel dataset, so the collapsed bookmark creates one out of a classified raster.

Hi @MarkAtSafe,

 

 

Thanks for your help. This method we have already applied. It works well but since we end up with solids for each elevation layer we end up with a lot of solids. So, it is a valid method but not optimal for large datasets.

 

 

Badge
This is an implementation example, including the original idea and process for dissolving faces for each side.

 

dissolve-adjacent-voxels.fmwt (FME 2018.0.1.1)

 

 

Hi @takashi,

 

I tried to open your workspace, however my version is older (FME Workbench 2017.1) so some of the transformers dont work.

 

 

Badge +3
Hi @DaveAtSafe,

 

The SolidDissolver was my first attempt acctually. It works really well for small datasets. I tested it without problems on 10 to 50.000 voxels. The problem is that i have more than a million voxels. After 2 days running the SolidDissolver still wasn't finished (I think its the clipper) so i terminated the process and started looking for a faster method.

 

 

Have you tried to iterate this proces? I know that works well for the NeighborFinder, e.g. first look at the first 10m, then at 100m and last at everything else. In this case maybe you can create smaller groups at first (in a parallel proces?) and in a next (number of) step(s) expand the Solid further.

 

 

Userlevel 2
Badge +17

Hi @philip_wehrens, just an idea.

  1. Decompose every voxel into individual Faces.
  2. Filter out duplicate faces with SurfaceOnSurfaceOverlayer + Tester (test if overlap count is equal to 1).
  3. Aggregate exterior boundary faces with the Aggregator and then transform the aggregate faces to a BRep Solid with the GeometryCoercer.

I think it works theoretically, but I don't know the performance could satisfy your requirement.

Re-created with FME 2017.1.

 

b17539-dissolve-adjacent-voxels.fmwt (FME 2017.1.0.0 build 17539)

 

It works fine on a sample dataset, but may not work depending on conditions of the actual dataset.

 

 

Badge
Re-created with FME 2017.1.

 

b17539-dissolve-adjacent-voxels.fmwt (FME 2017.1.0.0 build 17539)

 

It works fine on a sample dataset, but may not work depending on conditions of the actual dataset.

 

 

Dear @takashi,

 

Thanks for workspace. The total model still takes 2 days. Also the last face replacer returns 224 features as rejected out of 485937 features. I received an request and I will send a sample dataset to SAFE so they can run some tests. I will post any solutions in this thread. Thanks again,

 

Philip

 

 

Userlevel 2
Badge +17

Hi @philip_wehrens, just an idea.

  1. Decompose every voxel into individual Faces.
  2. Filter out duplicate faces with SurfaceOnSurfaceOverlayer + Tester (test if overlap count is equal to 1).
  3. Aggregate exterior boundary faces with the Aggregator and then transform the aggregate faces to a BRep Solid with the GeometryCoercer.

I think it works theoretically, but I don't know the performance could satisfy your requirement.

That's the "depending on conditions" I mentioned.

 

If the input faces were slightly sloped against the X/Y/Z axes and/or there are tiny gaps between adjacent faces, it could have a bad influence to the processing. i.e. the dissolving process could take a long time and also resulting surfaces/solids may not be valid. I think that the feature rejection in the FaceReplacer indicates that there could be such a situation.

 

 

Badge
That's the "depending on conditions" I mentioned.

 

If the input faces were slightly sloped against the X/Y/Z axes and/or there are tiny gaps between adjacent faces, it could have a bad influence to the processing. i.e. the dissolving process could take a long time and also resulting surfaces/solids may not be valid. I think that the feature rejection in the FaceReplacer indicates that there could be such a situation.

 

 

I understand. Although that seems unlikely to me. The way i created each voxel (brepsolid) is very basic. original input are centerpoints x,y,z with rounded coordinates. I use a bufferer, extruder and offsetter to create the voxels. I convert the extruded solid to a brepsolid with the geometry coercer. I dont see any reason why the faces would be sloping or gaps would appear. Am i missing something?

 

 

Userlevel 2
Badge +17

Hi @philip_wehrens, just an idea.

  1. Decompose every voxel into individual Faces.
  2. Filter out duplicate faces with SurfaceOnSurfaceOverlayer + Tester (test if overlap count is equal to 1).
  3. Aggregate exterior boundary faces with the Aggregator and then transform the aggregate faces to a BRep Solid with the GeometryCoercer.

I think it works theoretically, but I don't know the performance could satisfy your requirement.

If the coordinate values, buffer amount, extrusion distance, offset amounts are floating point numbers, there could be unavoidable computational error, always.

 

 

Userlevel 2
Badge +17

Hi @philip_wehrens, just an idea.

  1. Decompose every voxel into individual Faces.
  2. Filter out duplicate faces with SurfaceOnSurfaceOverlayer + Tester (test if overlap count is equal to 1).
  3. Aggregate exterior boundary faces with the Aggregator and then transform the aggregate faces to a BRep Solid with the GeometryCoercer.

I think it works theoretically, but I don't know the performance could satisfy your requirement.

This square has been created by the Bufferer (Buffer Amount: 0.2, End Cap Style: None) from a point (0.1, 0.1). You can see slight error in the resulting coordinate values.

 

 

Dear @philip_wehrens​  and @Takashi Iijima​ ,

 

May I know how the geological voxel model in the image was built?

 

I would like to build a voxel model like that. Could you recommend any efficent way to do that?

 

All the best,

Jie

Badge

Hi @jievoo​ 

This is a 3D model of lithostratigraphic units (discrete values)

input: borehole data, maps and cross-sections

3D interpolation of empty 3D grid by nearest neighbour (not the most sophisticated method, but works ok)

Results in a regular grid with cells size (50x50x2 meters)

Exported are the center points of the Grid.

Kind regards,

Philip

Reply