14
$\begingroup$

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.

$\endgroup$
0

5 Answers 5

13
$\begingroup$

[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

$\endgroup$
2
  • $\begingroup$ Nice to see v10 functionality helping for a change. ;^) +1 $\endgroup$
    – Mr.Wizard
    Commented Jul 20, 2014 at 5:33
  • $\begingroup$ Nice update! Really clean. I think you should post that as a second answer; I'd surely vote again. $\endgroup$
    – Mr.Wizard
    Commented Aug 27, 2014 at 0:22
13
$\begingroup$

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

$\endgroup$
11
$\begingroup$

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, -∞}
  , Lighting -> {{"Ambient", White}}
  , Mesh -> False
]

enter image description here

$\endgroup$
10
$\begingroup$
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

$\endgroup$
1
  • $\begingroup$ +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. $\endgroup$
    – Mr.Wizard
    Commented Jul 20, 2014 at 5:30
3
$\begingroup$

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]

Mathematica graphics

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

$\endgroup$
0

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.