Skip to main content
6 of 6
added 1930 characters in body
kglr
  • 400.5k
  • 18
  • 488
  • 929

Update: As an alternative and more flexible approach, we can post-process ContourPlot output to inject contour labels.

ClearAll[addLabels]
addLabels[colors_, labels_: Automatic, threshold_: 1/3][g_Graphics] :=
  Module[{diag = ArcLength@Line[Transpose @ PlotRange @ g], 
   assoc = AssociationThread[colors, 
     labels /. Automatic -> 
       MapIndexed[Framed[Style["(" <> ToString@#2[[1]] <> ")", #, 12], 
        FrameStyle -> None, Background -> White, FrameMargins -> Small] &, colors]]}, 
  ReplaceAll[{d_Directive, l__Line} :> {d, l, 
     Module[{BSF = BSplineFunction[First@#], 
        pos = If[ArcLength[#] < diag threshold, {.5}, 
         If[Norm[Subtract @@ #[[1, {1, -1}]]] <= 
           diag threshold, {.3, .8}, {0, 1}]]}, 
       Text[assoc@FirstCase[d, _?ColorQ], #] & /@ (BSF /@ pos)] & /@ {l}}] @ Normal[g]]

addLabels[colors_, labels_: Automatic, threshold_: 1/3][Legended[g_, legend_]] := 
 Legended[addLabels[colors, labels, threshold] @ g, legend]

The first argument, colors, is a list of colors with the same length as functionlist in ContourPlot[functionlist,...].

The (optional) second argument, labels, is a list of labels with the same length (if this argument is Automatic or not provided, the labels are taken to be numbers from 1 to length of colors).

The third argument, threshold, is also optional and it is used to control the number of labels and label positions on a contour curve. If a contour curve is too short (in comparison to the length of the diagonal of the plotting area) then a single label is placed in the middle of the curve. If the start and end points of the curve not too close two labels are placed at the two ends of the curve. If they are too close (as in a closed curve) two labels are placed so that they are not too close to each other.

We can use addLabels in two ways: (1) as the the setting for the option DisplayFunction by adding the option DisplayFunction -> addLabels[colors, labels, threshold] to ContourPlot, or (2) by wrapping ContourPlot[...] with it, i.e., using addLabels[colors, labels, threshold] @ ContourPlot[...].

Examples:

{g1, g2, b} = {x + 2 y, 2 x + y, {2, 2}};

funcs = {g1 - b[[1]], g2 - b[[2]]};

colors = {Blue, Magenta};

options = {Frame -> False, Axes -> True, ContourShading -> None, 
   ImageSize -> 400, PlotRangePadding -> Scaled[.05]};

ContourPlot[funcs, {x, -2, 4}, {y, -2, 4}, 
 Evaluate @ options, 
 ContourStyle -> Thread[Directive[colors, Thick]], 
 DisplayFunction -> addLabels[colors]]

enter image description here

addLabels[colors] @ ContourPlot[funcs, {x, -2, 4}, {y, -2, 4}, 
     Evaluate @ options, ContourStyle -> Thread[Directive[colors, Thick]]]
 same picture

With

funcs = {g1 - b[[1]], g2 - b[[2]], Cos[x - 1] + Cos[y - 1] - 1/3, 
   Sin[ x - 1] + x y Cos[y + 1] - 1/4};

colors = {Blue, Magenta, Red, Green};

we get

enter image description here

We can use the second argument of addLabels to inject pre-specified labels instead of automatically generated ones:

labels = MapIndexed[Framed[Style["(" <> ToString@#2[[1]] <> ")", #, Bold, 18], 
     FrameStyle -> None, Background -> White] &, colors];

ContourPlot[funcs, {x, -2, 4}, {y, -2, 4},
 Evaluate @ options,
 ContourStyle -> Thread[Directive[colors, Thick]], 
 DisplayFunction -> addLabels[colors, labels]]

enter image description here

Add the option PlotLegends->"Expressions" to get

enter image description here

Original answer:

{g1, g2, b} = {x + 2 y, 2 x + y, {2, 2}};

colors = {Blue, Magenta};

labels = MapIndexed[Framed[Style["(" <> ToString@#2[[1]] <> ")", #, 18], 
     FrameStyle -> None, Background -> White] &, colors];

Show[MapThread[
      ContourPlot[#, {x, -2, 4}, {y, -2, 4}, 
         Frame -> False, 
         Axes -> True,
         ContourShading -> None, 
         Contours -> {0}, 
         ContourStyle -> Directive[#2, Thick], 
         ContourLabels -> Function[{x, y, z}, Text[#3, {x, y}]], 
         ImageSize -> 400] &, 
      {{g1 - b[[1]], g2 - b[[2]]}, colors, labels}]] 

enter image description here

kglr
  • 400.5k
  • 18
  • 488
  • 929