Message Boards Message Boards

GROUPS:

Why does RegionDifference fail with crescent polygon (V10)?

Posted 1 month ago
262 Views
|
7 Replies
|
3 Total Likes
|

RegionDifference polygons

I’m trying to create a difference region by finding the difference between a rectangle and a crescent shape (fig. [a]) created by modifying Bezier data for a circle. The crescent is a polygon based on points created with BezierFunction[]. The goal is to use the difference region to mask out images of lines such as the diagonal where it extends beyond the border of the crescent in figure [a]. In a previous project, I was successful with RegionDifference[rectangle, disc] and RegionDifference[polygon, polygon] using simple polygons defined by three and four points as in figure [c], but using the crescent polygon as a region I fail with RegionDifference[polygon, polygon] and RegionDifference[polygon, rectangle] with the arguments in any order. Figure [b] provides an example. The error message is

{RegionDifference[Polygon[(…)],Polygon[(<<1>>)]]} is not a valid region to plot. >>

It seems that RegionDifference[] does not accept the list of points for the crescent as the basis for a valid Polygon[] region. The list appears to be uncomplicated. I would like to know why and find a solution.

Mathematica 10.0.0.0 OS 10.9.5

sz = 1.5; (* rect corner dimension *)

c = 0.551915024494; (* Bezier constant for circle *)

bz = {{0, 1}, {c, 1}, {1, c}, {1, 0}}; (* Bezier control points *)

bzF = BezierFunction[bz];

bzFPts = Table[bzF[t], {t, 0, 1, .1}];

crescentPts = AppendTo[bzFPts, bzFPts[[1]]];

(* illustrate the crescent with figure and ground
   but without RegionDifference[] *)

crescentPolygon = {EdgeForm@Black, FaceForm@White, 
   Polygon[crescentPts]};

background = {EdgeForm@Black, FaceForm@LightGray, 
   Rectangle[{-sz, -sz}, {sz, sz}]};

figure = Line[{{-1, -1}, {1, 1}}];

g1 = Graphics[{background, crescentPolygon, figure, 
    Text["[a]", {-.75, .75}]}, ImageSize -> {100, 100}];

(* RegionDifference between gray background and white crescent *)

rectanglePts = {{-sz, -sz}, {-sz, sz}, {sz, 
    sz}, {sz, -sz}, {-sz, -sz}};

regionDiffCrescent = First@RegionPlot@RegionDifference[
     Polygon@rectanglePts,
     Polygon@crescentPts
     ]; 

(* remove the default directives from new region *)

maskCrescent = DeleteCases[regionDiffCrescent, _Directive, -1]; 

g2 = Graphics[{figure, FaceForm@LightGray, maskCrescent, 
    Text["[b]", {-.75, .75}]}, 
   ImageSize -> {100, 100}];

(* region diff with triangle works properly *)

regionDiffTriangle = First@RegionPlot@RegionDifference[
     Polygon@rectanglePts,
     Polygon@{{-1, 0}, {0, 1}, {1, 0}, {-1, 0}}];

maskTriangle = DeleteCases[regionDiffTriangle, _Directive, -1]; 

g3 = Graphics[{figure, FaceForm@LightGray, maskTriangle, 
    Text["[c]", {-.75, .75}]}, 
   ImageSize -> {100, 100}];

Show[GraphicsRow[{g1, g2, g3}, Background -> White]]
7 Replies

If you have version 12 you can try out the new "polygon with holes" feature:

Graphics[Polygon[{{0, 0}, {1, 0}, {1, 1}, {0, 1}} -> 
   crescentPolygon[[3, 1]]]]
Posted 1 month ago

The new feature is good to know about, but I'm still using version 10. Can one conclude that DifferenceRegion also fails with these Bezier data in version 12?

Your code gives no error on my system. Can you give a piece of code that does not work?

Posted 1 month ago

The requested piece of code is the code for g2 which produced figure [b]. Does my code produce in your system a figure [b] with a white crescent with a diagonal line through it as in the triangle in figure [c]? If so, then I would conclude that the problem is the MMA 10 rather than with the code. I have isolated the code for figure [b].

sz = 1.5; (* rect corner dimension *)

c = 0.551915024494; (* Bezier constant for circle *)

bz = {{0, 1}, {c, 1}, {1, c}, {1, 0}};(* Bezier control points *)

bzF = BezierFunction@bz;

bzFPts = Table[bzF[t], {t, 0, 1, .1}];

crescentPts = AppendTo[bzFPts, bzFPts[[1]]];

figure = Line[{{-1, -1}, {1, 1}}];

rectanglePts = {{-sz, -sz}, {-sz, sz}, {sz, 
    sz}, {sz, -sz}, {-sz, -sz}};

(* error message generated here *)

regionDiffCrescent = First@RegionPlot@RegionDifference[
     Polygon@rectanglePts,
     Polygon@crescentPts
     ] ;

(* remove the default directives from new region *)

maskCrescent = DeleteCases[regionDiffCrescent, _Directive, -1]; 

g2 = Graphics[{figure, FaceForm@LightGray, maskCrescent, 
   Text["[b]", {-.75, .75}]}, ImageSize -> {100, 100}] 

On my system your maskCrescent is not really a mask with the crescent as a hole. It is a superposition of polygons that covers the whole of the square. I don't know what happens in version 10. I suspect that something goes wrong when we convert a Region with a hole into graphics primitives with RegionPlot. I get quite different pictures from the following inputs:

RegionDifference[Polygon@rectanglePts, Polygon@crescentPts]
RegionPlot@%

On my system the whole problem somehow goes away if I insert DiscretizeRegion before RegionPlot:

regionDiffCrescent = 
  First@RegionPlot@
    DiscretizeRegion@
     RegionDifference[Polygon@rectanglePts, Polygon@crescentPts];
Posted 1 month ago

That did the trick for me, too. I wonder exactly what DiscretizeRegion is doing to the RegionPlot object. To sum up, I'm guessing that native objects like Disk and Rectangle and simple Polygons have DiscretizeRegion somehow built in, but a Polygon construction with more complex data needs to be discretized. I include the revised figure.

enter image description here

Posted 1 month ago

This link is relevant:

Wolfram DiscretizeGraphics

Reply to this discussion
Community posts can be styled and formatted using the Markdown syntax.
Reply Preview
Attachments
Remove
or Discard

Group Abstract Group Abstract