Skip to main content
added 805 characters in body
Source Link
Lukas Lang
  • 34.4k
  • 1
  • 56
  • 99

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.

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.

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.

Source Link
Lukas Lang
  • 34.4k
  • 1
  • 56
  • 99

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.