4
$\begingroup$

How can I automatically create a Disk with a certain number of segments that are differently colored automatically depending on some values I input? For example, I want a disk with seven segments of a certain size, e.g. the First segment is 40 % starting and ending at some specified angle, the second one is 40 % asf. So basically I just want to input my percentages and the colors and then the disc is created. This is similar to what PieChart does, but I want to choose the position where a segment appears manually and it should be a graphics object.

I got as far as adjusting each of the segment in an awkwardly tedious way by manually finding the right values, but got stuck finding the right values automatically based on percentages.

innerDiskSize = 1
disk = {Orange, Disk[{0, 0}, innerDiskSize, {0.007, Pi/1.77}], 
  Magenta, Disk[{0, 0}, innerDiskSize, {Pi/1.77, 7.15 Pi/7}] , Red, 
  Disk[{0, 0}, innerDiskSize, {7.15 Pi/7, 9.38 Pi/7}], Blue, 
  Disk[{0, 0}, innerDiskSize, {9.38 Pi/7, 10.12 Pi/7}], Yellow, 
  Disk[{0, 0}, innerDiskSize, {10.12 Pi/7, 10.95 Pi/7}], Brown, 
  Disk[{0, 0}, innerDiskSize, {10.95 Pi/7, 11.85 Pi/7}] , Cyan, 
  Disk[{0, 0}, innerDiskSize, {11.85 Pi/7, 14.03 Pi/7}]   }
Graphics[disk]

Any help appreciated!

$\endgroup$
6
  • $\begingroup$ Isn't this what PieChart does $\endgroup$
    – Coolwater
    Aug 13, 2017 at 10:38
  • $\begingroup$ Yes you are right, but I want to choose the positions of the segments manually $\endgroup$
    – holistic
    Aug 13, 2017 at 10:53
  • 3
    $\begingroup$ PieChart has the option SectorOrigin $\endgroup$
    – Coolwater
    Aug 13, 2017 at 10:56
  • $\begingroup$ Yes, PieChart can do this, but it needs to be a Graphics object! $\endgroup$
    – holistic
    Aug 13, 2017 at 13:20
  • $\begingroup$ Doesn't Head[PieChart[your input]] return Graphics? $\endgroup$
    – Coolwater
    Aug 13, 2017 at 13:56

3 Answers 3

7
$\begingroup$

I don't know, why PieChart wouldn't help you here. To create a 40%, 30%, 20%, 10% pie, just use

PieChart[{.4, .3, .2, .1}, SectorOrigin -> {0, 0}, PerformanceGoal -> "Speed"]

Mathematica graphics

The option PerformanceGoal->"Speed" ensures that you get a pure Graphics without any dynamic annotations. SectorOrigin helps to position make your sectors start wherever you want.

If you like to colour the sectors, use the ChartStyle option.

$\endgroup$
3
  • $\begingroup$ Thanks for the answer, but I need to embed the PieChart in a more complex Graphics object. But I figured out that I can use Inset to embed it: Graphics[{Disk[{0, 0}, 5], Inset[PieChart[{.4, .3, .2, .1}, SectorOrigin -> {0, 0}, PerformanceGoal -> "Speed"], {0, 0}, {0, 0}, 11]}] $\endgroup$
    – holistic
    Aug 13, 2017 at 17:00
  • 1
    $\begingroup$ As I said, when you use PerformanceGoal->"Speed", you get an ordinary Graphics object. So you could use for instance pie[[1]] to extract the graphics primitives and combine them inside another graphics without using inset. $\endgroup$
    – halirutan
    Aug 13, 2017 at 19:38
  • $\begingroup$ Ah, I understand now, thank you! $\endgroup$
    – holistic
    Aug 13, 2017 at 19:58
3
$\begingroup$

I have at times been quite disappointed with the performance of plotting functions, e.g. Why is ListPlot so slow here? and I have long advocated manual Graphics constructs for performance, flexibility, and reliability. Here therefore is an alternative to PieChart.

pie[
  v_?VectorQ,
  scheme_,
  ori : _?NumericQ : 0,
  opts : OptionsPattern[Graphics]
] :=
  Module[{spec, colorfn, secfn, i = 1},

    colorfn = ColorData[{scheme, {1, Length@v}}];
    secfn = {colorfn[i++], Disk[{0, 0}, 1, #]} &;
    spec = Partition[Accumulate @ Prepend[2` Pi v/Tr[v], ori], 2, 1];

    Graphics[{EdgeForm[Opacity[0.5, Black]], secfn /@ spec, Circle[]}, opts]

  ]

pie[{3, 1, 4, 1, 5, 9}, "CandyColors", Pi/2]

enter image description here

And a performance comparison:

SeedRandom[0];
dat = RandomReal[1, 700];

pie[dat, "CandyColors", Pi/2] // RepeatedTiming // First

PieChart[dat, ChartStyle -> "CandyColors", SectorOrigin -> Pi/2, 
   PerformanceGoal -> "Speed"] // RepeatedTiming // First
0.0029

0.74

More than two orders of magnitude faster than PieChart despite specifying PerformanceGoal -> "Speed". Not bad, if I do say so myself. :^)

$\endgroup$
1
  • $\begingroup$ Thank you! Very sophisticated solution ;). $\endgroup$
    – holistic
    Aug 16, 2017 at 17:47
2
$\begingroup$

By now, I found a solution by using Insetin order to embed the PieChart into a Graphics object:

Graphics[{Disk[{0, 0}, 7], 
  Inset[PieChart[{.4, .3, .2, .1}, SectorOrigin -> {0, 0}, 
    PerformanceGoal -> "Speed", ImageSize -> 100], {0, 0}, {0, 0}, 
   Automatic]}] 

What I didn't figure out yet, is how to adjust the size of the Inset such that it has the same radius as the disk. Does anyone have an idea how to do this?

$\endgroup$
2
  • 2
    $\begingroup$ Use Inset[Show[PieChart[{.4, .3, .2, .1}, SectorOrigin -> {0, 0}, PerformanceGoal -> "Speed"], PlotRangePadding -> None], {0, 0}, {0, 0}, diameter] $\endgroup$
    – Coolwater
    Aug 13, 2017 at 17:44
  • $\begingroup$ I see, thanks a bunch! $\endgroup$
    – holistic
    Aug 13, 2017 at 19:57

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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