6
$\begingroup$

I don't think there's a built in "RegionSimplify" for polyhedral Regions and derived akin to how Interval automatically simplifies its argument expression:

Interval[{0, 1}, {1, 2}]

and

Interval[{0, 1}]~IntervalUnion~Interval[{1, 2}]

yield

Interval[{0, 2}]

In contrast, RegionUnion remains unevaluated, even in 2D:

Line[{{0, 0}, {1, 0}}]~ RegionUnion ~ Line[{{1, 0}, {2, 0}}]

(* RegionUnion[Line[{{0, 0}, {1, 0}}], Line[{{1, 0}, {2, 0}}]] *) 

From

Rectangle[{0, 0}, {1, 1}] ~ RegionUnion ~ 
  Rectangle[{1, 0}, {2, 1}] // RegionBoundary // DiscretizeRegion

enter image description here

As expected, the Rectangles' common segment is not part of the output.

How to expose or compute the ideal normal form for 2D (at least) polyhedral Regions like these basic examples:

Overlapping lines:

Line[{{0, 0}, {2, 0}}]~ RegionUnion ~ Line[{{1, 0}, {3, 0}}] (* // RegionSimplify *)

(*  Line[{{0,0},{3,0}}] *)

Union of rectangles:

 Rectangle[{0, 0}, {1, 1}] ~ RegionUnion ~ 
      Rectangle[{1, 0}, {2, 1}] (* // RegionSimplify *)

(* Rectangle[{0, 0}, {2, 1}] *)

Boundary:

 Rectangle[{0, 0}, {1, 1}] ~ RegionUnion ~ 
      Rectangle[{1, 0}, {2, 1}] // RegionBoundary  (* // RegionSimplify *)

(* Line[{{0,0},{2,0},{2,1},{0,1},{0,0}}]  *)

The simplification should work for all 2D polyhedral regions including cones (which btw the current language does not support correctly):

ConicHullRegion[{{0, 0}}, {{1, 0}, {1, 1}}] ~RegionUnion ~ 
 ConicHullRegion[{{0, 0}}, {{0, 1}, {1, 1}}] (* // RegionSimplify *)

(* ConicHullRegion[{{0, 0}}, {{1, 0}, {0, 1}}] *)

For convex regions and convex-preserving operations (eg intersection) should suffice to consider the extreme set (vertices and rays), but in general regions aren't convex (and union doens't preserve it).

(Note: RegionIntersection of the same Rectangles hangs the kernel w/ msg: Last::nolast: "{} has a length of zero and no last element")

$\endgroup$

2 Answers 2

1
$\begingroup$
eps = 0.001;
repl = (z_Symbol == val_) :> 
   (val - eps/2 <= z <= val + eps/2);

r1 = Line[{{0, 0}, {1, 0}}];
r2 = Line[{{1, 0}, {2, 0}}];

r3 = ImplicitRegion[RegionMember[
     RegionUnion[r1, r2], {x, y}] //
    Simplify, {x, y}] /. repl

ImplicitRegion[(x | y) \[Element] Reals && -0.0005 <= y <= 0.0005 && 
  0 <= x <= 2, {x, y}]

r3 // DiscretizeRegion

enter image description here

r4 = Line[{{0, 0}, {2, 0}}];
r5 = Line[{{1, 0}, {3, 0}}];

r6 = ImplicitRegion[RegionMember[
     RegionUnion[r4, r5], {x, y}] //
    Simplify, {x, y}] /. repl

ImplicitRegion[(x | y) \[Element] Reals && -0.0005 <= y <= 0.0005 && 
  0 <= x <= 3, {x, y}]

r6 // DiscretizeRegion

enter image description here

r7 = Rectangle[{0, 0}, {1, 1}];
r8 = Rectangle[{1, 0}, {2, 1}];
r9 = RegionUnion[r7, r8];

RegionMember[r9, {x, y}] // Simplify

(x | y) \[Element] Reals && 0 <= x <= 2 && 0 <= y <= 1

r9 // DiscretizeRegion

enter image description here

r10 = Rectangle[{0, 0}, {1, 1}];
r11 = Rectangle[{1, 0}, {2, 1}];
r12 = RegionUnion[r10, r11];

RegionMember[r12, {x, y}] // Simplify

(x | y) \[Element] Reals && 0 <= x <= 2 && 0 <= y <= 1

r12 // DiscretizeRegion

enter image description here

n = 5;
rectangles = 
  Rectangle @@@ 
   Transpose[{RandomInteger[{0, 10}, {n, 2}], 
     RandomInteger[{11, 20}, {n, 2}]}];

Graphics[{Opacity[.25], rectangles}]

enter image description here

r13 = RegionUnion @@ rectangles;

RegionMember[r13, {x, y}]

(x | y) \[Element] 
  Reals && ((2 <= x <= 13 && 3 <= y <= 14) || (2 <= x <= 14 && 
     4 <= y <= 11) || (3 <= x <= 16 && 
     8 <= y <= 19) || (4 <= x <= 13 && 
     9 <= y <= 13) || (5 <= x <= 17 && 8 <= y <= 13))

r13 // DiscretizeRegion

enter image description here

EDIT: Example of disconnected regions

r14 = Rectangle[{0, 0}, {1, 1}];
r15 = Rectangle[{1.1, 1.1}, {1.6, 1.7}];
r16 = RegionUnion[r14, r15];

RegionMember[r16, {x, y}] // Simplify

(x | y) \[Element] 
  Reals && ((0 <= x <= 1 && 0 <= y <= 1) || (1.1 <= x <= 1.6 && 
     1.1 <= y <= 1.7))

r16 // DiscretizeRegion

enter image description here

SECOND EDIT: Additional example--regions with holes.

r1 = Rectangle[{0, 0}, {1, 1}];
r2 = Rectangle[{.25, .25}, {.5, .5}];
r3 = RegionDifference[r1, r2];
r4 = Disk[{1.5, 1.25}, .75];
r5 = Rectangle[{1.25, 1.25}, {1.75, 1.35}];
r6 = RegionDifference[r4, r5];
r7 = RegionUnion[r3, r6];

RegionMember[r7, {x, y}]

(x | y) [Element] Reals && (((-1.5 + x)^2 + (-1.25 + y)^2 <= 0.5625 && ! (1.25 <= x <= 1.75 && 1.25 <= y <= 1.35)) || (0 <= x <= 1 && 0 <= y <= 1 && ! (0.25 <= x <= 0.5 && 0.25 <= y <= 0.5)))

DiscretizeRegion[r7]

enter image description here

$\endgroup$
6
  • $\begingroup$ Did you try Union of Rectangles that isn't simply-connected? $\endgroup$ Commented Oct 5, 2014 at 17:40
  • $\begingroup$ Added example of disconnected regions. $\endgroup$
    – Bob Hanlon
    Commented Oct 5, 2014 at 18:57
  • $\begingroup$ Those components are simply connected. Try something w/ a hole in it. $\endgroup$ Commented Oct 6, 2014 at 2:54
  • $\begingroup$ Added example with regions with holes. If this is not what you want, provide a specific example of what you do want. $\endgroup$
    – Bob Hanlon
    Commented Oct 6, 2014 at 5:05
  • $\begingroup$ Your method using RegionMember and Simplify, unlike Junho's, seems robust to the more complex topologies but it doesn't yield the normal form, which is the minimal number of boundary points (for polytopes). $\endgroup$ Commented Oct 6, 2014 at 17:21
0
$\begingroup$

(version 10) I made function lastUnion , firstUnion and RectangleRegionSimplify instead of RegionSimplify. I think you might want to make RectangleRegionSimplify.

lastUnion[coo_] := 
 Flatten[Replace[SplitBy [ coo, Last], {f_, ___, l_} -> {f, l}, 1], 1]
firstUnion[coo_] := 
 Flatten[Replace[SplitBy [ coo, First], {f_, ___, l_} -> {f, l}, 1], 1]
RectangleRegionSimplify[p__] := Module[{pts, rst},
  pts = MeshPrimitives[
     BoundaryDiscretizeRegion[
      DiscretizeRegion[RegionUnion@p], MaxCellMeasure -> \[Infinity]],
      2][[1, 1]];
  rst = Append[pts, First[pts]];
  rst = N[Rationalize[Chop[rst, 10^-6]], 5];
  rst // firstUnion // lastUnion // Rationalize // N // Line
]

And I made some sample Rectangle's as Region. Rectangle is not always Region, so I randomly selected those as Region.

n = 5;
data = Transpose[{RandomInteger[{0, 10}, {n, 2}], 
    RandomInteger[{11, 20}, {n, 2}]}];
fig1 = {ColorData["Atoms", "ColorList"][[1 ;; n]], 
    Rectangle @@@ data} // Transpose;
Graphics[{EdgeForm[Gray], Opacity[0.3], fig1}]

Blockquote

I think you can check for your code with following like this.

fig2 = RectangleRegionSimplify[RegionUnion @@ Rectangle @@@ data]

Line[{{4., 8.}, {5., 8.}, {5., 5.}, {7., 5.}, {7., 1.}, {12., 1.}, {12., 3.}, {16., 3.}, {16., 5.}, {19., 5.}, {19., 14.}, {15., 14.}, {15., 19.}, {4., 19.}, {4., 8.}}]

Graphics[{%, PointSize[Large], Red, Point @@ %}]

Blockquote

Caution

RegionQ[Rectangle[{0, 0}, {1, 3}]]

True

RegionQ[Rectangle[{2, 0}, {1, 3}]]

False

$\endgroup$
4
  • $\begingroup$ Junho, it doesn't work on derived Regions, eg: Rectangle[{0, 0}, {2, 1}]~RegionUnion~ Rectangle[{1, 0}, {2, 2}]. Derived implies RegionQ[r]==True $\endgroup$ Commented Oct 1, 2014 at 16:48
  • $\begingroup$ Applying Normal to BoundaryDiscretizeRegion is still a graphic. How to extract the line representation? Also note: ...// BoundaryDiscretizeRegion // RegionBoundary outputs many points that are not corners. $\endgroup$ Commented Oct 1, 2014 at 17:06
  • $\begingroup$ as per the calendar counterexample, try rectangles whose union is not simply connected. Also, the method should work for all 2D polyhedra and derived regions. $\endgroup$ Commented Oct 3, 2014 at 2:50
  • $\begingroup$ Your method fails if the union is not simply-connected, eg this "#" shape: data2 = {{{1, 0}, {2, 6}}, {{4, 0}, {5, 1}}, {{0, 1}, {6, 2}}, {{4, 0}, {5, 6}}, {{0, 4}, {6, 5}}} with msg: There is no simple cell representation for the specified cells of the BoundaryMeshRegion... $\endgroup$ Commented Oct 6, 2014 at 17:15

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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