7
$\begingroup$

My show is an overlay of 3 sets of countours in 3 different colours, but the countour labels are all black which makes identification problematic. I don't seem to be able to find a way to make the countour labels the same colour as their contours.

$\endgroup$
1
  • 2
    $\begingroup$ You need to post in a code block the executable code that demonstrates the problem you are trying to resolve. $\endgroup$
    – Bob Hanlon
    Mar 11, 2017 at 21:59

3 Answers 3

6
$\begingroup$
ContourPlot[
 Sin[x] Sin[y],
 {x, -3, 3}, {y, -3, 3},
 ContourStyle -> {Red, Dashed, Green},
 ContourLabels ->
  (Text[Style[#3,
      Switch[#3,
       -0.8 | -0.2 | 0.4, Red,
       -0.6 | 0 | 0.6, Black,
       -0.4 | 0.2 | 0.8, Green]],
     {#1, #2}] &),
 BaseStyle -> 18]

enter image description here

EDIT: If the pure Function using Slot designations is difficult to read, you can write this as

ContourPlot[
 Sin[x] Sin[y],
 {x, -3, 3}, {y, -3, 3}, 
 ContourStyle -> {Red, Dashed, Green}, 
 ContourLabels ->
  Function[{x, y, contourValue},
   Text[Style[contourValue,
     Switch[contourValue,
      -0.8 | -0.2 | 0.4, Red,
      -0.6 | 0 | 0.6, Black,
      -0.4 | 0.2 | 0.8, Green]],
    {x, y}]],
 BaseStyle -> 18]

EDIT 2: The default number of contour lines is nine. The contour lines will occur at function values of

lines = Module [{fmin = -1., fmax = 1., fdel},
  fdel = (fmax - fmin)/10;
  Range[fmin + fdel, fmax - fdel, fdel] // Chop]

(*  {-0.8, -0.6, -0.4, -0.2, 0, 0.2, 0.4, 0.6, 0.8}  *)

For a cycle of three colors, the groupings will be

With[{numberOfColors = 3},
 Partition[lines, numberOfColors] // Transpose]

(*  {{-0.8, -0.2, 0.4}, {-0.6, 0, 0.6}, {-0.4, 0.2, 0.8}}  *)

This will obviously change for different function ranges, number of contours, and number of colors.

$\endgroup$
5
  • $\begingroup$ Nice, and one could change that Switch to take the ColorData of the underlying contour plot too. Might need a Lighter@* on it too so it doesn't wholly blend in I guess. $\endgroup$
    – b3m2a1
    Mar 12, 2017 at 16:27
  • $\begingroup$ Great. That code worked pasted in and does more than I need. Sorry I don't understand it enough to modify it to just do the contours all in Red and the contour labels in Red too as I want with my function.It is the # stuff I don't get, Simon $\endgroup$
    – simon
    Mar 12, 2017 at 21:21
  • $\begingroup$ @simon - look at the documentation for Function and Slot. Links include in edit above. $\endgroup$
    – Bob Hanlon
    Mar 12, 2017 at 23:01
  • $\begingroup$ I entertained this approach but I do not see how to find the values -0.8 | -0.2 | 0.4 etc. robustly, without turning to post-processing again. Any ideas? $\endgroup$
    – Mr.Wizard
    Mar 13, 2017 at 4:49
  • $\begingroup$ @Mr.Wizard - this approach is not particularly robust but tailoring is straightforward. $\endgroup$
    – Bob Hanlon
    Mar 13, 2017 at 5:42
5
$\begingroup$

Another way to use post-processing is to take advantage of the Tooltips that are automatically generated by ContourPlot when the option ContourLabels is not used:

addColoredLabels = # /. 
    Tooltip[{x___, l : Line[__] ..}, z_] :> {x, l, 
      Dynamic@Text[Style[z, Darker@Darker@CurrentValue["Color"]], RandomChoice[#[[1]]],
           Background -> Opacity[.5, Lighter@Lighter@CurrentValue["Color"]]] & /@ {l}} &;

Example:

addColoredLabels @ ContourPlot[Sin[x] Sin[y], {x, -3, 3}, {y, -3, 3}, 
   ContourStyle -> ColorData[3, "ColorList"], 
   BaseStyle -> {Thick, 18, Bold}, ImageSize -> 500] 

Mathematica graphics

A simpler version of that function without the arcane CurrentValue["Color"]*.

colorSimple = # /. 
    Tooltip[{x___, l__Line}, z_] :> {x, l, 
       Text[Style[z, Opacity[1]], RandomChoice @@ #] & /@ {l}} &;

enter image description here

* Is there a way to access the (lexically) current colour inside Graphics?

$\endgroup$
2
  • $\begingroup$ Nice solution! Surely safer than mine. But I think you obfuscate it too much. I am going to add a simpler version for those who have trouble following the first code. $\endgroup$
    – Mr.Wizard
    Mar 13, 2017 at 4:54
  • $\begingroup$ @Mr.Wizard, much nicer, thank you. Makes me think "what was i thinking?" $\endgroup$
    – kglr
    Mar 13, 2017 at 5:05
4
$\begingroup$

There does not appear to be any way to do this natively. Here is an attempt at a post-processing work-around:

syncCountourLabels[g : Graphics[_GraphicsComplex, ___]] :=
  Module[{text, i = 1, pos = FirstPosition[g, {__Text}]},
   (
    text = Reverse @ Extract[g, pos];
    Delete[g, pos] /. x_Line :> {x, {Opacity[1], text[[i++]]}}
    ) /; pos =!= Missing["NotFound"]
  ]

Example:

ContourPlot[
  Sin[x] Sin[y], {x, -3, 3}, {y, -3, 3}, 
  ContourStyle -> {Red, Dashed, Green},
  ContourLabels -> True, 
  BaseStyle -> 18
] // syncCountourLabels

enter image description here

$\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.