How can I use legend in ContourPlot3D and add arrowheads for axis?
Try this:
sf1[x_, y_, z_] := x (1/(1 + 0.06))^3 + y (1/(1 + 0.06))^2 - z/3;
sf2[x_, y_, z_] :=
x (1 + 5 0.06) (1/((1 + 5 0.06) + 0.06))^3 +
y (1 + 5 0.06) (1/((1 + 5 0.06) + 0.06))^2 - z/3;
Show[{
ContourPlot3D[{sf1[x, y, z] == 0, sf2[x, y, z] == 0}, {x, 0,
150}, {y, 0, 100}, {z, 0, 200}, Ticks -> None,
BoundaryStyle -> Red, Boxed -> False, AxesOrigin -> {0, 0, 0}],
Graphics3D[{Red, Thickness[0.005], Arrowheads[0.03],
Arrow[{{0, 0, 0}, {153, 0, 0}}], Arrow[{{0, 0, 0}, {0, 0, 203}}],
Arrow[{{0, 0, 0}, {0, 102, 0}}]}],
Graphics3D[{Text[
Style["x", 18, Italic, Bold,
FontFamily -> "Times New Roman"], {149, 0, 16}],
Text[Style["y", 18, Italic, Bold,
FontFamily -> "Times New Roman"], {0, 96, 22}],
Text[Style["z", 18, Italic, Bold,
FontFamily -> "Times New Roman"], {0, 0, 215}]}]
}]
It should give this:
With another ViewPoint though. I turned a bit to make the y axis visible.
Have fun!
Edit: to address your question. I also did not succeed to use the Epilog->Inset
structure for this purpose. However, you may simply draw the necessary objects "by hand" the same way as the axes and labels were drawn. Try this:
Show[{ContourPlot3D[{sf1[x, y, z] == 0, sf2[x, y, z] == 0}, {x, 0,
150}, {y, 0, 100}, {z, 0, 200}, Ticks -> None,
BoundaryStyle -> Red, Boxed -> False, AxesOrigin -> {0, 0, 0},
ViewPoint -> {1.54, -2.77, 1.19}],
Graphics3D[{Red, Thickness[0.005], Arrowheads[0.03],
Arrow[{{0, 0, 0}, {153, 0, 0}}], Arrow[{{0, 0, 0}, {0, 0, 203}}],
Arrow[{{0, 0, 0}, {0, 102, 0}}]}],
Graphics3D[{Text[
Style["x", 18, Italic, Bold,
FontFamily -> "Times New Roman"], {149, 0, 16}],
Text[Style["y", 18, Italic, Bold,
FontFamily -> "Times New Roman"], {0, 96, 22}],
Text[Style["z", 18, Italic, Bold,
FontFamily -> "Times New Roman"], {0, 0, 215}],
Text[Style["b=0", 20, Darker@Brown], {20, 20, 180}],
Text[Style["b=5", 20, Darker@Blue], {83, 47, 128}]
}],
Graphics3D[{Arrowheads[0.03], Thickness[0.005],
Arrow[{{20, 20, 173}, {25, 25, 129}}],
Arrow[{{83, 47, 132}, {74, 34, 188}}]}]
}]
you should obtain the following:
The advantage is that bot the letters and arrows are 3D objects and you may rotate the image to visualize, say, where the second arrow points to. If the image rotation is not necessary, you may think about playing with the coordinates and placing the text b=5
and the corresponding arrow into another position, where the arrow is more visible.
Have fun!
Modifying the function axes
in this answer:
axes3D[x_, y_, z_, f_, a_] := With[{min = Min[x, y, z]},
Graphics3D[Join[{Arrowheads[a]}, Arrow[{{0, 0, 0}, #}] & /@ {{x, 0, 0}, {0, y, 0}, {0, 0, z}},
Text[Style[#, FontSize -> Scaled[f]], #2] & @@@
Transpose[{{"x", "y", "z"}, {{x/2, 0, 0}, {0, y/2, 0}, {0, 0, z/2}} /. (0) -> (-.05 min)}]],
Boxed -> False]]
cp = ContourPlot3D[{sf1[x, y, z] == 0, sf2[x, y, z] == 0}, {x, 0, 150}, {y, 0, 100}, {z, 0, 200},
BoundaryStyle -> Red, ContourStyle -> {Directive[Opacity[.8], Yellow],
Directive[Opacity[.8], Green]}, Mesh -> None,
PlotLegends -> SwatchLegend[{Yellow, Green}, {"b=0", "b=5"}]];
Show[axes3D[##&@@(Last/@ PlotRange[cp[[1]]]), .05, .03], cp, BoxRatios -> 1, Lighting -> "Neutral"]