# How to confine the region for an object to be displayed in Graphics?

I wrote the following code as an example of my question:

 Manipulate[
Graphics[{
Red, Rectangle[{0, 0}, {5, 5}],
Blue, Translate[Disk[{1, 1}, 1], {8 cross, 1}],
Green, Rectangle[{5, 5}, {10, 0}]}
, PlotRange -> All]
, {cross, 0, 1}]


I would like to move the blue disk over the red rectangle and, when it is moved into the space of the green rectangle, it shouldn't be shown,

I used the above code to show the effect that I'm talking about, but the problem is, in my code, the blue disk is just covered by the green rectangle. It's still being drawn by the graphics expression.

How do I actually confine the plot range of the blue disk to the red region without redefining the range of the control specified by {cross, 0, 1}?

Update: Inset[] works very well :)

• Do you want simply to confine the blue circle to the red region? This could be done by restricting the value of the translation to e.g.: {8 Min[.375, cross], 1} Sep 15, 2020 at 10:46
• No, i don't want to make any change to Translate[], as i mentioned, the overall effect is shown in my code, but the Disk[] actually hides behind the green rectangle when it leaves red region, is it possible to make it not display at all if it's outside the red region.
– DORA
Sep 15, 2020 at 12:53
• In graphics[], if i define the plotrange, then the object or part of the object will not be displayed if it crosses the plotrange boundary,but i don't know how to confine an object in a finite region in Graphics
– DORA
Sep 15, 2020 at 13:00

Here's a solution using Inset:

clipRange = {{0, 5}, {0, 5}};
Manipulate[
Graphics[
{
Red, Rectangle[{0, 0}, {5, 5}],
Inset[
Graphics[
{Blue, Translate[Disk[{1, 1}, 1], {8 cross, 1}]},
PlotRange -> clipRange
],
First /@ clipRange,
ImageScaled@{0, 0},
-Subtract @@@ clipRange
],
[email protected], Green, Rectangle[{5, 5}, {10, 0}]
},
PlotRange -> All
],
{cross, 0, 1}
]


Essentially, we are creating a second Graphics with the stuff to be clipped (here the disk), and then we carefully position the Inset to occupy the correct region in the outer Graphics:

• The plot range of the inner Graphics is set to clipRange
• The position is set to the lower left corner of the clipRange
• The reference position in the inner coordinate system is set to the lower left corner with ImageScaled@{0,0} (in theory, First/@clipRange would also work, but that solution doesn't quite work with PlotRange->All and ImagePadding->Automatic)
• The size of the inset is set to the size of the clipRange

Compared to the other solutions, this has the advantage that the placement of the "clipping region" can be anywhere inside the plot range (as opposed to the GraphicsRow solution), and that there is no need to call the potentially expensive and fragile function RegionIntersection. The code can also easily be extracted into a wrapper function that can be put around arbitrary graphics primitives:

ClipObjects[prim_, clipRange_] :=
Inset[
Graphics[
prim,
PlotRange -> clipRange
],
First /@ clipRange,
ImageScaled@{0, 0},
-Subtract @@@ clipRange
]

Manipulate[
Graphics[
{
Red, Rectangle[{0, 0}, {5, 5}],
ClipObjects[
{Blue, Translate[Disk[{1, 1}, 1], {8 cross, 1}]},
{{0, 5}, {0, 5}}
],
[email protected], Green, Rectangle[{5, 5}, {10, 0}]
},
PlotRange -> All
],
{cross, 0, 1}
]
(* same output *)


This does exactly the same as the code above, but the code is nicely separated from the graphics expression.

• Thanks, Inset[] is easier to be added to my original code without too much modulation on Graphics[]
– DORA
Sep 16, 2020 at 14:42

Update I don't know how to clipping a graphics by using a closed curves in MMA. Here we using RegionIntersection to obtain the DiskSegment etc.

Clear["*"];
reg[cross_] :=
RegionPlot[
RegionIntersection[Disk[{0, 0}, 4], Disk[{1, 2.5} + {cross, 0}, 1],
PerformanceGoal -> "Quality"], PlotPoints -> 200,
PlotStyle -> Blue];
Manipulate[
Show[Graphics[{Red, Disk[{0, 0}, 4]}], reg[cross]], {cross, -5, 5}]


Original

Clear["*"];
reg[cross_] =
RegionIntersection[Rectangle[{0, 0}, {5, 5}],
Disk[{1, 2.5} + {8 cross, 0}, 1]];
Manipulate[
Graphics[{Red, Rectangle[{0, 0}, {5, 5}], Blue, reg[cross], Green,
Opacity[0.2], Rectangle[{5, 5}, {10, 0}]},
PlotRange -> All], {cross, 0, 1}]


• It went wrong when the blue disk reached the boundary between two rectangles.
– DORA
Sep 16, 2020 at 9:57
• @DORA I had fixed the problem by defined the region function outside the Manipulate Sep 16, 2020 at 10:49

I am not sure I understand what you are requesting, but here is my interpretation.

Manipulate[
GraphicsRow[
{Graphics[
{Red, Rectangle[{0, 0}, {5, 5}],
Blue, Translate[Disk[{1, 2.5}, 1], {8 cross, 0}]},
PlotRange -> {{0, 5}, {0, 5}}],
Graphics[
{FaceForm[{Green, Opacity[.6]}], Rectangle[{0, 0}, {5, 5}]},
PlotRange -> {{0, 5}, {0, 5}}]},
Spacings -> 0],
{cross, 0, 1, .1, Appearance -> "Labeled"}]


With this code you will see the blue disk get clipped as it passes through the right edge of the red rectangle. Since the green rectangle is not fully opaque, the blue disk would be visible in the green rectangle if it weren't being clipped.

• Thanks, but it's better if there's only one Graphics[].
– DORA
Sep 16, 2020 at 9:54
• @DORA. I fully agree, but this is not a simple problem, and this approach tries to solve your problem with as little change to your code as possible. Sep 16, 2020 at 14:29