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've recently stumbled across this site: Koalas to the Max, and the first thought that came to my mind was "I want to recreate this with Mathematica".

As a first step I tried to create a Disk that splits itself up into four disks, when the mouse cursor touches it. Those four disks should in turn split themselves up. Here's what I have so far:

makeDisks[pos_] := makeDisks[1, pos]
makeDisks[level_, pos_] :=
 Module[{
   disk = Disk[pos, 1/level]},
  Mouseover[Dynamic@disk, Dynamic[disk = makeDisks[level + 1, #] & /@ 
   (pos + # & /@ (1/(2 level)) Tuples[{-1, 1}, 2])]]
  ]

(* test with the following *)

 Graphics[{makeDisks[1]},
   PlotRange -> {{-1, 1}, {-1, 1}}]

For the first disk this seems to work just as I want it. For later steps, however, I got the positioning wrong and some of the disks go back to larger ones, when another one is touched. How can these issues be fixed?

As a next step I want to add colors to the disks. Maybe this can be done by using MapIndexed with makeDisks on the ImageData of some image. The colors in each step should probably be the mean values of appropriate subsets of the image data.

Any help to move this little program forward is highly appreciated!

share|improve this question

2 Answers 2

up vote 19 down vote accepted

Here's a simple way using buttons, for some reason AutoAction is not working so you have to click, anyone know why?

nextPos[p_, r_] := {p + # r/2, r/2} & /@ Tuples[{1, -1}, 2]

DynamicModule[{diskList = {{ {0, 0}, 1}}},
 Graphics[Dynamic[
   Button[{ColorData["Rainbow"][Last@#], Disk @@ #},
      diskList = DeleteCases[Join[diskList, nextPos @@ #], #]
      ,AutoAction -> True
      ] & /@ diskList]]
 ]

circles

The coloring is only based on depth (radius)

Basing color on underlying image:

background = ImageCrop[ExampleData[{"TestImage", "Peppers"}], AspectRatio -> 1];

DynamicModule[{diskList = {{{0, 0}, 1}}}, Graphics[Dynamic[
   Button[{RGBColor@ImageValue[background,First@#, DataRange -> {{-1, 1}, {-1, 1}}],
       Disk @@ #} 
     ,diskList = DeleteCases[Join[diskList, nextPos @@ #], #]
     ,AutoAction -> True] & /@ diskList]]]

pepper

Using code from @Szabolcs comment it's possible to split the disks without clicking:

(* Create at most 2^6=64 disks in a row *) 
rmin = 2^-6;
DynamicModule[{diskList = {{{0., 0.}, 1.}}}, Graphics[Dynamic[
  EventHandler[{RGBColor@ImageValue[background, First@#, DataRange -> {{-1, 1}, {-1, 1}}], 
                Disk @@ #}
    ,{"MouseMoved" :>
      If[Last@# > rmin, diskList =DeleteCases[Join[diskList, nextPos @@ #], #]]}
   ] & /@ diskList]]
]
share|improve this answer
    
(+1) AutoAction doesn't work here either. But even if it did, wouldn't it trigger a split on every move? In the original, a split is only triggered when the mouse moves into a disk the first time (but not when the mouse happens to be over a newly generated disk) –  Szabolcs Feb 19 '13 at 17:08
    
@Szabolcs Indeed, potentially it would also create a crazy amount of disks, so would need some minimum r limit –  ssch Feb 19 '13 at 17:13
    
I mean, this would happen: DynamicModule[{diskList = {{{0, 0}, 1}}}, Graphics[Dynamic[ EventHandler[{ColorData["Rainbow"][Last@#], Disk @@ #}, {"MouseMoved" :> (diskList = DeleteCases[Join[diskList, nextPos @@ #], #])}] & /@ diskList]]] –  Szabolcs Feb 19 '13 at 17:14
1  
Autoaction seems not working with Graphical Buttons. Test it Module[{i = Disk[]}, #@ Button[Dynamic@i, Dynamic[i = Rectangle[]], AutoAction -> True]] & /@ {Identity, Graphics} –  belisarius Feb 19 '13 at 17:44
2  
Sadly it gets progressively slower as the number of disks increases... –  Ajasja Feb 19 '13 at 21:03

Alternative

DynamicModule[{visited = False}, 
    Dynamic@EventHandler[
      If[visited, 
       Thread@Translate[#0@#, {1, -1}~Tuples~2]~Scale~
        0.5, {ColorData["Rainbow"]@Random[], #}], 
      "MouseEntered" :> (visited = True)]] &[Disk[]] // Graphics

Other version. Works "more or less" fine. Read comments

SetAttributes[translateOnHover, HoldFirst];
s : translateOnHover[onVar_, animationLength_, animationRate_: 200][
   prim_] := 
 With[{creationTime = Clock[Infinity]~Refresh~None}, 
  DynamicModule[{visited = False}, 
   Dynamic@If[visited, 
     With[{visitedTime = Clock[Infinity]~Refresh~None}, 
      With[{currentTime := 
         1/animationLength (Clock[{0, visitedTime + animationLength, 
              1`/animationRate}, visitedTime + animationLength, 1] - 
            visitedTime)}, 
       Thread@Translate[s, ({1, -1}~Tuples~2) /. 
           pt : {_, _} :> Dynamic[pt currentTime]]~Scale~
        Dynamic[currentTime /. t_ :> 1 - t + 0.5 t^2]]], 
     EventHandler[{ColorData["Rainbow"]@Random[], prim}, 
      "MouseEntered" :> 
       If[onVar && 
         Refresh[Clock[Infinity], None] - creationTime > 
          animationLength, visited = True]]]]]

With[{animationLength = 0.8, animationRate = 80}, 
  DynamicModule[{on = False}, 
   Column[{Row[{Button["Start", on = True, Enabled -> Dynamic[! on]], 
       Spacer[20], 
       Button["Stop", on = False, Enabled -> Dynamic[on]]}], 
     Graphics[
      translateOnHover[on, animationLength, animationRate][Disk[]], 
      ImageSize -> Medium, PlotRange -> 1.2 {{-1, 1}, {-1, 1}}]}, 
    Alignment -> Center]]] // Panel
share|improve this answer
    
Nice use of #0! –  ssch Feb 19 '13 at 19:06
    
What is MouseEntered? Is there a link somewhere to a list of undocumented EventHandler events? –  Szabolcs Feb 19 '13 at 20:23
    
@Szabolcs it is triggered when the mouse enters, there's also MouseExited. I'm trying to remember where I got that from. –  Rojo Feb 19 '13 at 20:24
1  
Re your last edit: During animations I get a lot of "shaking", it seems like the plot range may be changing rapidly. For disks next to the edge the whole plot is shaking, for others only the animated part. Do you see this too? –  Szabolcs Feb 19 '13 at 20:27
1  
@rm-rf The "shaking" is definitely not mac specific. I get it too. (Windows 7, Mma 8) –  einbandi Feb 19 '13 at 23:42

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.