Take the 2-minute tour ×
Mathematica Stack Exchange is a question and answer site for users of Mathematica. It's 100% free, no registration required.

I have a list of functions defined on the plane, and I want to know which one of those functions is smaller than the other functions at particular points.

Currently, what I do is

Plot3D[{1 + 3/2 v, 1 + 2/3 m + 1/6 v, 9/4 + 1/8 v, 10/7 m, 
  m + Min[2/3, 1/2 m, v]}, {m, 1, 2}, {v, 0, 1}, 
 PlotStyle -> {Orange, Red, Blue, Green, Black}, ViewPoint -> Bottom]

And I get a picture like this (it is a little bit rotated because I can't view 3D plots unless I'm moving it... but that's another question)

enter image description here

I feel there must be a smarter way than doing this without invoke plotting a 3D diagram.

share|improve this question

5 Answers 5

up vote 12 down vote accepted

[Edit note: I added an alternative and then was encouraged to separate the two solutions. If you upvoted because of the second solution, feel to retract it. (Sorry.)]

Here's a V10 solution with ImplicitRegion.

fns = {1 + 3/2 v, 1 + 2/3 m + 1/6 v, 9/4 + 1/8 v, 10/7 m, m + Min[2/3, 1/2 m, v]};

rgns = Table[
   ImplicitRegion[
    Reduce[{And @@ Thread[fns[[i]] < Drop[fns, {i}]], 1 < m < 2,  0 < v < 1}, {m, v}],
    {m, v}],
   {i, Length[fns]}];

Show[MapThread[
  RegionPlot, {rgns, Thread[PlotStyle -> {Orange, Red, Blue, Green, Black}]}], 
 PlotRange -> All]

Mathematica graphics

This also will plot the regions, but I can't figure out how to style the regions:

Show[BoundaryDiscretizeRegion[#, MaxCellMeasure -> 2] & /@ rgns]

Mathematica graphics

Update: There's got to be a better way than this:

meshToGraphics[rgn_] /; RegionDimension[rgn] == 2 :=
 With[{boxes = Cases[
    ToBoxes @ BoundaryDiscretizeRegion[rgn, MaxCellMeasure -> 2],
    _GraphicsComplexBox,
    Infinity]},
  ReleaseHold@MakeExpression[GraphicsBox@boxes, StandardForm]
  ];

Show[MapThread[
  meshToGraphics[BoundaryDiscretizeRegion[#1, MaxCellMeasure -> 2]] /. p_Polygon :> {#2, p} &,
  {rgns, {Orange, Red, Blue, Green, Black}}]
 ]

Mathematica graphics

share|improve this answer
    
Nice to see v10 functionality helping for a change. ;^) +1 –  Mr.Wizard Jul 20 at 5:33
    
Nice update! Really clean. I think you should post that as a second answer; I'd surely vote again. –  Mr.Wizard Aug 27 at 0:22

In my opinion it's not a bad thing to use Plot3D for this as you offload plane intersection to the GPU.
You can get an orthogonal view like this:

Plot3D[
  {1 + 3/2 v, 1 + 2/3 m + 1/6 v, 9/4 + 1/8 v, 10/7 m, m + Min[2/3, 1/2 m, v]},
  {m, 1,2}, {v, 0, 1},
  PlotStyle -> {Orange, Red, Blue, Green, Black}, 
  ViewPoint -> {0, 0, -∞}
]

enter image description here

share|improve this answer

Late, but I wanted to show a different way of visualizing the ImplicitRegion approach shown by MichaelE2 based on a workaround I came up with here:

fns = {1 + 3/2 v, 1 + 2/3 m + 1/6 v, 9/4 + 1/8 v, 10/7 m, m + Min[2/3, 1/2 m, v]};

rgns = Table[ImplicitRegion[Reduce[{And @@ Thread[fns[[i]] < Drop[fns, {i}]], 1 < m < 2, 
      0 < v < 1}, {m, v}], {m, v}], {i, Length[fns]}];

{r1, r2, r3, r4, r5} = BoundaryDiscretizeRegion /@ rgns;

Then:

Graphics[GraphicsComplex[
    MeshCoordinates[#1], {Black, MeshCells[#1, 1], Opacity[0.6], #2, 
     MeshCells[#1, 2]}] & @@@ {{r1, Red}, {r2, Blue}, {r3, 
    Yellow}, {r4, Darker@Green}, {r5, Purple}}, Axes -> True, Frame -> True]

Mathematica graphics

share|improve this answer
flist = {1 + 3/2 v, 1 + 2/3 m + 1/6 v, 9/4 + 1/8 v, 10/7 m, m + Min[2/3, 1/2 m, v]}; 
pieceW = Piecewise[Table[{i, flist[[i]] == Min[flist]}, {i, 1, Length@flist}]];

DensityPlot

DensityPlot[pieceW, {m, 1, 2}, {v, 0, 1},  
 PlotPoints -> 200, ImageSize -> 500, 
 ColorFunction -> ({Orange, Red, Blue, Black, Green}[[#]] &), 
 ColorFunctionScaling -> False, ImagePadding -> 25]

enter image description here

ContourPlot

ContourPlot[pieceW, {m, 1, 2}, {v, 0, 1},
     PlotPoints -> 200, ImageSize -> 500, Contours -> Range[5], 
     ContourShading -> RotateRight[{Orange, Red, Blue, Black, Green}],
     ContourStyle -> {Orange, Red, Blue, Black, Green}]

enter image description here

RegionPlot

regions = And @@@ (Outer[Less, flist, flist] /. x_ < x_ :> Sequence[]);
RegionPlot[regions, {m, 1, 2}, {v, 0, 1}, ImageSize -> 500,  PlotPoints -> 100,
           PlotStyle -> {Orange, Red, Blue, Black, Green}, ImagePadding -> 25]

enter image description here

share|improve this answer
    
+1 for providing alternatives, but it's worth noting that this takes much longer to render than the code in my answer because this cannot (or at least does not) offload the work to the GPU. –  Mr.Wizard Jul 20 at 5:30

This is my second answer. I was encouraged to post this separately. There is some sense to that, as it lets the community sort out the best solution, instead of tying two solutions together.

From my answer to How to do a region plot with many functions

When m and v have Ordering[fns, 1] returns the index of the function whose value is least. By setting the contour levels between the indices, we can plot the regions indicating which function has the least value.

fns = {1 + 3/2 v, 1 + 2/3 m + 1/6 v, 9/4 + 1/8 v, 10/7 m, m + Min[2/3, 1/2 m, v]};

ContourPlot[Ordering[fns, 1], {m, 1, 2}, {v, 0, 1}, 
 Contours -> 1/2 + Range[Length@fns - 1], 
 ContourShading -> {Orange, Red, Blue, Green, Black}, 
 MaxRecursion -> 4]

To plot the regions indicating which function has the greatest value, use Ordering[fns, -1].

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.