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.

Help me please.

Task: Disk movement inside the Ellipse so that naturally Disk reflected from the walls and continued to move.

Thanks.

My friend was able make a move on the square only:

x = 0.5;
y = 0.5;

vx = 1;
vy = Pi/2;

step = 0.01;
radius = 0.05;

Animate[

 x = x + vx*step;
 y = y + vy*step;


 If[Abs[x - 1] <= radius || Abs[x] <= radius , vx = -vx];
 If[Abs[y - 1] <= radius || Abs[y] <= radius, vy = -vy];

 Graphics[
  {
   Cyan,
   Rectangle[{0, 0}, {1, 1}],
   Gray,
   Disk[{x, y}, radius],
    Point[{0.0, 0.0}], 
   Point[{1.0, 1.0}]
   }
  ],

 {t, 0, Infinity}

 ]

P.S. Sorry for my bad english =)

share|improve this question
add comment

2 Answers 2

up vote 8 down vote accepted

Unfortunately I don't have time to explain now. But take a look at wikipedia ellips site, tangent line part especially.

DynamicModule[{u = 0, t0, imp, v1, x0 = {0, .49}, v0 = {.5, -1.0}, t, a = 1, b = .5, 
              c, f1, f2},
 DynamicWrapper[
  Graphics[{ Thick, Scale[Circle[], {a, b}], AbsolutePointSize@7, Dynamic@Point[x0],
             Dashed, Thin, Dynamic@Line[{{x0, imp}, {imp, imp + Normalize@v1}, 
                                         {imp - normal, imp + normal}}]
           }, PlotRange -> 1.1, ImageSize -> 500, Frame -> True],
  Refresh[
    If[(#/a)^2 + (#2/b)^2 & @@ x0 < 1,
       x0 += v0;,
       x0 = imp + v1; v0 = v1; rec]
    , TrackedSymbols :> {}, UpdateInterval -> .001]]
  ,
  Initialization :> (
    c = Sqrt[a^2 - b^2]; v0 = Normalize[v0]/100; f1 = {-c, 0}; f2 = {c, 0};

    rec := ({t0, imp} = {t, x0 + t v0
               } /. Quiet@NSolve[(#/a)^2 + (#2/b)^2 & @@ (x0 + t v0) == 1. && 
                                  t > 0, t, Reals][[1]];
    normal = Normalize[Normalize[imp - f1] + Normalize[imp - f2]];

    v1 = Normalize[v0 - 2 normal (v0.normal)]/100;(*bounce*));

    rec)]

enter image description here

share|improve this answer
    
After a few turns you get (i.stack.imgur.com/6GwYq.png) . Perhaps you've forgotten some sanity check –  belisarius Dec 17 '13 at 2:44
1  
@belisarius should be fixed now. but still point case –  Kuba Dec 17 '13 at 21:04
    
@Kuba, what is imp ? –  Spizhen Dec 18 '13 at 21:31
    
@Spizhen imp = x0 + t v0 where t is from NSolve. So it is next impact position. –  Kuba Dec 18 '13 at 21:33
    
@Kuba, and what happens if the a space between the variables simply placed? Here, for example imp = x0 + t v0 I do not know about this. Maybe it's a feature version 9? –  Spizhen Dec 18 '13 at 21:44
show 3 more comments

My goal was quite ambitious. I wanted to create a way to let any rigid body bounce elastically against any other surface. To do this I use "masks" for the object and the environment. These masks are black and white images. White indicates that this is where the object/surface is, black is empty space. I can calculate the overlap between the object and the surface using Mathematica's image processing functions. Using the overlap I can calculate the normal of the surface. After that it's simple physics to change the velocity of the object accordingly. The code looks like this:

obj[mask_] := Graphics[{
   White, mask
   },
  PlotRange -> {{0, 500}, {0, 500}},
  ImageSize -> {500, 500},
  Background -> Black
  ]

forceVector[obj_, env_, center_] := N@Normalize[Plus @@ (center - # & /@ PixelValuePositions[ImageMultiply[obj, env], 1])]

step[{pt_, v_}] := Module[{f, nv},
  f = forceVector[obj[Disk[pt, 20]], ColorNegate@obj[Disk[{250, 250}, {100, 200}]], pt] /. (0. -> {0, 0});
  nv = If[v.f < 0, v - 2 v.f f, v];
  {pt + nv, nv}
  ]

pts = NestList[step, {{250, 250}, {1, 2}}, 1000];

frames = Graphics[{
     Black, Rectangle[{0, 0}, {500, 500}],
     White, Disk[{250, 250}, {100, 200}],
     Orange, Disk[#, 20]
     },
    PlotRange -> {{0, 500}, {0, 500}},
    ImageSize -> {500, 500}
    ] & /@ pts[[All, 1]];

ListAnimate[frames]

Here's a gif with a reduced number of frames:

bouncing disk

One can play with the velocity of the disk as well as the number of frames to get a longer path without as many calculations. This method is not very fast.

If you don't have the time/computing power to pre-compute the position list, you can still view the simulation using the code below. It will probably be very slow on many computers though (which is why I chose to pre-compute positions):

DynamicModule[{pt = {250, 250}, v = {6, 2}, f},
 Dynamic[
  f = forceVector[obj[Disk[pt, 20]], 
     ColorNegate@obj[Disk[{250, 250}, {100, 200}]], 
     pt] /. (0. -> {0, 0});
  If[v.f < 0, v = v - 2 v.f f];
  pt = pt + v;
  Graphics[{
    Black, Rectangle[{0, 0}, {500, 500}],
    White, Disk[{250, 250}, {100, 200}],
    Orange, Disk[pt, 20]
    },
   PlotRange -> {{0, 500}, {0, 500}},
   ImageSize -> {500, 500}
   ]
  ]
 ]
share|improve this answer
    
Your method is very long build. Even if the decrease in the value of two times. Is this normal? How long should I wait? 10 minutes is not ready. P.S. Hardware: MacBook Air 13" (mid 2013) –  Spizhen Dec 17 '13 at 20:13
    
@Spizhen Yeah, it's kind of slow because the way it detects collision is very expensive. I use an iMac and it certainly didn't take me ten minutes to execute that code but it may very well be the case on Macbook Air. –  Pickett Dec 17 '13 at 20:23
    
whether there is a primitive example of solving tasks? Maybe a circle instead of an ellipse. Tomorrow morning need to show my teacher =( –  Spizhen Dec 17 '13 at 20:32
    
@Spizhen whoah, aren't you ashamed writing such comments? have you tried anything? Anon, interesting approach ;) +1. –  Kuba Dec 17 '13 at 20:35
1  
@Spizhen I added a version that you can show without having to do anything in advance. You still need the function definition for forceVector and obj from earlier. –  Pickett Dec 18 '13 at 0:37
show 7 more comments

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.