var w,h,ratio,i,s,el,g,div,dragQ,game,my={};function hyperbolaMain(imode){my.version='0.71';mode=typeof imode!=='undefined'?imode:'foci';w=360;h=360;canvasid="canvas"+mode;titleid="title"+mode;infoid="info"+mode;s="";s+='
';s+='
';s+='
';s+='
';s+='
Drag The Points!
';s+='
';s+='
Difference:
'
s+='
';s+='
';s+='
© 2018 MathsIsFun.com v'+my.version+'
';s+='
';document.write(s);el=document.getElementById(canvasid);ratio=2;el.width=w*ratio;el.height=h*ratio;el.style.width=w+"px";el.style.height=h+"px";g=el.getContext("2d");g.setTransform(ratio,0,0,ratio,0,0);theCanvas=el;context=g;dragIndex=0;numShapes=3;shapes=[];ptData=[];switch(mode){case "foci":case "arc":case "tangent":ptData=[[80,170,"F"],[260,130,"G"],[200,100,"P"]];break;case "axes":case "semiaxes":ptData=[[40,170,"A"],[260,130,"B"],[150,100,"C"],[230,230,"D"]];break;default:ptData=[[80,170,"F"],[260,130,"G"],[200,100,"P"]];}
numShapes=ptData.length;my.diff=0.5;makeShapes(ptData);drawShapes();theCanvas.addEventListener("mousedown",mouseDownListener,false);theCanvas.addEventListener('touchstart',ontouchstart,false);theCanvas.addEventListener("mousemove",domousemove,false);}
function onDiffChg(n,v){v=Number(v);my.diff=v;drawShapes();}
function reset(){makeShapes();drawShapes();}
function ontouchstart(evt){var touch=evt.targetTouches[0];evt.clientX=touch.clientX;evt.clientY=touch.clientY;evt.touchQ=true;mouseDownListener(evt)}
function ontouchmove(evt){var touch=evt.targetTouches[0];evt.clientX=touch.clientX;evt.clientY=touch.clientY;evt.touchQ=true;mouseMoveListener(evt);evt.preventDefault();};function ontouchend(evt){theCanvas.addEventListener('touchstart',ontouchstart,false);window.removeEventListener("touchend",ontouchend,false);if(dragging){dragging=false;window.removeEventListener("touchmove",ontouchmove,false);}}
function domousemove(e){document.body.style.cursor="default";var bRect=theCanvas.getBoundingClientRect();mouseX=(e.clientX-bRect.left)*(el.width/ratio/bRect.width);mouseY=(e.clientY-bRect.top)*(el.height/ratio/bRect.height);for(i=0;ihighestIndex){dragHoldX=mouseX-shapes[i].x;dragHoldY=mouseY-shapes[i].y;highestIndex=i;dragIndex=i;}}}
if(dragging){if(evt.touchQ){window.addEventListener('touchmove',ontouchmove,false);}else{window.addEventListener("mousemove",mouseMoveListener,false);}}
if(evt.touchQ){theCanvas.removeEventListener("touchstart",ontouchstart,false);window.addEventListener("touchend",ontouchend,false);}else{theCanvas.removeEventListener("mousedown",mouseDownListener,false);window.addEventListener("mouseup",mouseUpListener,false);}
if(evt.preventDefault){evt.preventDefault();}
else if(evt.returnValue){evt.returnValue=false;}
return false;}
function mouseUpListener(evt){theCanvas.addEventListener("mousedown",mouseDownListener,false);window.removeEventListener("mouseup",mouseUpListener,false);if(dragging){dragging=false;window.removeEventListener("mousemove",mouseMoveListener,false);}}
function mouseMoveListener(evt){var posX;var posY;var shapeRad=12;var minX=shapeRad;var maxX=theCanvas.width-shapeRad;var minY=shapeRad;var maxY=theCanvas.height-shapeRad;var bRect=theCanvas.getBoundingClientRect();mouseX=(evt.clientX-bRect.left)*(el.width/ratio/bRect.width);mouseY=(evt.clientY-bRect.top)*(el.height/ratio/bRect.height);posX=mouseX-dragHoldX;posX=(posXmaxX)?maxX:posX);posY=mouseY-dragHoldY;posY=(posYmaxY)?maxY:posY);shapes[dragIndex].x=posX;shapes[dragIndex].y=posY;drawShapes();}
function hitTest(shape,mx,my){var dx;var dy;dx=mx-shape.x;dy=my-shape.y;return(dx*dx+dy*dya2)
a2+=2*Math.PI;pt.angleIn=a1;pt.angleOut=a2;}}
function getClockwise(pts){var numPoints=pts.length;var count=0;for(var i=0;i0){count++;}}
if(count>0)
return(1);if(count==0)
return(0);return(-1);}
function getSides(pts){var numPoints=pts.length;var sides=[];for(var i=0;imaxNo){currNo=minNo+(currNo-minNo)%range;}
return currNo;}
function constrain(min,val,max){return(Math.min(Math.max(min,val),max));}
function Line(pt1,pt2){this.a=pt1;this.b=pt2;}
Line.prototype.getDist=function(){return dist(this.b.x-this.a.x,this.b.y-this.a.y);}
Line.prototype.getMidPt=function(){return new Pt((this.a.x+this.b.x)/2,(this.a.y+this.b.y)/2);}
Line.prototype.setMidPt=function(toPt){var fromPt=this.getMidPt();this.a.x+=toPt.x-fromPt.x;this.a.y+=toPt.y-fromPt.y;this.b.x+=toPt.x-fromPt.x;this.b.y+=toPt.y-fromPt.y;}
Line.prototype.rotateMidMe=function(angle){var midPt=this.getMidPt();this.a.translateMe(midPt,false);this.b.translateMe(midPt,false);this.a.rotateMe(angle);this.b.rotateMe(angle);this.a.translateMe(midPt);this.b.translateMe(midPt);}
Line.prototype.getClosestPoint=function(toPt,inSegmentQ){var AP=toPt.translate(this.a,false);var AB=this.b.translate(this.a,false);var ab2=AB.x*AB.x+AB.y*AB.y;var ap_ab=AP.x*AB.x+AP.y*AB.y;var t=ap_ab/ab2;if(inSegmentQ){t=constrain(0,t,1);}
closest=this.a.translate(AB.multiply(t));return closest;}
Line.prototype.setLen=function(newLen,fromMidQ){fromMidQ=typeof fromMidQ!=='undefined'?fromMidQ:true;var len=this.getLength();if(fromMidQ){var midPt=this.getMidPt();var halfPt=new Pt(this.a.x-midPt.x,this.a.y-midPt.y);halfPt.multiplyMe(newLen/len);this.a=midPt.translate(halfPt);this.b=midPt.translate(halfPt,false);}else{var diffPt=new Pt(this.a.x-this.b.x,this.a.y-this.b.y);diffPt.multiplyMe(newLen/len);this.b=this.a.translate(diffPt,false);}}
Line.prototype.getAngle=function(){return Math.atan2(this.b.y-this.a.y,this.b.x-this.a.x);}
function updateFoci(){var d0=shapes[0];var d1=shapes[1];var dm=shapes[2];var isCircQ=false;if(dist(d0.x-d1.x,d0.y-d1.y)<2){console.log("update: make d0 and d1 very close to simulate circle without problems of divide by zero etc");d0.x=d1.x+0.1;d0.y=d1.y+0.1;isCircQ=true;}
var ln=new Line(d0,d1);var distFoci=ln.getDist();ln.setLen(2000);g.strokeStyle='blue';if(!isCircQ){g.beginPath();g.moveTo(ln.a.x,ln.a.y);g.lineTo(ln.b.x,ln.b.y);g.stroke();}
var mPt=new Pt();mPt.setAvg([d0,d1]);var pPt=new Pt(dm.x,dm.y);var nearPt=new Pt(0,0);var pDist=1000;var eccentricity=2
var a=1.2*distFoci/2/eccentricity;var b=a;var k=distFoci*my.diff;var hPts=getHyperbola2Pts(distFoci,k);var pts=[];for(var i=0;iw)continue;if(pt.y<0)continue;if(pt.y>h)continue;if(pt.dist(pPt)Math.PI)intAngle-=Math.PI;var da=dist(tanLn.a.x-d0.x,tanLn.a.y-d0.y);var db=dist(tanLn.b.x-d0.x,tanLn.b.y-d0.y);if(datoAngle){while(fromAngle>toAngle){fromAngle-=2*Math.PI;}}
var steps=Math.max(1,parseInt((toAngle-fromAngle)*20));for(var i=0;i<=steps;i++){var radians=fromAngle+(toAngle-fromAngle)*(i/steps);var thisX=midX+(1/Math.cos(radians)*a);var thisY=midY-(Math.tan(radians)*b);points.push(new Pt(thisX,thisY));}
return points;}
function updateAxes(){var d0=new Pt(shapes[0].x,shapes[0].y);var d1=new Pt(shapes[1].x,shapes[1].y);var d2=new Pt(shapes[2].x,shapes[2].y);var d3=new Pt(shapes[3].x,shapes[3].y);if(dragIndex==d2||dragIndex==d3){var tp=d0;d0=d2;d2=tp;tp=d1;d1=d3;d3=tp;}
var majorLn=new Line(d0,d1);var minorLn=new Line(d2,d3);var majorLen=majorLn.getDist();var minorLen=minorLn.getDist();var mPt=new Pt();mPt.setAvg([d0,d1]);var pts=getArcPts(mPt.x,mPt.y,majorLen/2,minorLen/2,0,Math.PI*2);pts=rotatePts(pts,mPt.x,mPt.y,-majorLn.getAngle());g.strokeStyle='rgba(200,100,0,1)';g.beginPath();drawPts(g,pts);g.stroke();minorLn.setMidPt(mPt);minorLn.rotateMidMe(minorLn.getAngle()-(majorLn.getAngle()+Math.PI/2));shapes[2].x=minorLn.a.x;shapes[2].y=minorLn.a.y;shapes[3].x=minorLn.b.x;shapes[3].y=minorLn.b.y;if(majorLentoAngle){while(fromAngle>toAngle){fromAngle-=2*Math.PI;}}
var steps=Math.max(1,parseInt((toAngle-fromAngle)*10));for(var i=0;i<=steps;i++){var radians=fromAngle+(toAngle-fromAngle)*(i/steps);var thisX=midX+(Math.cos(radians)*radiusX);var thisY=midY-(Math.sin(radians)*radiusY);points.push(new Pt(thisX,thisY));}
return points;}
function rotatePts(pts,midX,midY,rot){var newPts=[];for(var i=0;icentralVal+limitVal)
return false;return true;}
CanvasRenderingContext2D.prototype.drawArrow=function(x0,y0,totLen,shaftHt,headLen,headHt,angle,sweep,invertQ){var g=this;var pts=[[0,0],[-headLen,-headHt/2],[-headLen+sweep,-shaftHt/2],[-totLen,-shaftHt/2],[-totLen,shaftHt/2],[-headLen+sweep,shaftHt/2],[-headLen,headHt/2],[0,0]];if(invertQ){pts.push([0,-headHt/2],[-totLen,-headHt/2],[-totLen,headHt/2],[0,headHt/2]);}
for(var i=0;i90){HiGraphics.lineStyle(2,0xff0000);d=Math.max(20,30-(angDeg-90)/6);}else{HiGraphics.lineStyle(2,0x4444FF);}
g.fillStyle="rgba(0, 0, 255, 0.3)";g.beginPath();g.moveTo(x,y);g.arc(x,y,d,sttAngle,sttAngle+angle,false);g.closePath();g.fill();}
var ang=Math.round(angle*180/Math.PI,this.dec);var angDescr=ang+"° + "
var aMid=sttAngle+(angle/2);var txtPt=new Pt(0,0)
txtPt.x=x+(d+15)*Math.cos(aMid)-0
txtPt.y=y+(d+15)*Math.sin(aMid)-0
g.font="bold 16px Arial";g.fillStyle="rgba(0, 0, 255, 1)";g.fillText(Math.round(ang)+"°",txtPt.x-10,txtPt.y+5);};function drawAnglePts(g,pts,alsoEndsQ){alsoEndsQ=typeof alsoEndsQ!=='undefined'?alsoEndsQ:false;setAngles(pts);for(var i=0;i90){g.lineStyle="#ff0000";g.lineWidth=1;d=Math.max(20,30-(angDeg-90)/6);}else{g.lineStyle="#4444FF";g.lineWidth=1;}
g.fillStyle="rgba(0, 0, 255, 0.3)";g.beginPath();g.moveTo(x,y);var sttAngle=pts[i].angleOut;var angle=pts[i].angleOut-pts[i].angleIn;if(sttAngle>angle){while(sttAngle>angle){sttAngle-=2*Math.PI;}}
g.arc(x,y,d,sttAngle,sttAngle-angle,true);g.closePath();g.fill();var aMid=(pts[i].angleIn+pts[i].angleOut)/2;var ax=pts[i].x+(d+15)*Math.cos(aMid);var ay=pts[i].y+(d+15)*Math.sin(aMid);g.font="16px Arial";g.textAlign='center';g.fillStyle="rgba(0, 0, 255, 1)";g.fillText(Math.round(angle*180/Math.PI)+"°",ax,ay);}}}
function setAngles(pts){var CW=getClockwise(pts);var numPoints=pts.length;var angles=[];for(var i=0;ia2)
a2+=2*Math.PI;pt.angleIn=a1;pt.angleOut=a2;}}
CanvasRenderingContext2D.prototype.drawBox=function(midX,midY,radius,angle){g.beginPath();var pts=[[0,0],[Math.cos(angle),Math.sin(angle)],[Math.cos(angle)+Math.cos(angle+Math.PI/2),Math.sin(angle)+Math.sin(angle+Math.PI/2)],[Math.cos(angle+Math.PI/2),Math.sin(angle+Math.PI/2)],[0,0]];for(var i=0;i