Proper way to Plot a single function in two different styles?

Note - this does not work since version 10

I've taken Mr. Wizard's clever trick of using Sequence and I to get both sections of the plot assigned to the same element of PlotStyle, and also used the ability of PlotStyle to take functions as well as graphics directives.

First define the functions splitplot and splitstyle:

SetAttributes[splitplot, HoldAll];
splitplot[pieces__] := Piecewise[{#}, I] & /@ Unevaluated @ pieces
splitplot[{v_, c_}] := splitplot[{v, c}, {v, ! c}]

splitstyle[styles__] := Module[{st = Directive /@ {styles}},
{{Last[st = RotateLeft @ st], #}} & ]

Usage:

  • splitplot takes pairs of {value, condition} like Piecewise, and is used as the function to be plotted.
  • There can be any number of "pieces" to the plot.
  • If only a single piece is specified, a second piece {value, Not[condition]} will be automatically added.
  • splitstyle takes style directives, which are applied to those pieces. The styles are used cyclically.
  • Each style directive can be a list like {Red, Thick}
  • The splitstyle function can itself be a member of a list, for example {Thick, splitstyle[Red, Blue]} will split the plot into red and blue parts, both of which are thick.
  • An empty list {} can be given to apply the default style with no alterations.

Simple example - apply dashing for x<0.5

Plot[{x, splitplot[{x^2, x < 0.5}]}, {x, 0, 1},
 PlotStyle -> {Thick, {Thick, splitstyle[Dashed, {}]}}]

enter image description here

Note that if the condition describes multiple unconnected regions this will generate multiple "pieces". In the plot below the condition x<2||x>4 produces two pieces, which are assigned to the first two style directives in splitstyle.

Plot[splitplot[{x, x < 2 || x > 4}, {13 x - 2 x^2 - 16, 2 < x < 4}], {x, 0, 6},
 PlotStyle -> splitstyle[Dashed, Green, Red]]

enter image description here

Multiple splitplot and splitstyle can be used in a single Plot

Plot[{splitplot[{6 - 2 x, x < 2}, {2 x - 2, x > 2}], 
  splitplot[{2 x, x < 3}, {12 - 2 x, x > 3}]}, {x, 0, 5}, 
 PlotStyle -> {splitstyle[{}, Dashed], splitstyle[Dashed, {}]}]

enter image description here


Your method already looks pretty good to me. However, since you are looking for alternatives, here is one, though honestly I'd do it the way you started for clarity and robustness.

This uses the behavior shown in this answer, then /. (ReplaceAll) to style the separate Line expressions afterward.

Piecewise is used with a default argument of I (imaginary number) which does not plot.

The replacement works on the internal format of the Graphics expression produced by Plot as described here.

Plot[
  {V^2/144`,
   Sequence[
    Piecewise[{{V^2/344`, V < 12}}, I],
    Piecewise[{{V^2/344`, V > 12}}, I]
   ]
  },
  {V, 8, 18},
  PlotRange -> {0, 1.5},
  PlotStyle -> AbsoluteThickness[3],
  GridLines -> Automatic,
  Epilog -> {Thick, Dashed, Black, Line[{{{12, 0}, {12, 2}}, {{8, 1}, {18, 1}}}]}
] /. {sty__, x_Line, y_Line} :> {sty, y, Dashed, x}

Mathematica graphics


You can use a Piecewise to combine your curve, and then use Mesh and MeshShading to specify different styles for different ranges. In the example below there is only a split at 12, so Mesh -> {{12}}.

MeshShading is then used to style the different ranges.

Plot[{(V^2/360)/0.4, 
     Piecewise[{{(V^2/860)/0.4, V < 12}, {(V^2/860)/0.4, V > 12}}]
   },
   {V, 8, 18},
   PlotRange -> {0, 1.5},
   GridLines -> Automatic, 
   Mesh -> {{12}},
   MeshShading -> {Dashed, Automatic}, 
   PlotStyle -> AbsoluteThickness[3], 
   Epilog -> {{Thick, Dashed, Black, Line[{{12, 0}, {12, 2}}]}, {Thick, 
      Dashed, Black, Line[{{8, 1}, {18, 1}}]}}
]

Exported plot

I did not manage to only make one of the curves dashed with one call.

A hackery way to do it is to create two plots, the first with a Transparent curve. I don't recommend this though, as your version is cleaner.

p1 = Plot[{1, Piecewise[{{(V^2/860)/0.4, V < 12}, {(V^2/860)/0.4, V > 12}}]},
  {V, 8, 18}, PlotRange -> {0, 1.5}, 
  PlotStyle -> {Transparent, {AbsoluteThickness[3]}}, 
  GridLines -> Automatic, Mesh -> {{12}}, 
  MeshShading -> {Dashed, Automatic}, 
  Epilog -> {{Thick, Dashed, Black, Line[{{12, 0}, {12, 2}}]}, {Thick,
      Dashed, Black, Line[{{8, 1}, {18, 1}}]}}]

p2 = Plot[(V^2/360)/0.4, {V, 8, 18}, PlotRange -> {0, 1.5}, 
  PlotStyle -> AbsoluteThickness[3]]

Show[p1, p2]

The result is the same as your output.

Tags:

Plotting