4
$\begingroup$

Compare the two renderings of the same point in the following code (this is just a reduced example, I know I could just zoom in the scene, it's not an option in original code):

Manipulate[Row[{
   Graphics[Point[{0, x[t]}], PlotRange -> {{-0.1, 0.1}, {-0.1, 0.3}},
     Axes -> False, ImageSize -> 10],
   Graphics3D[Point[{0, x[t], 0}], 
    PlotRange -> {{-0.1, 0.1}, {-0.1, 0.3}, All}, Boxed -> False, 
    ImageSize -> 10, ViewVector -> {0, 0, 10^4}]
   }], {t, 10, 100}, ControlPlacement -> Left, 
 Initialization :> (x[t_] = Abs@Sin[t]/t)]

The resulting two points animate like follows:

animations for comparison

Here's a magnified version of the above animation to better see what happens:

magnified version

You can see the point at left seems to move jerkily, while the one at right moves smoothly. After some time the left one stops moving, while the right one still does visibly move. This is due to antialiasing of positions, not just shape. 2D functions seem to round positions to integer screen coordinates, while 3D ones don't.

The second way with Graphics3D would be the best solution for me, but in some more complex 2D scenes the 3D engine takes too much time to render, making Manipulate unusable.

So my question is: is there any way to force 2D Graphics and functions like ListPlot antialias positions too, so that one didn't need to resort to 3D engine?

$\endgroup$
  • 1
    $\begingroup$ There is no difference. Both "vibrate" the same way. Try this to see it better Manipulate[ Row[{ Graphics[ {PointSize[Large], Point[{0, x[t]}]}, PlotRange -> {{-0.1, 0.1}, {-0.1, 1.1}}, Axes -> False, ImageSize -> 50], Graphics3D[{PointSize[Large], Point[{0, x[t], 0}]}, PlotRange -> {{-0.1, 0.1}, {-0.1, 1.1}, All}, Boxed -> False, ImageSize -> 50, ViewVector -> {0, 0, 10^4}] }], {{t, .1, "time"}, .1, 100, .1, Appearance -> "Labeled", ContinuousAction -> True}, ControlPlacement -> Left, Initialization :> ( x[t_] := Abs@Sin[t]/t ) ] $\endgroup$ – Nasser Jan 31 '16 at 10:00
  • $\begingroup$ You also defining a function use =. This should really be =:. $\endgroup$ – Nasser Jan 31 '16 at 10:08
  • 2
    $\begingroup$ @Nasser of course you don't see any difference if you enlarge the points — see my parenthesized part of the first sentence. I wasn't talking about logical positions — my question is about rasterization, which does yield different results. To see the difference, use a screen magnifier (e.g. Qt's pixeltool) on my animation. As for function definition, why should it be a delayed assignment (I guess you mean := not =:)? It doesn't make any real difference here, and in general it isn't useful to completely reevaluate an expression for each argument unless the expression is not idempotent. $\endgroup$ – Ruslan Jan 31 '16 at 11:32
  • $\begingroup$ Related question: Graphics elements do not line up perfectly in exported PDFs $\endgroup$ – ybeltukov Dec 14 '17 at 21:05
2
$\begingroup$

The obvious solution, if there's no native support for this in Mathematica, is to implement manual supersampling. Here's an example function which could do it:

antialias[img_, size_, supersampling_: 5] := ImageResize[Image[Rasterize[img,
    RasterSize -> supersampling*size], ImageSize -> supersampling*size], size]

The steps here are

  1. Rasterize, which renders the image as it should look, but in a higher resolution,
  2. Image, which creates actual image in the requested size (which Rasterize doesn't do),
  3. ImageResize, which downsamples, applying some low-pass filter to the supersampled image.

If we omit step 1, then in various Plot, ListPlot etc. we'll get wrong sizes of points and lines. Rasterize makes them look correct.

Now we can include this variant in the demo from the OP as follows (the point rendered by the new method is in the middle):

Manipulate[Row[{
   Graphics[Point[{0, x[t]}], PlotRange -> {{-0.1, 0.1}, {-0.1, 0.3}},
     Axes -> False, ImageSize -> 10],
   antialias[Graphics[Point[{0, x[t]}], PlotRange -> {{-0.1, 0.1}, {-0.1, 0.3}},
     Axes -> False, ImageSize -> 10], 10],
   Graphics3D[Point[{0, x[t], 0}], 
    PlotRange -> {{-0.1, 0.1}, {-0.1, 0.3}, All}, Boxed -> False, 
    ImageSize -> 10, ViewVector -> {0, 0, 10^4}]
   }], {t, 10, 100}, ControlPlacement -> Left, 
 Initialization :> (
   x[t_] = Abs@Sin[t]/t;
   antialias[img_, size_, supersampling_: 5] := ImageResize[
     Image[Rasterize[img, RasterSize -> supersampling*size], 
      ImageSize -> supersampling*size], size]
   )]
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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