var w,h,i,el,ratio,g,parser;var my={xMin:-1,xMax:1,xN:30,yMin:-1,yMax:1,yN:30,zMin:-4,zMax:4,zFact:1,svgQ:false,svgBtnQ:false};function grid3dMain(shapeName){var version='0.92';this.shapeName=typeof shapeName!=='undefined'?shapeName:'grid';w=550;h=550;var examples=[['sin(x/5)-cos(y)',[-5,5,-5,5],1],['x^2-y^2',[-5,5,-5,5],0.1],['-x*y*e^(-x^2-y^2)',[-5,5,-5,5],20],['cos(abs(x)+abs(y))',[-5,5,-5,5],1],['abs(x)-abs(y)',[-5,5,-5,5],0.5],['(x^2+y^2)^0.5',[-5,5,-5,5],1],['cos(x^2+y^2-0.5)',[-1,1,-1,1],1],[]];var exNo=6;my.fn=examples[exNo][0];var limits=examples[exNo][1];my.xMin=limits[0];my.xMax=limits[1];my.yMin=limits[2];my.yMax=limits[3];my.zFact=examples[exNo][2];var s="";s+=''
s+='
';s+='
';s+='
';s+='';s+='';s+='';s+='';if(my.svgBtnQ)s+='';s+='';s+='
';s+='
';s+="Coloring: ";s+=getDropdownHTML(['Multi','Seethru','Two','Glass','PureGlass','Shaded'],'clrChg','clrType');s+='
';s+='
';s+='';s+='
';s+='
';my.edits=[['xMin',my.xMin],['xMax',my.xMax],['xN',my.xN],['yMin',my.yMin],['yMax',my.yMax],['yN',my.yN],['zFact',my.zFact]];for(var i=0;i
'+e[0]+': ';s+='';if(!((i+1)%3))s+='
';}
s+='
';s+='';s+='';s+='
';s+='';s+='
© 2020 MathsIsFun.com v'+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);parser=new Parser();this.transMat=[[1,0,0],[0,1,0],[0,0,-1],[0,0,0]];this.f=500;this.shapes=[];this.clrs=["#ff0000","#0000ff","#ff9900","#00ff00","#ffff00","#660066","#99ff00","#0099ff","#00ff99","#9900ff","#ff0099","#006666","#666600","#990000","#009999","#999900","#003399","#ff00ff","#993333","#330099"];this.dragQ=false;this.explodeQ=false;this.axesQ=false;dragQ=false;draggingQ=false;prevmouseX=0;prevmouseY=0;svg=new SVG();this.poly=new Poly();xAngle=2;yAngle=4;zAngle=0;el.addEventListener('touchstart',ontouchstart,false);el.addEventListener('touchmove',ontouchmove,false);el.addEventListener('mousedown',onmouseDown,false);el.addEventListener('mousemove',onmouseMove,false);el.addEventListener("mouseup",onmouseUp,false);init();}
function chgVal(i,val){var name=my.edits[i][0];if(name=='xN'||name=='yN'){val=parseInt(val);if(val<1)val=1;if(val>100)val=100;}
my[name]=parseFloat(val);}
function reset(){this.transMat=[[1,0,0],[0,1,0],[0,0,-1],[0,0,0]];g.clearRect(0,0,el.width,el.height);drawShapes();}
function ontouchstart(evt){draggingQ=true;var touch=evt.targetTouches[0];var bRect=el.getBoundingClientRect();prevmouseX=(touch.clientX-bRect.left)*(el.width/ratio/bRect.width);prevmouseY=(touch.clientY-bRect.top)*(el.height/ratio/bRect.height);}
function ontouchmove(evt){var touch=evt.targetTouches[0];evt.clientX=touch.clientX;evt.clientY=touch.clientY;evt.touchQ=true;onmouseMove(evt);evt.preventDefault();}
function onmouseDown(evt){draggingQ=true;prevmouseX=mouseX;prevmouseY=mouseY;}
function onmouseUp(evt){draggingQ=false;}
function onmouseMove(evt){var bRect=el.getBoundingClientRect();mouseX=(evt.clientX-bRect.left)*(el.width/ratio/bRect.width);mouseY=(evt.clientY-bRect.top)*(el.height/ratio/bRect.height);if(dragQ){if(draggingQ){settransMat(-(prevmouseY-mouseY)*3,(prevmouseX-mouseX)*3,0,transMat);prevmouseX=mouseX;prevmouseY=mouseY;g.clearRect(0,0,el.width,el.height);drawShapes();}}else{yAngle=-(mouseX-w/2)/25;xAngle=(mouseY-h/2)/25;}}
function editpop(){console.log("editpop");var pop=document.getElementById('editpop');pop.style.transitionDuration="0.3s";pop.style.opacity=1;pop.style.zIndex=12;pop.style.left='100px';document.getElementById('funbox').value=my.fn;}
function editYes(){var pop=document.getElementById('editpop');pop.style.opacity=0;pop.style.zIndex=1;pop.style.left='-500px';my.fn=document.getElementById('funbox').value;console.log("editYes",my.fn);setShapesFromPoly();g.clearRect(0,0,el.width,el.height);drawShapes();}
function editNo(){var pop=document.getElementById('editpop');pop.style.opacity=0;pop.style.zIndex=1;pop.style.left='-500px';}
function toggleDrag(){dragQ=!dragQ;toggleBtn("dragBtn",dragQ);if(dragQ){document.getElementById("dragBtn").innerHTML='Drag';}else{document.getElementById("dragBtn").innerHTML='Spin';}}
function toggleExplode(){this.explodeQ=!this.explodeQ;toggleBtn("explodeBtn",this.explodeQ);restart();}
function toggleAxes(){this.axesQ=!this.axesQ;toggleBtn("axesBtn",this.axesQ);restart();}
function toggleBtn(btn,onq){if(onq){document.getElementById(btn).classList.add("hi");document.getElementById(btn).classList.remove("lo");}else{document.getElementById(btn).classList.add("lo");document.getElementById(btn).classList.remove("hi");}}
function getDropdownHTML(opts,funcName,id){var s='';s+='';return s;}
function clrChg(){var el=document.getElementById('clrType');if(el.selectedIndex==-1)
return null;var t=el.options[el.selectedIndex].text;setClrs(t);g.clearRect(0,0,el.width,el.height);drawShapes();}
function getClrType(){if(this.curvyQ||this.flatyQ){if(this.shapeName=='plane'){return "Glass";}else{return "Seethru";}}else{var div=document.getElementById('clrType');if(div.selectedIndex==-1)return 'Multi';return div.options[div.selectedIndex].text;}}
function init(){shapes=[];poly.shapeType=shapeName;setShapesFromPoly();settransMat(200,50,0,transMat);g.clearRect(0,0,el.width,el.height);drawShapes();this.frameNo=0;animate();}
function restart(){shapes=[];poly.shapeType=shapeName;setShapesFromPoly();g.clearRect(0,0,el.width,el.height);drawShapes();}
function animate(){this.frameNo++;if(dragQ){}else{settransMat(xAngle,yAngle,zAngle,transMat);g.clearRect(0,0,el.width,el.height);drawShapes();}
if(this.frameNo<1e8){requestAnimationFrame(animate);}}
function drawShapes(){var prevDepth=0;var sortNeededQ=false;for(var i=0,len=shapes.length;i0){if(shape.depthmy.zMax)my.zMax=z;pts[n]=[x,y,z];}}
my.nExtra=pts.length;var C=[];for(i=0;i>0)+1;var grn=(dark*255>>0)+1;angle=this.getNormalAngle(this.pts,1);dark=(1-angle/Math.PI);var blu=(dark*255>>0)+1;this.fillClr='rgba('+red+','+grn+','+blu+','+alpha+')';this.svgClr='rgb('+red+','+grn+','+blu+')';this.svgAlpha=alpha;}
Shape3D.prototype.getNormalAngle=function(pts,dimN){var a=[pts[1].x-pts[0].x,pts[1].y-pts[0].y,pts[1].z-pts[0].z];var b=[pts[2].x-pts[1].x,pts[2].y-pts[1].y,pts[2].z-pts[1].z];var cross=[a[1]*b[2]-a[2]*b[1],a[2]*b[0]-a[0]*b[2],a[0]*b[1]-a[1]*b[0]];var mag=Math.sqrt(cross[0]*cross[0]+cross[1]*cross[1]+cross[2]*cross[2]);var theta=Math.acos(cross[dimN]/mag);return theta;}
Shape3D.prototype.calcCentroid=function(){centroid=new Pt3d();for(var i=0;i0){centroid.x/=this.pts.length;centroid.y/=this.pts.length;centroid.z/=this.pts.length;}};Shape3D.prototype.to2d=function(){var xsum=0;var ysum=0;var zsum=0;var clips=[];var zMin=Number.MAX_VALUE;var zMax=-Number.MAX_VALUE;var i=0;var ptRot;while(i2){g.beginPath();for(i=0,len=pt2s.length;i="0"&&c<="9"){thisType="N";}else{if(this.operators.indexOf(c)>=0){if(c=="-"){thisType="-";}else{thisType="O";}}else{if(c=="."||c==this.Variable){thisType="N";}else{thisType="C";}}
if(c=="("){thisType="(";}
if(c==")"){thisType=")";}}
x+=thisType;if(prevType=="("&&thisType=="-"){y+="0";}
if(OpenQ){switch(thisType){case "N":break;default:y+=")";OpenQ=false;}}
if(prevType=="O"&&thisType=="-"){y+="(0";OpenQ=true;}
y+=c;prevType=thisType;}
if(OpenQ){y+=")";OpenQ=false;}
return(y);};Parser.prototype.fixImplicitMultply=function(s){var x=s+"\n";var y="";var prevType="?";var prevName="";var thisType="?";var thisName="";for(var i=0;i="0"&&c<="9"){thisType="N";}else{if(this.operators.indexOf(c)>=0){thisType="O";thisName="";}else{thisType="C";thisName+=c;}
if(c=="("){thisType="(";}
if(c==")"){thisType=")";}}
x+=thisType;if(prevType=="N"&&thisType=="C"){y+="*";thisName="";}
if(prevType=="N"&&thisType=="("){y+="*";}
if(prevType==")"&&thisType=="("){y+="*";}
if(thisType=="("){switch(prevName){case "i":case "pi":case "e":case "a":case this.Variable:y+="*";break;}}
y+=c;prevType=thisType;prevName=thisName;}
return(y);};Parser.prototype.reset=function(){this.tempNode=[];this.errMsg="";};Parser.prototype.parse=function(s){if(s==""){return new MathNode("real","0",this.radiansQ);}
if(isNumeric(s)){return new MathNode("real",s,this.radiansQ);}
if(s.charAt(0)=="$"){if(isNumeric(s.substr(1))){return this.tempNode[Number(s.substr(1))];}}
var sLo=s.toLowerCase();if(sLo.length==1){if(sLo>="a"&&sLo<="z"){return new MathNode("var",sLo,this.radiansQ);}}
switch(sLo){case "pi":return new MathNode("var",sLo,this.radiansQ);break;}
var bracStt=s.lastIndexOf("(");if(bracStt>-1){var bracEnd=s.indexOf(")",bracStt);if(bracEnd<0){this.errMsg+="Missing ')'\n";return new MathNode("real","0",this.radiansQ);}
var isParam=false;if(bracStt==0){isParam=false;}else{var prefix=s.substr(bracStt-1,1);isParam=this.operators.indexOf(prefix)<=-1;}
if(!isParam){this.tempNode.push(this.parse(s.substr(bracStt+1,bracEnd-bracStt-1)));return this.parse(s.substr(0,bracStt)+"$"+(this.tempNode.length-1).toString()+s.substr(bracEnd+1,s.length-bracEnd-1));}else{var startM=-1;for(var u=bracStt-1;u>-1;u--){var found=this.operators.indexOf(s.substr(u,1));if(found>-1){startM=u;break;}}
var nnew=new MathNode("func",s.substr(startM+1,bracStt-1-startM),this.radiansQ);nnew.addchild(this.parse(s.substr(bracStt+1,bracEnd-bracStt-1)));this.tempNode.push(nnew);return this.parse(s.substr(0,startM+1)+"$"+(this.tempNode.length-1).toString()+s.substr(bracEnd+1,s.length-bracEnd-1));}}
var k;var k1=s.lastIndexOf("+");var k2=s.lastIndexOf("-");if(k1>-1||k2>-1){if(k1>k2){k=k1;var nnew=new MathNode("op","add",this.radiansQ);nnew.addchild(this.parse(s.substr(0,k)));nnew.addchild(this.parse(s.substr(k+1,s.length-k-1)));return nnew;}else{k=k2;nnew=new MathNode("op","sub",this.radiansQ);nnew.addchild(this.parse(s.substr(0,k)));nnew.addchild(this.parse(s.substr(k+1,s.length-k-1)));return nnew;}}
k1=s.lastIndexOf("*");k2=s.lastIndexOf("../index.html");if(k1>-1||k2>-1){if(k1>k2){k=k1;var nnew=new MathNode("op","mult",this.radiansQ);nnew.addchild(this.parse(s.substr(0,k)));nnew.addchild(this.parse(s.substr(k+1,s.length-k-1)));return nnew;}else{k=k2;var nnew=new MathNode("op","div",this.radiansQ);nnew.addchild(this.parse(s.substr(0,k)));nnew.addchild(this.parse(s.substr(k+1,s.length-k-1)));return nnew;}}
k=s.indexOf("^");if(k>-1){var nnew=new MathNode("op","pow",this.radiansQ);nnew.addchild(this.parse(s.substr(0,k)));nnew.addchild(this.parse(s.substr(k+1,s.length-k-1)));return nnew;}
if(isNumeric(s)){return new MathNode("real",s,this.radiansQ);}else{if(s.length==0){return new MathNode("real","0",this.radiansQ);}else{this.errMsg+="'"+s+"' is not a number.\n";return new MathNode("real","0",this.radiansQ);}}};function MathNode(typ,val,radQ){this.tREAL=0;this.tVAR=1;this.tOP=2;this.tFUNC=3;this.radiansQ=true;this.setNew(typ,val,radQ);}
MathNode.prototype.setNew=function(typ,val,radQ){this.radiansQ=typeof radQ!=='undefined'?radQ:true;this.clear();switch(typ){case "real":this.typ=this.tREAL;this.r=Number(val);break;case "var":this.typ=this.tVAR;this.v=val;break;case "op":this.typ=this.tOP;this.op=val;break;case "func":this.typ=this.tFUNC;this.op=val;break;}
return(this);};MathNode.prototype.clear=function(){this.r=1;this.v="";this.op="";this.child=[];this.childCount=0;};MathNode.prototype.addchild=function(n){this.child.push(n);this.childCount++;return(this.child[this.child.length-1]);};MathNode.prototype.getLevelsHigh=function(){var lvl=0;for(var i=0;i0){var parq=false;if(this.op=="add")parq=true;if(this.op=="sub")parq=true;if(prevop=="div")parq=true;if(noparq)parq=false;if(this.typ==this.tFUNC)parq=true;if(this.typ==this.tOP){}else{s+=this.fmt(true);}
if(parq)s+="(";for(var i=0;i0)s+=this.fmt();s+=this.child[i].walkFmta(false,this.op);if(this.typ==this.tFUNC||(parq&&i>0)){s+=")";}}}else{s+=this.fmt();if(prevop=="sin"||prevop=="cos"||prevop=="tan"){if(this.radiansQ){s+=" rad";}else{s+="°";}}}
return s;};MathNode.prototype.walkNodesFmt=function(level){var s="";for(var i=0;i2){f*=i;}
return f;}
function isNumeric(n){return!isNaN(parseFloat(n))&&isFinite(n);}
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;i";this.txt=this.getHeader();}
SVG.prototype.getHeader=function(){var s="";s+='\n';s+='\n';s+='