5
$\begingroup$

I want to get the difference between the following two regions, an annulus and a crown: enter image description here enter image description here

Here's the code:

Rin = 0.75;
width = 0.25;
Rout = Rin + width;
nTriangles = 24;


basepoints = Rin*{Cos[#], Sin[#]} & /@ Range[0, 2 Pi, 2 Pi/nTriangles];
basesegments = {basepoints[[# + 1]], 
     basepoints[[Mod[# + 1, nTriangles] + 1]]} & /@ 
   Range[1, nTriangles];

triad[segment_, height_] := {segment[[1]], 
  segment[[2]], # + 
     height Normalize[#] &[(segment[[1]] + segment[[2]])/2 ]}

tiltangle = ArcCos[1];
flatsegmentsE = {{Cos[tiltangle] #[[1, 1]], 
      Cos[tiltangle] #[[1, 2]]}, {Cos[tiltangle] #[[2, 1]], 
      Cos[tiltangle] #[[2, 2]]}} & /@ 
   basesegments[[1 ;; nTriangles ;; 2]];
flatsegmentsO = {{Cos[tiltangle] #[[1, 1]], 
      Cos[tiltangle] #[[1, 2]]}, {Cos[tiltangle] #[[2, 1]], 
      Cos[tiltangle] #[[2, 2]]}} & /@ 
   basesegments[[2 ;; nTriangles ;; 2]];
triads = triad[#, width] & /@ Join[flatsegmentsE, flatsegmentsO];

flattriangles = Triangle[#] & /@ %;


(*Create a region using DiscretizerGraphics on Graphics*)
flatpicture = Graphics[flattriangles]
regiontriangles = DiscretizeGraphics[flatpicture]

regionAnnulus = 
  ImplicitRegion[x^2 + y^2 <= Rout^2 && x^2 + y^2 >= Rin^2, {x, y}];
 RegionDifference[regionAnnulus, regiontriangles];

RegionDifference works, but its output is not 'clean', which is to say there are some small hanging slivers of 'region' left at the inner tips:

enter image description here

I subsequently want to export this region as an STL file with meshing, so I need to get a clean RegionDifference product. Can someone please help?

$\endgroup$
2
  • $\begingroup$ regiontriangles seems to be undefined. $\endgroup$ – Tim Laska Jan 27 at 1:22
  • $\begingroup$ @TimLaska Fixed! $\endgroup$ – ap21 Jan 27 at 2:14
8
$\begingroup$

It looks like you have introduced non-manifold geometry into your model. I explain non-manifold in more detail in my answer here. Even full-featured CAD packages will fail to create non-manifold geometry, as shown here:

SolidWorks

We can try an approach using FEMAddOns as shown below. The FEM mesher will tend to create watertight and isotropic meshes.

(*Uncommented the following function if FEMAddOns not installed*)
(*ResourceFunction["FEMAddOnsInstall"][]*)
Needs["FEMAddOns`"];
bmeshann = 
  ToBoundaryMesh[regionAnnulus, MaxCellMeasure -> {"Length" -> .01}];
bmeshtri = 
  ToBoundaryMesh[RegionUnion @@ flattriangles, 
   MaxCellMeasure -> {"Length" -> .001}];
bmesh = BoundaryElementMeshDifference[bmeshann, bmeshtri];
mesh = ToElementMesh[bmesh, "MeshOrder" -> 1];
mesh["Wireframe"]
FindMeshDefects[MeshRegion[mesh]]

Tiny Faces

As you can see, FindMeshDefects finds many tiny faces on the inner ring.

We can mitigate the problem by adding a small margin to the inner radius of the annulus.

regionAnnulus = 
  ImplicitRegion[
   x^2 + y^2 <= Rout^2 && x^2 + y^2 >= (1.005 Rin)^2, {x, y}];
bmeshann = 
  ToBoundaryMesh[regionAnnulus, MaxCellMeasure -> {"Length" -> .1}];
bmeshtri = 
  ToBoundaryMesh[RegionUnion @@ flattriangles, 
   MaxCellMeasure -> {"Length" -> .01}];
bmesh = BoundaryElementMeshDifference[bmeshann, bmeshtri];
mesh = ToElementMesh[bmesh, "MeshOrder" -> 1];
mesh["Wireframe"]
FindMeshDefects[MeshRegion[mesh]]

Inner radius margin

By adding the margin to the inner radius, we have eliminated errors detected by FindMeshDefects.

Conversion to a 3D object using RegionProduct

If there is a desire to extrude the 2D mesh into a 3D object, one could use RegionProduct to accomplish this task as shown in the following workflow:

(*Tensor product mesh from:https://wolfram.com/xid/0rs5ccudm-eqv31q*)
pointsToMesh[data_] := 
  MeshRegion[Transpose[{data}], 
   Line@Table[{i, i + 1}, {i, Length[data] - 1}]];
rv = pointsToMesh[Subdivide[0, 1, 1]];
SetDirectory[NotebookDirectory[]];
Export["test.stl", RegionProduct[MeshRegion[mesh], rv]];
stl = Import["test.stl"];
bm1 = ToBoundaryMesh[stl];
(*Color surfaces by feature angle*)
groups = bm1["BoundaryElementMarkerUnion"];
temp = Most[Range[0, 1, 1/(Length[groups])]];
colors = ColorData["BrightBands"][#] & /@ temp;
bm1["Wireframe"["MeshElementStyle" -> FaceForm /@ colors, 
  PlotRange -> {{-1.5, 1.5}, {0, 1.5}, {-1.2, 1.2}}]]
FindMeshDefects[MeshRegion[bm1]]

3D extruded mesh

$\endgroup$
3
  • $\begingroup$ Tim, you may have switched the 2D triangulated mesh images. It seems a bit odd that the first displayed triangulated mesh should have tiny faces at the tip but the second mesh might very well have this issue. $\endgroup$ – user21 Jan 28 at 10:06
  • $\begingroup$ @user21 I will look into it shortly. Thanks! $\endgroup$ – Tim Laska Jan 29 at 4:13
  • $\begingroup$ my mistake, I now see what you mean. When I looked at this I did not see the tiny tringles at the inner tips. Thanks for clarifying this. $\endgroup$ – user21 Feb 5 at 5:23
4
$\begingroup$

This is nothing compared to @Tim Laska's detailed answer above, but I found that a quickfire way of removing the small slivers from the geometry was to use the option MaxCellMeasure -> Infinity while turning the region into a mesh, as such:

mr = DiscretizeRegion[regionCones, MaxCellMeasure -> Infinity]

giving me

enter image description here

This works probably because the slivers are small, and setting a large value for MaxCellMeasure forces the meshing algorithm to ignore them. I don't expect this to work for generic non-manifold geometry. For that, refer to @Tim Laska's answer above.

$\endgroup$
1
  • $\begingroup$ Clever! I tried a number of MaxCellMeasures, but it did not occur to me to try Infinity. I also agree with you that you'll want to try to avoid non-manifold geometry whenever possible. $\endgroup$ – Tim Laska Feb 2 at 3:12

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.