let my={}
function init(){let version='0.94'
my.drag={n:0,onQ:false,holdX:0,holdY:0}
my.mode=getJSQueryVar('mode','pent-pyramid')
this.curvyQ=['cone','cylinder','sphere','hemisphere'].indexOf(my.mode)>=0
this.flatyQ=['plane','coplanar'].indexOf(my.mode)>=0
my.pointsQ=false
my.wd=450
my.ht=450
let s=''
s+=''
s+=''
if(this.curvyQ||this.flatyQ){}else{s+=''
s+='
'
s+='Coloring: '
s+=getDropdownHTML(['Multi','Shaded','Two','Glass','PureGlass','Beams'],'clrChg','clrType')
s+='
'}
if(my.mode=='coplanar'){my.pointsQ=true
my.mode='3 points'
s+=''
s+='Type: '
s+=getDropdownHTML(['3 points','4 coplanar points','4 points','6 coplanar points','6 points'],'coplanarChg','coplanarType')
s+='
'}
s+=wrap({cls:'copyrt',pos:'abs',style:'left:5px; bottom:3px'},`© 2022 Rod Pierce v${version}`)
s=wrap({cls:'js',style:'width:'+my.wd+'px; height:'+my.ht+'px;'},s)
docInsert(s)
my.can=new Can('canvasId',my.wd,my.ht,2)
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.explodeQ=false
my.dragModeQ=false
my.drag.onQ=false
my.drag.holdX=0
my.drag.holdY=0
this.poly=new Poly()
xAngle=2
yAngle=4
zAngle=0
let el=my.can.el
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)
stt()}
function ontouchstart(ev){my.drag.onQ=true
let touch=ev.targetTouches[0]
let[mouseX,mouseY]=my.can.mousePos(ev)
my.drag.holdX=mouseX
my.drag.holdY=mouseY}
function ontouchmove(ev){let touch=ev.targetTouches[0]
ev.clientX=touch.clientX
ev.clientY=touch.clientY
ev.touchQ=true
onmouseMove(ev)
ev.preventDefault()}
function onmouseDown(ev){my.drag.onQ=true
let[mouseX,mouseY]=my.can.mousePos(ev)
my.drag.holdX=mouseX
my.drag.holdY=mouseY}
function onmouseUp(ev){my.drag.onQ=false}
function onmouseMove(ev){let[mouseX,mouseY]=my.can.mousePos(ev)
if(my.dragModeQ){if(my.drag.onQ){settransMat(-(my.drag.holdY-mouseY)*3,(my.drag.holdX-mouseX)*3,0,transMat)
my.drag.holdX=mouseX
my.drag.holdY=mouseY
update()}}else{yAngle=-(mouseX-my.wd/2)/25
xAngle=(mouseY-my.ht/2)/25}}
function toggleDrag(){my.dragModeQ=!my.dragModeQ
toggleBtn('dragBtn',my.dragModeQ)
if(my.dragModeQ){document.getElementById('dragBtn').innerHTML='Drag'}else{document.getElementById('dragBtn').innerHTML='Spin'}}
function toggleExplode(){this.explodeQ=!this.explodeQ
toggleBtn('explodeBtn',this.explodeQ)
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){let s=''
s+=''
return s}
function clrChg(){let el=document.getElementById('clrType')
if(el.selectedIndex==-1)return null
let t=el.options[el.selectedIndex].text
setClrs(t)
update()}
function coplanarChg(){let el=document.getElementById('coplanarType')
if(el.selectedIndex==-1)return null
let t=el.options[el.selectedIndex].text
my.mode=t
restart()}
function getClrType(){if(this.curvyQ||this.flatyQ){if(my.mode=='plane'){return 'Glass'}else{return 'Shaded'}}else{let div=document.getElementById('clrType')
if(div.selectedIndex==-1)return 'Multi'
return div.options[div.selectedIndex].text}}
function stt(){shapes=[]
poly.shapeType=my.mode
setShapesFromPoly()
settransMat(200,50,0,transMat)
my.can.clear()
drawShapes()
this.frameNo=0
animate()}
function restart(){shapes=[]
poly.shapeType=my.mode
setShapesFromPoly()
update()}
function animate(){this.frameNo++
if(my.dragModeQ){}else{settransMat(xAngle,yAngle,zAngle,transMat)
update()}
if(this.frameNo<1e8){requestAnimationFrame(animate)}}
function update(){my.can.clear()
drawShapes()}
function drawShapes(){let prevDepth=0
let sortNeededQ=false
for(let i=0,len=shapes.length;i0){if(shape.depth>0)+1
let grn=((dark*255)>>0)+1
angle=this.getNormalAngle(this.pts,1)
dark=1-angle/Math.PI
let blu=((dark*255)>>0)+1
this.fillClr='rgba('+red+','+grn+','+blu+','+alpha+')'}
Shape3D.prototype.getNormalAngle=function(pts,dimN){if(pts.length<3)return 0
let a=[pts[1].x-pts[0].x,pts[1].y-pts[0].y,pts[1].z-pts[0].z]
let b=[pts[2].x-pts[1].x,pts[2].y-pts[1].y,pts[2].z-pts[1].z]
let 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]]
let mag=Math.sqrt(cross[0]*cross[0]+cross[1]*cross[1]+cross[2]*cross[2])
let theta=Math.acos(cross[dimN]/mag)
return theta}
Shape3D.prototype.calcCentroid=function(){centroid=new Pt3d()
for(let i=0;i0){centroid.x/=this.pts.length
centroid.y/=this.pts.length
centroid.z/=this.pts.length}}
Shape3D.prototype.drawsurface=function(aboutEyeQ,viewType){let g=my.can.g
g.lineJoin='round'
let xsum=0
let ysum=0
let zsum=0
let clips=[]
let zMin=Number.MAX_VALUE
let zMax=-Number.MAX_VALUE
let i=0
let ptRot
while(i2){g.beginPath()
for(i=0,len=pt2s.length;i{if(cls.length==0)cls='btn'
return '