5
$\begingroup$

I have an even function $f(x)$ that I wish to plot on the interval $x \in [-1,1]$. The evaluation of $f(x)$ at a given point takes a bit of time to compute, so I would want to evaluate $f(x)$ only on the interval $x \in [0,1]$ and plot the rest by making use of the evenness of the function. For example, if I do:

myf[x_] := (Pause[0.01]; x^2)
Show[Plot[myf[x], {x, 0, 1}], Plot[myf[x], {x, -1, 0}]],

the second plot is actually a waste.

I could manually make an array of $f(x_i)$ at different points $x_i \in [0,1]$, set $f(-x_i) = f(x_i)$ and then use ListPlot, but I feel that there should be a quicker way to do this. Ideally, something of the sort of using Plot[myf[x], {x, 0, 1}], copy it, make a mirror image of it, stick the two plots together and show the result?

$\endgroup$
1
  • $\begingroup$ things like ImageReflect will not work well, due to the axis getting in the way. Better to work with the data itself directly. $\endgroup$
    – Nasser
    Commented Jul 20, 2022 at 14:51

3 Answers 3

6
$\begingroup$

I could manually make an array of f(xi) at different points

You do not need to. Mathematica's Plot does it for you and it is better at sampling at the right places. (adaptive sampling).

How about getting the data points from one half of the plot, and just add minus to each x coordinate?

something like

myf[x_] := x^2
(*read the data from one half only *)
data = Catenate@Cases[Plot[myf[x], {x, 0, 1}], Line[data_] :> data, Infinity];

(*flip the x coordinates*)
data2 = Map[{-First@#, Last@#} &, data];

(*plot both*)
Show[ListLinePlot[data], ListLinePlot[data2], PlotRange -> All]

Mathematica graphics

You can see it is the same points used, but one half is flipped

Show[ListLinePlot[data, Mesh -> All, MeshStyle -> Red], 
 ListLinePlot[data2, Mesh -> All, MeshStyle -> Blue], 
 PlotRange -> All]

Mathematica graphics

For an odd

data2=Map[{-First@#,-Last@#}&,data];
Show[ListLinePlot[data],ListLinePlot[data2],PlotRange->All]

Mathematica graphics

$\endgroup$
1
  • $\begingroup$ Nice! How do you modify the first part for a 2D function $f(x,y)$? $\endgroup$
    – Patrick.B
    Commented Jul 20, 2022 at 15:16
2
$\begingroup$

To complete Nasser's answer, the below shows how to extend the method for a 3D plot, which is inspired by an answer to a different question. Specifically, if $f(x,y)$ is an even function of $x$, then

(* plot f(x,y) for positive x only *)
myplot = Plot3D[x^2 Sin[y], {x, 0, 1}, {y, -\[Pi]/2, \[Pi]/2}];
(* read the data *)
data = FirstCase[myplot, GraphicsComplex[p_, __] :> p, {}, -4];
(* flip x coordinate *)
data2 = Map[{-#[[1]], #[[2]], #[[3]]} &, data];
(* plot both data together *)
Show[ListPlot3D[data], ListPlot3D[data2]]
$\endgroup$
1
  • 1
    $\begingroup$ This is doing too much work. You extract points out of the GraphicsComplex[], only to feed them again into another plotting function that would regenerate a GraphicsComplex[]. $\endgroup$ Commented Jul 20, 2022 at 16:06
2
$\begingroup$

When plotting 3D surfaces with symmetries, it is sometimes convenient to use GeometricTransformation[] with an appropriate choice of ScalingTransform[]. Using the OP's example of a bivariate function with odd and even symmetries:

p1 = Plot3D[x^2 Sin[y], {x, 0, 1}, {y, 0, π/2}];
Graphics3D[GeometricTransformation[First[p1], 
           Table[ScalingTransform[s],
                 {s, {{1, 1, 1}, {-1, 1, 1}, {1, -1, -1}, {-1, -1, -1}}}]], 
           Axes -> Automatic, BoxRatios -> {1, 1, 0.4}]

a function with odd and even symmetries


The OP's original parabola example can be treated similarly:

para = Plot[x^2, {x, 0, 1}];
Graphics[GeometricTransformation[First[para],
         Table[{DiagonalMatrix[s], {0, 0}}, {s, {{1, 1}, {-1, 1}}}]], 
         Axes -> Automatic]
$\endgroup$

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.