hulet
Version:
The canvas as the Cartesian plane
1 lines • 6.84 kB
JavaScript
!function(f){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=f();else if("function"==typeof define&&define.amd)define([],f);else{("undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this).hulet=f()}}((function(){return function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,(function(r){return o(e[i][1][r]||r)}),p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o}({1:[function(require,module,exports){const{form:form}=require("./math");class Camera{constructor(Canvas){this.Canvas=Canvas,this.center=[0,0],this.zoom=Canvas.width/Canvas.cwidth}transform(vec){let nVec=form.translate(vec,form.negate(this.center));return nVec=form.scale(nVec,1/this.zoom),nVec=[nVec[0],-nVec[1]],nVec=form.translate(nVec,[this.Canvas.cwidth/2,this.Canvas.cheight/2]),nVec}invTransform(vec){let nVec=form.translate(vec,[-this.Canvas.cwidth/2,-this.Canvas.cheight/2]);return nVec=[nVec[0],-nVec[1]],nVec=form.scale(nVec,this.zoom),nVec=form.translate(nVec,this.center),nVec}getEndpoints(){let w=this.Canvas.cwidth,h=this.Canvas.cheight;return[[w,0],[0,0],[0,h],[w,h]].map((endpoint=>this.invTransform(endpoint)))}}module.exports={Cartesian:class Cartesian{constructor(ctx,w,h){this.ctx=ctx,this.cwidth=ctx.canvas.width,this.cheight=ctx.canvas.height,this.width=w,this.height=h,this.init(),this.pointStyle="#c70000",this.pointSize=2.5,this.strokeStyle="black",this.lineWidth=2.5,this.fillStyle="rgba(200, 0, 0, 0.5)",this.stroke=!0,this.fill=!0}init(){this.ctx.save(),this.ctx.fillStyle="white",this.ctx.fillRect(0,0,this.cwidth,this.cheight),this.ctx.restore(),this.Camera=new Camera(this)}clear(){this.ctx.clearRect(0,0,this.cwidth,this.cheight)}point(vec){let[x,y]=this.Camera.transform(vec);this.ctx.beginPath(),this.ctx.arc(x,y,this.pointSize,0,2*Math.PI),this.ctx.fillStyle=this.pointStyle,this.ctx.fill()}segment(u,v){let[x1,y1]=this.Camera.transform(u),[x2,y2]=this.Camera.transform(v);this.ctx.beginPath(),this.ctx.moveTo(x1,y1),this.ctx.lineTo(x2,y2),this.ctx.strokeStyle=this.strokeStyle,this.ctx.lineWidth=this.lineWidth,this.ctx.stroke()}ray(u,v){let[x1,y1]=u,[x2,y2]=v;if(x1===x2){let end,endY,dir=y2>y1?1:-1,endpoints=this.Camera.getEndpoints();endY=1===dir?endpoints[0][1]:endpoints[2][1],end=[x1,endY],this.segment(u,end)}let m=(y2-y1)/(x2-x1);let end,endX,dir=x2>x1?1:-1,endpoints=this.Camera.getEndpoints();var x;endX=1===dir?endpoints[0][0]:endpoints[1][0],end=[endX,(x=endX,y1+m*(x-x1))],this.segment(u,end)}line(u,v){this.ray(u,v),this.ray(v,u)}polygon(vertices){let coords=vertices.map((v=>this.Camera.transform(v)));this.ctx.beginPath(),this.ctx.moveTo(coords[0][0],coords[0][1]);for(let i=1;i<coords.length;i++)this.ctx.lineTo(coords[i][0],coords[i][1]);this.ctx.closePath(),this.fill&&(this.ctx.fillStyle=this.fillStyle,this.ctx.fill()),this.stroke&&(this.ctx.strokeStyle=this.strokeStyle,this.ctx.lineWidth=this.lineWidth,this.ctx.stroke())}circle(c,r){let[x,y]=this.Camera.transform(c);this.ctx.beginPath(),this.ctx.arc(x,y,r/this.Camera.zoom,0,2*Math.PI),this.fill&&(this.ctx.fillStyle=this.fillStyle,this.ctx.fill()),this.stroke&&(this.ctx.strokeStyle=this.strokeStyle,this.ctx.lineWidth=this.lineWidth,this.ctx.stroke())}axes(x=!0,y=!0,style="black"){let oldStyle=this.strokeStyle;this.strokeStyle=style;let endpoints=this.Camera.getEndpoints();x&&this.segment([endpoints[1][0],0],[endpoints[0][0],0]),y&&this.segment([0,endpoints[2][1]],[0,endpoints[0][1]]),this.strokeStyle=oldStyle}grid(delta,x=!0,y=!0,style="rgba(0,0,0,0.25)"){2===arguments.length&&(style=arguments[1],x=!0,y=!0);let oldStyle=this.strokeStyle;this.strokeStyle=style;let endpoints=this.Camera.getEndpoints(),x1=Math.round(endpoints[1][0]/delta)*delta,y1=Math.round(endpoints[2][1]/delta)*delta,x2=Math.round(endpoints[0][0]/delta)*delta,y2=Math.round(endpoints[0][1]/delta)*delta;if(x)if(x1<=0&&x2>=0){for(let x=0;x<x2;x+=delta)this.segment([x,y1],[x,y2]);for(let x=0;x>x1;x-=delta)this.segment([x,y1],[x,y2])}else for(let x=x1+delta;x<x2;x+=delta)this.segment([x,y1],[x,y2]);if(y)if(y1<=0&&y2>=0){for(let y=0;y<y2;y+=delta)this.segment([x1,y],[x2,y]);for(let y=0;y>y1;y-=delta)this.segment([x1,y],[x2,y])}else for(let y=y1+delta;y<y2;y+=delta)this.segment([x1,y],[x2,y]);this.strokeStyle=oldStyle}label(delta,X=!0,Y=!0,style="black",font="16px times",offset=5){2==arguments.length?(style=arguments[1],X=!0,Y=!0):3==arguments.length&&"string"==typeof arguments[1]&&(style=arguments[1],font=arguments[2],X=!0,Y=!0),this.ctx.save(),this.ctx.font=font,this.ctx.fillStyle=style;let endpoints=this.Camera.getEndpoints(),x1=Math.round(endpoints[1][0]/delta)*delta,y1=Math.round(endpoints[2][1]/delta)*delta,x2=Math.round(endpoints[0][0]/delta)*delta,y2=Math.round(endpoints[0][1]/delta)*delta;if(X)for(let x=x1;x<x2;x+=delta){if(this.ctx.textAlign="center",this.ctx.textBaseline="top",0===x){this.ctx.textAlign="right",this.ctx.textBaseline="top";let pos=this.Camera.transform([0,0]),dist=delta/this.Camera.zoom;this.ctx.fillText(x,pos[0]-offset,pos[1]+offset,dist);continue}let pos=this.Camera.transform([x,0]),dist=delta/this.Camera.zoom;this.ctx.fillText(x,pos[0],pos[1]+offset,dist)}if(Y)for(let y=y1;y<y2;y+=delta){if(0==y&&X)continue;let pos=this.Camera.transform([0,y]);this.ctx.textAlign="right",this.ctx.textBaseline="middle",this.ctx.fillText(y,pos[0]-offset,pos[1])}this.ctx.restore()}parametric(f,T,k=256){let start=T[0],span=T[1]-T[0];for(let i=0;i<k;i++){let t=start+i*span/k,[x,y]=f(t),tPrime=start+(i+1)*span/k,[xPrime,yPrime]=f(tPrime);this.segment([x,y],[xPrime,yPrime])}}graph(f,X,Y,k=256){if(void 0===X||void 0===Y){let endpoints=this.Camera.getEndpoints();void 0===X&&(X=[endpoints[1][0],endpoints[0][0]]),void 0===Y&&(Y=[endpoints[2][1],endpoints[0][1]])}let start=X[0],span=X[1]-X[0];for(let i=0;i<=k;i++){let x=start+i*span/k;if(x<X[0]||x>X[1])continue;let y=f(x);if(y<Y[0]||y>Y[1])continue;let xPrime=start+(i+1)*span/k,yPrime=f(xPrime);this.segment([x,y],[xPrime,yPrime])}}},Camera:Camera}},{"./math":3}],2:[function(require,module,exports){module.exports={translate:(u,v)=>[u[0]+v[0],u[1]+v[1]],scale:(v,k)=>[v[0]*k,v[1]*k],negate:v=>[-v[0],-v[1]],rotate:(v,theta)=>{let[x,y]=v;const cosTheta=Math.cos(theta),sinTheta=Math.sin(theta);return[x*cosTheta-y*sinTheta,x*sinTheta+y*cosTheta]}}},{}],3:[function(require,module,exports){const form=require("./form");module.exports={form:form}},{"./form":2}],4:[function(require,module,exports){const core=require("./core"),{Cartesian:Cartesian}=core;module.exports={Cartesian:Cartesian,core:core,version:"v0.1.4"}},{"./core":1}]},{},[4])(4)}));