1 /*
  2     Copyright 2010
  3         Matthias Ehmann,
  4         Michael Gerhaeuser,
  5         Carsten Miller,
  6         Bianca Valentin,
  7         Alfred Wassermann,
  8         Peter Wilfahrt
  9 
 10     This file is part of JSXGraph.
 11 
 12     JSXGraph is free software: you can redistribute it and/or modify
 13     it under the terms of the GNU Lesser General Public License as published by
 14     the Free Software Foundation, either version 3 of the License, or
 15     (at your option) any later version.
 16 
 17     JSXGraph is distributed in the hope that it will be useful,
 18     but WITHOUT ANY WARRANTY; without even the implied warranty of
 19     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 20     GNU Lesser General Public License for more details.
 21 
 22     You should have received a copy of the GNU Lesser General Public License
 23     along with JSXGraph.  If not, see <http://www.gnu.org/licenses/>.
 24 */
 25 
 26 JXG.Math.Numerics.createRoulette = function(c1, c2, start_c1, stepsize, direction, time, pointlist) {
 27     var Roulette = function() {
 28         var alpha = 0,
 29             t1 = start_c1,
 30             t2 = JXG.Math.Numerics.root(
 31                 function(t) { 
 32                     var c1x = c1.X(t1),
 33                         c1y = c1.Y(t1),
 34                         c2x = c2.X(t),
 35                         c2y = c2.Y(t);
 36                     return (c1x-c2x)*(c1x-c2x) + (c1y-c2y)*(c1y-c2y);
 37                 },
 38                 0),
 39             t1_new = 0.0, t2_new = 0.0, 
 40             mx, my, c1x, c1y, c2x, c2y, c1dist,
 41             rotation = brd.create('transform',[function(){ return alpha;}, 
 42                                            function(){ return c1.X(t1);},
 43                                            function(){ return c1.Y(t1);}], 
 44                                           {type:'rotate'}),
 45             linDist = function(t) {
 46                 c2x = mx - c2.X(t);
 47                 c2y = my - c2.Y(t);
 48                 return c1dist - (c2x*c2x+c2y*c2y);
 49                 },   
 50             beta = Math.PI/18.0,
 51             beta9 = beta*9,
 52             interval = null; 
 53 
 54         this.rolling = function(){
 55             t1_new = t1+direction*stepsize;
 56             mx = c1.X(t1);
 57             my = c1.Y(t1);
 58             c1x = mx - c1.X(t1_new);
 59             c1y = my - c1.Y(t1_new);
 60             c1dist = c1x*c1x+c1y*c1y;  // used in linDist
 61             t2_new = JXG.Math.Numerics.root(linDist, t2+direction*stepsize);
 62             alpha = -JXG.Math.Geometry.rad(
 63                     [c1.X(t1_new),c1.Y(t1_new)],
 64                     [c1.X(t1),c1.Y(t1)],
 65                     [c2.X(t2_new),c2.Y(t2_new)]);
 66             if (alpha <-beta && alpha>-beta9) { // -(10-90) degrees
 67                 alpha = -beta;
 68                 rotation.applyOnce(pointlist);
 69             } else if (alpha>-2*Math.PI+beta && alpha<-2*Math.PI+beta9) {
 70                 alpha = -2*Math.PI+beta;
 71                 rotation.applyOnce(pointlist);
 72             } else {
 73                 rotation.applyOnce(pointlist);
 74                 t1 = t1_new;
 75                 t2 = t2_new;
 76             }
 77             brd.update();
 78         };
 79     
 80         this.start = function() {
 81             if (time>0) {
 82                 interval = setInterval(this.rolling, time);
 83             }
 84             return this;
 85         };
 86     
 87         this.stop = function() {
 88             clearInterval(interval);
 89             return this;
 90         };
 91         return this;
 92     };
 93     return new Roulette();
 94 };
 95 
 96 JXG.Math.Numerics.reuleauxPolygon = function(points, nr) {
 97     var pi2 = Math.PI*2,
 98         pi2_n = pi2/nr,
 99         diag = (nr-1)/2,
100         beta, d = 0,
101         makeFct = function(which, trig) {
102                 return function(t, suspendUpdate) {
103                     if (!suspendUpdate) {
104                         d = points[0].Dist(points[diag]);
105                         beta = JXG.Math.Geometry.rad([points[0].X()+1,points[0].Y()],points[0],points[(diag)%nr]);
106                     }
107                     var t1 = (t%pi2 + pi2) % pi2;
108                     var j = Math.floor(t1 / pi2_n)%nr;
109                     if (isNaN(j)) return j;
110                     t1 = (t1-j*pi2_n)*0.5 + beta+j*pi2_n;
111                     return points[j][which]()+d*Math[trig](t1);
112                 };
113             };
114     return [
115             makeFct('X','cos'),
116             makeFct('Y','sin'),
117             0,
118             Math.PI*2
119         ];
120 };        
121