Upload
others
View
7
Download
0
Embed Size (px)
Citation preview
Mistretta 1
In Pursuit of the Curve
A discrete method of modeling pursuit curves
Anthony Mistretta
Senior Project, MAT 499
April 10, 2014
Mistretta 2
Table of Contents
Abstract 3
Introduction 4
My Proposal 5
Definitions 5
Basic pursuer dynamics 7
Basic feeling operation 8
Advanced feeling operation 9
Modified movement dynamics 11
3D Chase 12
The Catch 14
Random user interface 15
Conclusion 15
Bibliography 17
Appendix: the Chase Program text 20
Mistretta 3
Abstract
Curves of Pursuit are one of the most fundamental structures that are considered when
attempting to formulate how to obtain a desired goal--how do we get from here to there in the
most economical way? In its simplicity, the method of just moving towards your goal provides a
strong foundation on which to work out a lot of the issues that may arise. Trying to model a
pursuit curve using differential equations will often be too difficult a task for a person to achieve
since the results often do not conform nicely to any elementary functions. This project uses
HTML/Javascript to design a discrete method of finding pursuit curve solutions to a wide variety
of initial conditions. It provides a framework upon which we can apply more realistic properties
to the objects being considered. Inspired by Euler’s tangent line method of approximating the
solution to a differential equation, and by using the bisection method to approximate any real
number to an acceptable degree of error, we can model a pursuit on countless varieties of
surfaces and space curves. The program that is developed allows us to watch the action
unfolding, and to view it from any angle of perspective.
Mistretta 4
Introduction
Since the dawn of time, when ancient man first laid eyes upon ancient woman, the chase
has been on. This research paper deals with the topic of Curves of Pursuit. In general, a pursuit
curve is the curve that is generated when tracking an object along a direct line of sight with
uniform velocity, as defined by George Boole [1]. This presents us with the property that at any
given moment the slope of the tangent to the curve can be defined giving a differential equation.
The most basic of pursuits--the trivial case--is when the object being pursued is simply stationary
resulting in a straight line. A more popular version, which is just as trivial, goes along the lines
of what was presented in Alcuin’s collection of problems [2] designed to encourage children to
think mathematically (Propositiones alcuini doctoris caroli magni imperatoris ad acuendos
juvenes), the 26th proposition reads:
“There is a field which is 150 feet long. At one end stood a dog, at the other, a hare. The
dog advanced behind, namely, to chase the hare. But whereas the dog went nine feet per
stride, the hare went seven. How many feet and how many leaps did the dog take in
pursuing the fleeing hare until it was caught?”
Since the chase is along a straight line, the object is essentially stationary relative to the purser
such that it reduces to the trivial case.
Pierre Bouguer (1732) is credited as being the first person to apply calculus to a specific
pursuit problem that he was considering [3]. It involved a merchant ship which traveled along a
straight course with a constant speed which was sighted afar by a pirate ship. At first, the
merchant ship’s line of travel is not collinear to the line of travel of the pirate ship which allows
for a more taxing solution--and therefore nontrivial. In 1735, Pierre Moreau de Maupertuis
Mistretta 5
considered paths whereby the object of pursuit followed nonlinear courses [4]. Others have
presented problems such that the object being chased travels along a predefined function in
Cartesian, as well as polar, and a multitude of other coordinate systems.
My Proposal
The majority of the present findings maintain that the differential equation produced by
the pursuit curve does not yield nicely, in general, to some elementary function. They deal with
curves of pursuit that are generated when the course of the object is already known. This paper
proposes to create a Chase program (a chicken chasing a rabbit) using elements of geometry and
vector calculations to follow, and perhaps to predict, a path that is generated by user input that
can be predefined using parametric or polar equations; or by directing the path of the rabbit using
keystrokes from a keyboard. Leonard Euler proposed solutions to differential equations by
taking iterative steps; the slope being defined at a known point is followed to another point with
which the slope is recalculated to direct the next movement [5]. This same concept will be
utilized to create a path for both the chicken and the rabbit to move on. A record of all the
discrete points can be kept to determine the accuracy of this method with known solutions to
predefined pursuit curve problems.
Definitions
The basic element of movement is a step: a discrete jump from point A, to point B with
no intermediary points between. This creates a sequence of discrete points with which to model
a function with. In order to maintain a uniform speed, the concept of a stride is developed. A
stride is the distance traveled per unit of time, and is composed of one or more steps which add
Mistretta 6
up in succession to the required distance of travel.
A Bstride: |------------ … --------------|
steps: |---|---| … |---| … |---| a0 a1 a2… ai ai+1 … ak-1 ak
It is not necessary for each step to be of equal length; but for the sake of simplicity, our
program will use steps of equal length, such that for k steps per stride, the length of each step is:
stride/k. By composing a stride with multitude of steps the discrete path provides a better
approximation to a continuous function. As the number of steps per stride approaches infinity,
the curves that are traveled by the rabbit, and generated by the chicken, converge to their
respective continuous functions. This approach can be verified by keeping a log of the
coordinates that are generated and using known solutions to pursuit problems to compare with.
In order for our computer program to determine where to move the rabbit discretely along
a predefined continuous function, an operation which we will call feeling can be constructed.
Feeling is an operation based on the concept of a Dedekind cut. For a closed, well-ordered, non-
empty, bounded interval [a, b] in ℝ, there exists some c in [a, b] such that [a, b] = [a, c] (c,
b]. As such, the interval is divided into 2 distinct partitions, L := [a, c] , or R := (c, b], such that
for any k in [a, b], k is either in L or in R. Our feeling operation is an iterative process of
partitioning the interval that contains k into finer and finer partitions until we reach an acceptable
error, E, defined to be |k - ai| ≤ E, for the first i th iteration that satisfies this criteria. For example,
suppose we have the set of ai = {aj, aj+1, aj+2, …}, which consists of all the elements that satisfy
the condition, |k - ai| ≤ E, then we would let aj (the least upper bound) be a reasonable
approximation for k. In our program we will be dividing each subinterval that contains k in half,
Mistretta 7
testing the midpoint, c, for the condition of |k - c| = 0. If this condition is false, then we
determine if |k - c| < E to allow for the possibility of the endpoint being close enough for a
solution. If neither condition holds true, then we evaluate if k - c < 0 in order to choose the
interval containing k to work through again. Feeling is only required when we are trying to
conform the rabbit’s movements to some predefined parametric/polar function and has no
practical application when programing for a random run.
Basic Pursuer Dynamics
1 stride = 1 step
Our program will make extensive use of vector calculations to plot the movements for
both the chicken and the rabbit. For any given moment in time, the chicken is headed directly
towards the rabbit. The chicken moves forward along a pursuit vector with a magnitude equal to
the speed of the chicken.
Mistretta 8
The calculation for any given pursuit vector is therefore:
Basic Feeling Operation
The rabbit’s movement is defined by a vector with a magnitude equal to the rabbit’s
speed. In order to compare this method to known results, the chase program will move the rabbit
along some generic function by feeling for the next step. This process starts by feeling for y =
f(x) around a circle with a radius equal to 1 step of the rabbit (Vr), centered at Rn = (rx, ry).
Mistretta 9
The (x,y) components for the feeler are calculated parametrically:
The parameter θk is defined recursively using the conditions:
This feeler function is terminated when the distance between r yn +1and f (rxn+1 ) is within some
predefined acceptable allowance in which we define r yn +1=f (r xn+1 ) for the accepted value of r xn+1.
These movement calculations are then repeated until the position vectors of the chicken and
rabbit are in close enough proximity to declare a capture.
Advanced Feeling Operation
One drawback that we come across using the basic feeling operation is that it is only
suitable for a relatively small set of functions, y being a function that depends on x--it is just not
well adapted to parametric or polar functions. In order to accommodate for a wider range of
functions we need to consider some parametric function, x(t), y(t) (or some polar function, r(t)
respectively). Let x(tn), y(tn) represent some current point, and let k be the length of 1 step. By
using the parametric identities: x(t) = r(t) cos(t), and y(t) = r(t) sin(t) to convert a polar point to a
Mistretta 10
parametric point, we can represent our feeling operation with the condition (d) that for some tn,
and tn +i, for some positive unit measure 1 of i, as:
d=min(√(x (t n )−x (tn+i ))2+( y (tn )− y (tn+i ))2−k )≥ 0
In other words, the distance between the points represented by the input values of tn, and tn +i is
just large enough to contain k. For example;
In this case, we would obtain the interval [tn +5, tn +6] which contains the input value for our
next move. This interval is then partitioned into finer and finer subintervals to determine our
next step.
1 A positive unit measure depends on the dimension of t. If t measures time, then i is 1 unit of time. If t measures degrees, then i is 1 degree. If t is a measure of radians, we assume i to be π/180.
Mistretta 11
Modified movement dynamics
1 stride = k steps, for k > 1.
As a consequence of the discrete nature of of our movements, the strides that are
calculated by both objects do not always conform to the arclength of a predefined function which
the same speed applied to that of a continuous function would generate--a line between 2 points
is not necessarily the same length as a curve between two points. In order to allow the pursuit
curve to converge more quickly, we want the chicken to maintain a greater number of steps per
stride than that of the rabbit. The more points of contact with the ground, the more control exists
within the program. In our program, this ratio is maintained as 16 steps per chicken stride to 1
rabbit step. In order to accomplish this modification we have to first have to construct an evade
vector. An evade vector is a scaled down version of the rabbit’s stride that divvies up the
rabbit’s position into k collinear steps--in this case, k = 10.
Mistretta 12
This evade vector allows us to maintain the basic calculation of (1) for a chicken step by simply
adding in an appropriate multiple of the evade vector to the current Rn position vector.
3D Chase
Running a chase in a 3-dimensional vector space provided us a few new obstacles to
overcome. One of the simplest was solved by adding a third vector component to our objects to
keep track of. Another hurdle had to do with representing a 3-dimensional space on a 2-
dimensional screen, and viewing it from any given perspective. We concocted a series of matrix
calculations, x=, to rectify the situation.
¿ [cos (θ3 ) −sin (θ3 )sin (θ3 ) cos (θ3 ) ]=[1 0 0
0 sin (θ2 ) cos (θ2 )]=[cos ( θ1 ) −sin (θ1 ) 0sin (θ1 ) cos ( θ1 ) 0
0 0 1 ]For any x:= (x1, x2, x3), lets us rotate x about the origin in the xy plane by some angle θ1;
provides a vertical rotation about the origin in the zy plane by some angle θ2 and projects the
results onto the zx plane; gives us the ability to rotate the zx plane about the origin by an angle
θ3.
We also want the ability to chase the rabbit on a predefined surface. This changes the
structure of our pursuit vector from moving directly towards the rabbit, into moving in the
direction of the rabbit. For a given predefined surface, z(x,y), the direction towards the rabbit is
maintained by the projection of our pursuit vector onto the xy plane. We can then apply our
Mistretta 13
basic feeling function in order to feel where we want to step on the surface.
By feeling through the angle θ, we can find a scalar, s, such that:
b=s i √( px )2+ ( py )2=|Pn|cos (θi )
si=|Pn|cos (θi )√ ( px )2+( py )2
When the value of z(s(px), s(py)) is within an acceptable error, our pursuit vector (px,py,pz) is
modified as s(px, py, z(px, py)) in order to maintain the same speed and follow along the
predefined surface in the direction of the rabbit.
***Other surfaces to consider, and how to adapt user inputs to accommodate them. We can find
polar coordinate rabbit runs in 2d, adapt for cylinder/spherical ?? can advanced feeling be used in
‘nonfunction’ surfaces .. x(u,v), y(u,v), z(u,v) ??
Mistretta 14
The Catch
In some cases, if we just define a catch by some predefined distance, the parameter to set
in motion a catch is never obtained. For certain cases we just oscillate around the path of the
rabbit without actually fulfilling a catch condition.
There are two conditions that need to be looked at in order to determine of a suitable
catch has occurred. Since the shortest distance between a point and a line is the perpendicular
distance, these conditions can be considered
in reference to drawing on the right. Vector d
represents the place where the rabbit will land,
Rn+1, relative to where the chicken started
from. The catch zone is the circle around the
rabbit’s end position that has a radius equal to
the catch parameter. Condition 1 represent
the situation such that the magnitude of our
pursuit vector is strictly less than |d| cos(),
and the distance from the point Rn+1 and the end position of the chicken, Cn+Pn, is calculated to
determine if a catch has been made. Condition 2 the situation in which the magnitude of our
pursuit vector is greater than, or equal to, |d| cos(). It is sufficient for Condition 2 to calculate
Mistretta 15
the perpendicular distance. If |d| sin() is less than, or equal to, the catch parameter then a valid
catch has been made.
Random user interface
A computer program that simulates a random was also written. Random run programs
are useful in gaming applications since the user of the program is allowed to control where the
rabbit goes in real-time. All that has to be accounted for is keeping the chase in its selected
atmosphere (space chase, or surface chase). A space chase is the simplest to account for since
there are no obstructions to hinder the paths that are generated. A surface chase would use the
respective feeling operations to keep the rabbit and chicken confined to the same surface.
Conclusion
We were able to generating a considerable number of pursuit curves from a small set of
fundamental principles. We were only limited by time and imagination as to other possibilities
we could have pursued. Future considerations include giving the chicken a degree of autonomy.
By giving the chicken a memory in which it can record past movements, it is feasible that it may
use that information to extrapolate the speed of the rabbit using trigonometry and vector
calculations and thereby adjust its own speed. A memory would also allow it to interpolate the
local course of the rabbit consider adjustments to its own path in an attempt predict where the
rabbit will move next.
A method to determine the accuracy of the generated pursuit curve needs to be developed
in order to solidify our concepts in a more rigorous fashion. The visual acuity is a strong
indicator of the legitimacy of our project, but is not the best way to assess the accuracy of it.
Mistretta 16
One course of action that still needs to be ironed out addresses how we could maintain a
chase on a 3-dimensional surface such that the chase occurs in the u,v-plane, but its parameters
are defined in the x,y,z-vector space. If this could be worked out, then a chase on such objects as
complete quadratic surfaces and even Klein bottles could be demonstrated.
The programs that we created could be refined such that they are more efficient in terms
of the computer sciences. The overall aim of this project to develop strategies and a working
model was achieved, but there is definite room for improvements.
Mistretta 17
Bibliography
[1] Boole, G. (1859). Treatise on Differential Equations, (p. 246). Cambridge, Macmillan
and Co.. Print.
[2] Singmaster, D. (1992). Problems to sharpen the young: an annotated translation of
Propositiones ad acuendos juvenes. The Mathematical Gazette,Vol 76, No. 475, March
1992 (pp.102–126). Print.
[3] Morley, F. V. (1921). A Curve of Pursuit. The American Mathematical Monthly, Vol 28,
No. 2, Feb 1921 (p. 54-61). Print.
[4] Simoson, A. J. (2007). Pursuit Curves for the Man in the Moone. The College Mathematics
Journal, Vol 38 (pp. 330-338). Print.
[5] BIBLIOGRAPHY Boyce, W. E., & DiPrima, R. C. (2001). Elementary Differential Equations and
Boundary Value Problems, 7E: Numerical Methods (ch 8, Sec 1). New York: John Wiley and Sons,
Inc. Textbook.
Mistretta 18
Appendix: the Chase Program
Explanation of user interface: There are many fields to address customization of predefined curves/surfaces. A “Surface Chase” confines the objects to a surface defined as z(x’,y’). A “Space Chase” lets the z-axis be defined by the parameter t’. The function inputs for this specific program have to be made in the Javascript Math Object syntax, and an eval() command interprets the text. The Javascript String Object then searches, replaces and overall injects the parameters starting values, and in progress values to calculate the placement of the objects. Hide options are provided to focus on either 1 or both paths generated by the movement of the objects. Camera tilt functionality allows us to view the event from any angle or perspective. Start of course starts the process moving (the relative center of the computer monitor is the origin, but varies by model); Stop is to provide a manual break; and Refresh is used to clean out the variables of the program so that they do not interfere in a new run. Speeds are
Mistretta 19
measured in units of time so that the number of moves provides the time it takes, and multiplying that by the speed gives us the distances traveled.
The Code (written in HTML/Javascript):
<html>
<!-- ------------------------------------------------------// Chase Program used to generate Curves of Pursuit.// by: Anthony Mistretta/ Senior Project 2014/ Saint Leo University// Patent may or may not be pending :)/----------------------------------------------------------->
<body>
<img id="cdiv" style="position:absolute; top:-50:left:0"><img id="rdiv" style="position:absolute; top:-50:left:0"><div id="chase">
</div><div id="screen" style="position:absolute; top:1500">
</div><table>
<tr><td><br><u>Parametric Setup</u>: Display Results as:<select id="det">
<option value="s1">Space Chase</option><option value="s2">Surface Chase</option>
</select><br><br></td>
</tr></table>
<table><tr>
<td align="right">Rabbit x(t') := <input id="xft"> <br>Rabbit y(t') := <input id="yft"> <br>Rabbit z(t'; x',y') := <input id="zft"> <br>
Mistretta 20
<br></td>
</tr></table>
<table><tr>
<td align="right">Change z-alpha by, <input type=button id="znf" value="-5" onClick="reVue(this.id)">
<input id="zalpha" size=2 value="0"> <input type=button id="zpf" value="+5" onClick="reVue(this.id)">
degrees.</td>
</tr>
<tr><td align="right">Change x-beta by, <input type=button id="xnf" value="-5" onClick="reVue(this.id)">
<input id="xbeta" value="0" size=2> <input type=button id="xpf" value="+5" onClick="reVue(this.id)">
degrees.</td>
</tr>
<tr><td align="right">Change y-gamma by, <input type=button id="ynf" value="-5" onClick="reVue(this.id)">
<input id="ygmma" value="0" size=2> <input type=button id="ypf" value="+5" onClick="reVue(this.id)">
degrees.</td>
</tr>
<tr><td><br>Chicken Start (x,y,z)= (<input id="cx" value="300" size=2>,
<input id="cy" value="100" size=2>,<input id="cz" value="300" size=2>)
</td>
<td><br>Chicken Speed=<input id="vc" value="0" size=2></td>
</tr>
<tr>
Mistretta 21
<td>Rabbit Start, time(t')=<input id="rs" value="0" size=2></td>
<td>Rabbit Speed= <input id="vr" value="5" size=2></td>
</tr>
<tr><td>Catch Parameter: <input id="err" value="1" size=1><br></td>
<td># Steps: <input id="stp" value="1" size=2></td>
</tr>
<tr><td><input type=button value=" Start " onClick="qwe()">;<input type=button value=" Stop " onClick="zxc()">;<input type=button value=" Refresh " onClick="reFrsh()"></td>
</tr>
</table>
<textarea id="log">Fills after a chase ...</textarea><br>(Point Record)<br><br>
<table border=1><tr>
<td>Number of moves:</td>
<td> <span id="outp">
</span></td>
</tr></table><br>
Mistretta 22
(Hide Path Options)<input id="rbt" type=button value=" Rabbit " onClick="reVue('o',this.id)">;<input id="chkn" type=button value=" Chicken " onClick="reVue('o',this.id)">
</body>
<script language=javascript>
/* ********************************** DECLARE GLOBAL VARIABLES********************************** */
var cnx, rnx, cny, rny, cnz, rnz, evar pnx, pny, pnz, vc, vr, a, b, g, x, d, flag=-1var rlog="r=[", clog="c=[", n=1, f=0var rbt="", chkn="", stp, tail=""
var eqy="", eqx="", eqz="", pip=0var Feqy="", Feqx="", Feqz=""var rsx, rsy, csx, csyvar evx, evy, evz
var nxa, nya, nzavar nxb1, nyb1, nxb2, nyb2, nzb var zalf=0, xbeta=0var csz, rszvar frx, fry, frz
var xrsh=new Array()var xcsh=new Array()var yrsh=new Array()var ycsh=new Array()
var cimg1=new Image()var cimg2=new Image()var rimg1=new Image()var rimg2=new Image()
var cdiv="", rdiv="", img=0, det
/* ********************************** SETUP*********************************** */
Mistretta 23
function qwe(){
cimg1.src= "chickenhunter1.gif"cimg2.src= "chickenhunter2.gif"rimg1.src= "rabbit1.gif"rimg2.src= "rabbit2.gif"
reFrsh()pip=0
stp= document.getElementById("stp").value*1det= document.getElementById("det").valuee= document.getElementById("err").value*1
zalf= document.getElementById("zalpha").value*1zalf= zalf*Math.PI/180
xbeta= document.getElementById("xbeta").value*1xbeta= xbeta*Math.PI/180
nxb1= Math.cos(xbeta)nyb1= -Math.sin(xbeta)nxb2= Math.sin(xbeta)nyb2= Math.cos(xbeta)
nya= Math.sin(zalf)nza= Math.cos(zalf)
n= document.getElementById("rs").value*1
eqx= document.getElementById("xft").valueeqy= document.getElementById("yft").valueeqz= document.getElementById("zft").value
rnx= strx(n)rny= stry(n)rnz= strz(n,rnx,rny)
rsx= rnx*nxb1 +rny*nyb1rsy= rnx*nxb2 +rny*nyb2rsz= rnz
rsx= rsxrsy= rsy*nya +rsz*nza
Mistretta 24
cnx= document.getElementById("cx").value*1cny= document.getElementById("cy").value*1cnz= document.getElementById("cz").value*1
if (det=="s2"){cnz= strz(0,cnx,cny)}
csx= cnx*nxb1 +cny*nyb1csy= cnx*nxb2 +cny*nyb2csz= cnz
csx= csxcsy= csy*nya +csz*nza
lcnx[pip]= cnxlcny[pip]= cnylcnz[pip]= cnz
lrnx[pip]= rnxlrny[pip]= rnylrnz[pip]= rnz
/* ****************** RUN THE CHASE****************** */g=setInterval("chicken()",66)
}
var lcnx=new Array()var lcny=new Array()var lcnz=new Array()
var lrnx=new Array()var lrny=new Array()var lrnz=new Array()
var lrbf=new Array()var lcbf=new Array()
function chicken()
Mistretta 25
{vc= document.getElementById("vc").value*1vr= document.getElementById("vr").value*1
img=img+1if (img == 1)
{document.getElementById("cdiv").src= cimg1.srcdocument.getElementById("rdiv").src= rimg1.src}
else{document.getElementById("cdiv").src= cimg2.srcdocument.getElementById("rdiv").src= rimg2.src}
if (img > 2) {img=0}
document.getElementById("cdiv").style.top= csy*-1+500document.getElementById("rdiv").style.top= rsy*-1+500document.getElementById("cdiv").style.left= csx+500document.getElementById("rdiv").style.left= rsx+500
/* ******************* Display**********************/
if (rny >= 0){var rbf= "<fon"+"t color='red'>"; lrbf[pip]= rbf}
else{var rbf= "<fon"+"t color='orange'>"; lrbf[pip]= rbf}
if (cny >= 0){var cbf= "<fon"+"t color='green'>"; lcbf[pip]= cbf}
else{var cbf= "<fon"+"t color='blue'>"; lcbf[pip]= cbf}
chkn=chkn+"<di"+"v style='position:absolute; top:"+(csy*-1+500)+"; left:"+(csx+500)+"'>"+cbf+"<b>c</b></font></d"+"iv>"rbt=rbt+"<di"+"v style='position:absolute; top:"+(rsy*-1+500)+"; left:"+(rsx+500)+"'>"+rbf+"<b>r</b></font></d"+"iv>"
document.getElementById("chase").innerHTML= rbt+chknpip=pip+1
Mistretta 26
/* ******************* Catch Condition**********************/
if (Math.pow(Math.pow((cnx-rnx),2)+Math.pow((cny-rny),2)+Math.pow((cnz-rnz),2),1/2) <= e){zxc()}
/* **************************** STRIDES ***************************** */
a= Math.pow((rnx-cnx),2)b= Math.pow((rny-cny),2)c= Math.pow((rnz-cnz),2)
pnx= (vc*(rnx-cnx)/Math.pow((a+b+c), 0.5))/(stp*16)pny= (vc*(rny-cny)/Math.pow((a+b+c), 0.5))/(stp*16)pnz= (vc*(rnz-cnz)/Math.pow((a+b+c), 0.5))/(stp*16)
cnx= cnx + pnxcny= cny + pnycnz= cnz + pnz
csx= cnx*nxb1 +cny*nyb1csy= cnx*nxb2 +cny*nyb2csz= cnz
csx= csxcsy= csy*nya +csz*nza
/* ************************************ PARAMETRIC FEELING************************************ */
for (var t=n; t<101+n; t=t+1) {frx= strx(t)fry= stry(t)frz= strz(t,frx,fry)
var d1= Math.pow(Math.pow((rnx-frx),2)+Math.pow((rny-fry),2)+Math.pow((rnz-frz),2), 0.5)
Mistretta 27
if (t == 100+n){f= t; t= 102+n}
if ((vr/stp-d1) <= 0){f= t; t= 102+n}
}
if ((vr/stp-d1) == 0) {feelMe(0)}
else{for (var k=1; k<101; k=k+1)
{frx= strx(f)fry= stry(f)frz= strz(f,frx,fry)
d1= Math.pow(Math.pow((rnx-frx),2)+Math.pow((rny-fry),2)+Math.pow((rnz-frz),2), 0.5)
if (k == 100){feelMe(1); k= 102}
if (Math.abs(d1-vr/stp) < .00001){feelMe(1); k= 102}
if ((vr/stp-d1) < 0){f= f - Math.pow(0.5,k)}
else {f= f + Math.pow(0.5,k)}
}}
n= f
lrnx[pip]=rnxlrny[pip]=rnylrnz[pip]=rnz
lcnx[pip]=cnxlcny[pip]=cnylcnz[pip]=cnz}
Mistretta 28
var pds
function feelMe(pds){if (pds == 0)
{evx= (strx(f)-rnx)/(stp*16)evy= (stry(f)-rny)/(stp*16)evz= (strz(f,frx,fry)-rnz)/(stp*16)}
else{evx= (frx-rnx)/(stp*16)evy= (fry-rny)/(stp*16)evz= (frz-rnz)/(stp*16)}
for (var h=1; h<16; h=h+1){a= Math.pow((rnx+h*evx-cnx),2)b= Math.pow((rny+h*evy-cny),2)c= Math.pow((rnz+h*evz-cnz),2)
var d2= Math.pow((a+b+c),1/2)
if (d2 == 0){pip=pip+1h=18zxc()}
else{pnx= (vc/(stp*16))*(rnx+h*evx-cnx)/Math.pow((a+b+c), 0.5)pny= (vc/(stp*16))*(rny+h*evy-cny)/Math.pow((a+b+c), 0.5)pnz= (vc/(stp*16))*(rnz+h*evz-cnz)/Math.pow((a+b+c), 0.5)
if (det=="s2"){surface()}
else{cnx=cnx + pnxcny=cny + pnycnz=cnz + pnz}
Mistretta 29
}}
rnx= frxrny= fryrnz= frz
rsx= rnx*nxb1 +rny*nyb1rsy= rnx*nxb2 +rny*nyb2rsz= rnz
rsx= rsxrsy= rsy*nya +rsz*nza}
/* ************************************ EVALUATE x(t)************************************ */
var n1, n2, n3, cv
function strx(cv){Feqx= eqx.replace(/t'/g, cv)n1= eval(Feqx)
if (n1=="Infinity"){n1=0}
if (n1!=n1){n1=0}
Feqx=""
return n1}
/* ************************************ EVALUATE y(t)************************************ */
function stry(cv)
Mistretta 30
{Feqy= eqy.replace(/t'/g, cv)n2= eval(Feqy)
if (n2=="Infinity"){n2=0}
if (n2!=n2){n2=0}
Feqy=""
return n2}
/* ************************************ EVALUATE z(t)************************************ */var gx,gy, flag=0
function strz(cv,gx,gy){var Fqz1, Fqz2
if (det=="s1"){var ba= eqz.search("x'")var bd= eqz.search("y'")if (flag == 0)
{if (ba != -1 || bd != -1){alert("Space Chase selected: x'= y'= t'")flag= 1}
}
Fqz1= eqz.replace(/x'/g, "t'")Fqz2= Fqz1.replace(/y'/g, "t'")Feqz= Fqz2.replace(/t'/g, cv)}
if (det=="s2"){Fq1= eqz.replace(/x'/g, gx)Feqz= Fq1.replace(/y'/g, gy)}
n3= eval(Feqz)
if (n3=="Infinity")
Mistretta 31
{n3=0}if (n3!=n3)
{n3=0}
Feqz=""
return n3}
/* ************************************ SURFACE CHASE************************************ */
function surface(){var ncnzvar ncxp=pnx, ncyp=pny, nczp=pnzvar alpha = 0
for (w=1; w<16; w=w+1){ncnz = strz(0, cnx+ncxp, cny+ncyp)
if (cnz + nczp == ncnz){w = 17}
else{ncxp = pnx * vc*
Math.cos(alpha)/(16*stp*Math.sqrt(Math.pow(pnx,2)+Math.pow(pny,2)))ncyp = pny * vc*
Math.cos(alpha)/(16*stp*Math.sqrt(Math.pow(pnx,2)+Math.pow(pny,2)))nczp = vc*Math.sin(alpha)/(16*stp)
if (cnz + nczp < ncnz){alpha = alpha + Math.PI/Math.pow(2,w)}
else{alpha = alpha - Math.PI/Math.pow(2,w)}
}}
cnx = cnx + ncxpcny = cny + ncypcnz = cnz + nczp
return}
Mistretta 32
/* ***************************************** 3D Rotation***************************************** */
var shft, shid, hide="", togl=""
function reVue(shid,hide){
zalf= document.getElementById("zalpha").value*1xbeta= document.getElementById("xbeta").value*1ygmma= document.getElementById("ygmma").value*1
if(shid=="znf"){shft=-5;document.getElementById("zalpha").value=zalf+shft}
if(shid=="zpf"){shft=5;document.getElementById("zalpha").value=zalf+shft}
if(shid=="xnf"){shft=-5;document.getElementById("xbeta").value=xbeta+shft}
if(shid=="xpf"){shft=5;document.getElementById("xbeta").value=xbeta+shft}
if(shid=="ynf"){shft=-5;document.getElementById("ygmma").value=ygmma+shft}
if(shid=="ypf"){shft=5;document.getElementById("ygmma").value=ygmma+shft}
if (hide=="rbt"){if (togl == "roff"){togl="ron"}
else {togl = "roff"}}
if (hide=="chkn"){if (togl == "coff"){togl="con"}
else {togl = "coff"}}
var seeMe=""
zalf= document.getElementById("zalpha").value*1xbeta= document.getElementById("xbeta").value*1
Mistretta 33
ygmma= document.getElementById("ygmma").value*1
zalf= zalf*Math.PI/180xbeta= xbeta*Math.PI/180ygmma= ygmma*Math.PI/180
nxb1= Math.cos(xbeta)nyb1= -Math.sin(xbeta)nxb2= Math.sin(xbeta)nyb2= Math.cos(xbeta)
nya= Math.sin(zalf)nza= Math.cos(zalf)
gxb1= Math.cos(ygmma)gyb1= -Math.sin(ygmma)gxb2= Math.sin(ygmma)gyb2= Math.cos(ygmma)
for (var v=0; v<pip; v=v+1){if (togl != "roff")
{rsx= lrnx[v]*nxb1 +lrny[v]*nyb1rsy= lrnx[v]*nxb2 +lrny[v]*nyb2rsz= lrnz[v]
rsy= rsy*nya +rsz*nza
var yrsx= rsx*gxb1 +rsy*gyb1var yrsy= rsx*gxb2 +rsy*gyb2
}else{yrsy = 600; yrsx=yrsy}
if (togl != "coff"){csx= lcnx[v]*nxb1 +lcny[v]*nyb1csy= lcnx[v]*nxb2 +lcny[v]*nyb2csz= lcnz[v]
csy= csy*nya +csz*nza
var ycsx= csx*gxb1 +csy*gyb1var ycsy= csx*gxb2 +csy*gyb2}
else{ycsy = 600; ycsx=ycsy}
Mistretta 34
seeMe=seeMe+"<di"+"v style='position:absolute; top:"+(ycsy*-1+500)+"; left:"+(ycsx+500)+"'>"+lcbf[v]+"<b>c</b></font></d"+"iv>"
seeMe=seeMe+"<di"+"v style='position:absolute; top:"+(yrsy*-1+500)+"; left:"+(yrsx+500)+"'>"+lrbf[v]+"<b>r</b></font></d"+"iv>"
}
document.getElementById("chase").innerHTML= seeMe
document.getElementById("cdiv").style.top= ycsy*-1+500document.getElementById("rdiv").style.top= yrsy*-1+500document.getElementById("cdiv").style.left= ycsx+500document.getElementById("rdiv").style.left= yrsx+500}
/* ***************************************** STOP FUNCTION, OUTPUT POINTS***************************************** */
function zxc() {clearInterval(g)document.getElementById("outp").innerHTML=pip-1
var bob="r=["
for (var x=0; x<lrnx.length; x=x+1){bob=bob+"("+lrnx[x]+","+lrny[x]+","+lrnz[x]+"),"}
bob=bob+"]\r\rc=["
for (var x=0; x<lcnx.length; x=x+1){bob=bob+"("+lcnx[x]+","+lcny[x]+","+lcnz[x]+"),"}
bob=bob+"]"document.getElementById("log").value=bob}
/* ***************************************** REFRESH VARIABLES***************************************** */
function reFrsh(){
Mistretta 35
vc=0; vr=0; a=0; b=0; g=0; x=0; d=0cnx=0; cny=0; cnz=0rnx=0; rny=0; rnz=0pnx=0; pny=0; pnz=0
n=1; f=0rbt=""; chkn=""; flag=0eqy=""; eqx=""; eqz="" Feqy=""; Feqx=""; Feqz=""n1=0; n2=0; n3=0; cv=0
document.getElementById("chase").innerHTML= ""document.getElementById("log").value= ""
document.getElementById("cdiv").style.top= -50document.getElementById("rdiv").style.top= -50
lrnx.length=0lrny.length=0lrnz.length=0lcnx.length=0lcny.length=0lcnz.length=0
}
</script></html>