3
$\begingroup$

Good morning. I have two equations (or more) that I want plot with ContourPlot colored with different colours and labelled according to equation order, in a automatic way. I have tried several solutions without success. My plot should remain as

g1 = x + 2 y; g2 = 2 x + y; b = {2, 2};
grosor = Thickness[0.01];
color3 = Blue;
color4 = Magenta;

coloresRest = {Blue, Magenta}; 
labelRest = Table[Text[Style["(" <> ToString@i <> ")", coloresRest[[i]]]], 
 {i, Length@coloresRest}];

ContourPlot[{g1 == b[[1]], g2 == b[[2]]}, {x, -2, 4}, {y, -2, 4}, 
  Frame -> False, Axes -> True, 
  ContourStyle -> Thread[{coloresRest, grosor}], 
  Epilog -> {Text[Style["(1)", color3], Offset[{20, 0}, {-2, 2}]], 
     Text[Style["(2)", color4], Offset[{-10, -10}, {-1, 4}]]}, 
  ImageSize -> 400]

enter image description here

I have tried with Table, ContourLabel, Riffle or Epilog, without success. For example:

ContourPlot[{g1 == b[[1]], g2 == b[[2]]}, {x, -2, 4}, {y, -2, 4}, 
  Frame -> False, Axes -> True, 
  ContourStyle -> Thread[{coloresRest, grosor}], 
  ContourLabels -> Table[Text[Style[labelRest[[i]], Offset[{10, 0}, {#1, #2} &]]], 
   {i, 1, Length@coloresRest}], 
  ImageSize -> 400]

or

ContourPlot[{g1 == b[[1]], g2 == b[[2]]}, {x, -2, 4}, {y, -2, 4}, 
  Frame -> False, Axes -> True, 
  ContourStyle -> Thread[{coloresRest, grosor}], 
  ContourLabels -> {Riffle[coloresRest, Inset[labelRest, Offset[{10, 0}, {#1, #2} &]]]}, 
  ImageSize -> 400]

I realize that expresión {#1, #2}& yield coordinates for labels, chosen by Mathematica. I'd prefer that and not to choose such coordinates.

Thank in advance


Sorry, but I forgot that

grosor=Thickness[0.01]
color3=Blue
color4=Magenta

and I prefer that Mathematida choose coordenates of label with {#1, #2} & instruction.

Thank

$\endgroup$
1

1 Answer 1

6
$\begingroup$

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

$\endgroup$
1
  • $\begingroup$ Thank you so much. This program and their users are incredible. I will have to study carefully the answer, I like. $\endgroup$
    – user81835
    Sep 14, 2021 at 10:12

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.