Generating Mesh of Rotated Graphics

I have a simple geometry that consists of a few rotated rectangles

Graphics[Table[
Rotate[Rectangle[{-(1/5), .55}, {1/5, .95}], x, {0, 0}], {x, π/
8, 2 π, π/4}]]


I would like to convert this into a 2D boundary mesh. The standard workflow is the discretize the graphics elements then use ToBoundaryMesh. Or just put a RegionUnion straight into ToBoundaryMesh.

Here's what happens

DiscretizeGraphics[%]
(*EmptyRegion[2]*)


Here's a fun example that shows this issue in a bit of a simpler way

ToBoundaryMesh[Rectangle[]]
(*ElementMesh[{{0., 1.}, {0., 1.}}, Automatic]*)

ToBoundaryMesh[Rotate[Rectangle[], Pi/8]]


DiscretizeGraphics[Rectangle[]]


DiscretizeGraphics[Rotate[Rectangle[], Pi/8]]


So it seems that rotate only works when called inside Graphics? This seems to me like a bug unless im missing something. (I also tried GeometricTransformation with no luck)

My only terrible solution is this

(Graphics[
Table[Rotate[Rectangle[{-(1/5), .55}, {1/5, .95}],
x, {0, 0}], {x, π/8, 2 π, π/4}]] // Rasterize //
ColorNegate // ImageMesh // ToBoundaryMesh)["Wireframe"]


Another thing I thought I'd mention is RoundingRadius gives some very strange results.

GraphicsRow[({Graphics[#1], DiscretizeGraphics[#1],
ToElementMesh[#1]["Wireframe"]} &)[
Graphics[Rectangle[{0, 0}, {1, 1}, RoundingRadius -> .1]]]]


Or better yet, change the rectangle to default size

GraphicsRow[({Graphics[#1], DiscretizeGraphics[#1],
ToElementMesh[#1]["Wireframe"]} &)[


And while I'm talking about bugs. Has anyone else noticed that when you call RandomPolyhedra with no argumnents the UI gets mad but the code runs just fine.

Also the documentations indicates nothing about a default option.

I guess I hold Mathematica to too high a standard, but it's a shame when stiff doesn't work as expected.

• According to the documentation for Rotate, it should be possible to use Normal to obtain a version of the graphics primitive where Rotate has been replaced by a version of the graphics primitive that is rotated. But for some reason, it doesn't work for rectangles. – C. E. Nov 14 at 21:23
• Graphics[Table[Rectangle[{-1/5,.55},{1/5,.95}]//RotationTransform[x,{0,0}],{x,π/8,2 π,π/4}]]//DiscretizeGraphics works. – chyanog Nov 15 at 10:20

I think the failure to discretize your first Graphics object is a bug.

But, instead of creating graphics objects and then converting them to MeshRegion objects with DiscretizeGraphics, I think it is simpler to use Region functionality instead, since Rectangle is already a Region primitive. When working with Region primitives you need to use TransformedRegion instead of GeometricTransformation or Rotate. Then, to convert Region primitives to MeshRegion objects, you need to use DiscretizeRegion or BoundaryDiscretizeRegion.

The following rotates a rectangle and converts it into a MeshRegion object:

BoundaryDiscretizeRegion @ TransformedRegion[Rectangle[], RotationTransform[Pi/8]]


You can create your desired ElementMesh output with:

Needs["NDSolveFEM"]
mesh = ToBoundaryMesh @ BoundaryDiscretizeRegion @ RegionUnion[
Table[
TransformedRegion[Rectangle[{-(1/5), .55}, {1/5, .95}], RotationTransform[θ]],
{θ, Pi/8, 2Pi, Pi/4}
]
];
mesh["Wireframe"]


• Thanks so much this works! – user2757771 Nov 14 at 21:18
• Another solution I found is to discretize first then rotate. DiscretizeGraphics@ Table[Rotate[DiscretizeGraphics[Rectangle[{-1/6, 1/2}, {1/6, 1}]], x, {0, 0}], {x, Pi/8, 2*Pi, Pi/4}] – user2757771 Nov 15 at 6:16

As an alternative you can use BoundaryElementMeshRotate (and a few other Boolean operations) for boundary element meshes that are part of the FEMAddOns paclet. The installation of the paclet is now very easy since the installation can be done via the FEMAddOnsInstall resource function.

ResourceFunction["FEMAddOnsInstall"][]
Needs["FEMAddOns"]


Now, generate the boundary mesh for the rectangle as usual.

bmesh1 = ToBoundaryMesh[Rectangle[{-(1/5), .55}, {1/5, .95}]];


And rotate it to your hart's content:

bms = Table[
BoundaryElementMeshRotation[bmesh1, RotationMatrix[theta]], {theta,
Pi/8, 2 Pi, Pi/4}];


You can put everything in a single boundary element mesh:

bm = BoundaryElementMeshJoin @@ bms;
bm["Wireframe"]


ToElementMesh[bm]["Wireframe"]

bmesh1 = ToBoundaryMesh[Rectangle[{-(1/5), .55}, {1/5, .95}],
`