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+='\n';s+="SVG Output\n";return s;};SVG.prototype.lineStyle=function(thick,clr,alpha){if(thick==0)thick=0.2;this.lineWidth=thick;this.lineClr=clr;};SVG.prototype.beginFill=function(clr,alpha){fillClr=clr;};SVG.prototype.endFill=function(){};SVG.prototype.moveTo=function(x,y){if(this.line.length>1)this.polyline();this.line.push([x,y]);this.currStyle=this.getStyle()};SVG.prototype.lineTo=function(x,y){this.line.push([x,y]);};SVG.prototype.drawRect=function(x,y,width,height){txt+='';};SVG.prototype.drawText=function(x,y,text,rotate){txt+='';txt+=text;txt+="";};SVG.prototype.getStyle=function(){var s="";s+="opacity:1;fill:#"+fillClr.toString(16)+";fill-opacity:1;fill-rule:nonzero;";s+="stroke:#"+lineClr.toString(16)+"; stroke-width:"+lineWidth.toString()+"; stroke-linecap:butt; stroke-linejoin:miter; stroke-opacity:1; visibility:visible;";return s};SVG.prototype.getFontStyle=function(){var s="";s+="font-size:30px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;";s+="text-align:start; line-height:100.00000381%;";s+="opacity:1; fill:#0000ff; fill-opacity:1; fill-rule:nonzero; stroke:none;";s+="visibility:visible;display:inline;font-family:Komika Text;";return(s);};SVG.prototype.polyline=function(){var s="";s+="0)s+=", ";var pt=line[i];s+=pt.x.toPrecision(5);s+=" ";s+=pt.y.toPrecision(5);} s+="' ";s+=this.getStyle();s+=" />";s+="\n";this.txt+=s;};SVG.prototype.getStyle=function(){s='';s+="stroke-width='"+this.lineWidth+"' ";s+="stroke='"+this.lineClr+"' ";if(this.fillClr.length>0){s+="fill='"+this.fillClr+"' ";s+="fill-opacity='"+this.fillAlpha+"' ";} return s;};SVG.prototype.group=function(id){if(inGroupQ){txt+="\n";} txt+="";inGroupQ=true;};SVG.prototype.getText=function(){if(this.line.length>1)this.polyline();if(this.inGroupQ){this.txt+="\n";} return(this.txt+this.ftrStr);};