function point2ball (xmouse, ymouse, m) { // compute intersection with vtb, no need to normalize, 1 sqrt/call var factor; var inout; dir=new Array(3); // change xconv, yconv to *, make this vector? xm = (xmouse-xcenter)*oneoverxconv; ym = -(ymouse-ycenter)*oneoveryconv;// convert to image plane coordinates for (i=0; i<3; i++) m[i] = xm*i1[i]+ym*i2[i]; // convert to R^3 normpmsq = normsq3(m); // =0 for center if (normpmsq>grazsq) { // normalize to radius of grazing circle in image plane inout=1; factor = 1.0/Math.sqrt(normpmsq); for (i=0; i<3; i++) m[i] *= factor; } else { // normpmsq <= grazsq, quadratic for parameter of viewline intersection with ball inout=0; for (i=0;i<3;i++) dir[i]=vp[i]-m[i]; a=normsq3(dir); //a = focsq+normpmsq; // a>normpmsq>0 since focsq >0 // either form screws up because they assume (vp,m)=0 in b // which is really -2dot3(m,dir) so use that. //b = -2.0*normpmsq; // b=0 for centerpoint, else b<0 b=2.0*dot3(m,dir); // if not gradual instability loss of orthogonality feedback! c = normpmsq-1.0; // 00 t =q/a; // r1=q/a;// r2=c/q; // a>0 gives one positive solution always for (i=0; i<3; i++) m[i] += t*dir[i]; } // end else (inside ball) return inout; } function transvect () {// rotate vd,i2 by e2 to e1 transvection, 4 dot products, 1 division bb = new Array(3); w = new Array(3); // 4 scalar multiplies, 4 scalar ax+y, 1 vector +, 1 scalar ax for (i=0; i<3; i++) bb[i] = e1[i]+e2[i]; nsbb=normsq3(bb); if (nsbb > tol){ // do nothing if bb is numerically zero, identity rotation anyway twoovernormsqbb = 2.0/nsbb; // reflect v1 in bb then in e1, then do same for v2 twov1dotbb = dot3(vd, bb)*twoovernormsqbb; for (i=0; i<3; i++) w[i] = twov1dotbb*bb[i]-vd[i]; twowdote1 = 2.0*dot3(w, e1); for (i=0; i<3; i++) vd[i] = twowdote1*e1[i]-w[i]; twov2dotbb = dot3(i2, bb)*twoovernormsqbb; for (i=0; i<3; i++) w[i] = twov2dotbb*bb[i]-i2[i]; twowdote1 = 2.0*dot3(w, e1); for (i=0; i<3; i++) i2[i] = twowdote1*e1[i]-w[i]; cross(vd, i2, i1); for (i=0; i<3; i++) vp[i] = -foc*vd[i]; } } function persp (dp, p) { // compute perspective projection of data point into viewplane // (vp+t(dp-vp),vd)=0 so t=-(vd,vp)/(vd,dp-vp) // doesn't require basis for that plane // so it can be used to set i2 in initialization! var t; dir = new Array(3); centerv = new Array(3); for (i=0; i<3; i++) dir[i] = dp[i]-vp[i]; t = -dot3(vd, vp)/dot3(vd, dir); for (i=0; i<3; i++) p[i] = vp[i]+t*dir[i]; } // the main loop: if (mouseisdown == 0) { // mouseisup transvect(); mousewasdown=0; } else { mousewasout=mouseisout; mouseisout=point2ball(_xmouse, _ymouse, e2);// gets new point on ball and mouse in/out state if ((mousewasdown==1)&&(mousewasout==mouseisout)) transvect();//mouse was down, didn't cross horizon else for (i=0; i<3; i++) e1[i]=e2[i]; //just down/crossed horizon, initialize identity mousewasdown=1; } // end if isdown someListener.onMouseDown = function () { // the event, not the state mousewasdown=0; mouseisdown=1; name1 = "circle"; attachMovie("circle", name1, 1); //attached so not cleared each frame _root[name1]._x = xcenter;_root[name1]._y = ycenter; _root[name1]._xscale = xconv*graz; _root[name1]._yscale = yconv*graz; } someListener.onMouseUp = function () { // the event, not the state mousewasdown=1; mouseisdown=0; _root[name1].removeMovieClip(); }