-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathindex.html
More file actions
39 lines (39 loc) · 12.5 KB
/
index.html
File metadata and controls
39 lines (39 loc) · 12.5 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name='viewport' content='width=device-width,initial-scale=1'>
<meta name="description" content="Star polygons generation tool based on vertices and turning point(s)."/>
<meta name="keywords" content="stars, polygons, geometry, generator, ratios, proportions, golden ratio">
<title>Star polygons</title>
<style>body{font-family:Georgia,serif;font-size:12px;color:#000}input,button{margin-bottom:5px}label{min-width:120px;display:inline-block}table{border-collapse:collapse}td div{padding:0 5px}td:first-child div{padding:0 5px 0 0}</style>
</head>
<body>
<form action="javascript:draw()">
<label for="p">p <small>vertices</small></label><input id="p" type="number" min="1" value="5"/><br/>
<label for="q0">q<sub>0</sub> <small>turning number</small></label><input id="q0" type="number" min="1" value="1"/><br/>
<span id="additional_qs"></span>
<button onclick="addQ();return false;">Add q</button><button onclick="removeQ();return false;">Del q</button><br/>
<label for="r">r <small>radius</small></label><input id="r" type="number" min="0" value="1"/><br/>
<label for="scale">scale</label><input id="scale" type="number" min="1" value="200"/><br/>
<button type="submit">Submit</button>
</form>
<table>
<tr>
<td id="edges"></td>
<td id="angles_rad"></td>
<td id="angles_deg"></td>
<td id="intersections"></td>
<td style="display:none;" id="segments"></td>
<td style="display:none;" id="ratios_ext"></td>
<td style="display:none;" id="ratios_int"></td>
<td style="display:none;" id="ratios_ratio"></td>
<td style="display:none;" id="roots"></td>
<td style="display:none;" id="phis"></td>
<td style="display:none;" id="sequences"></td>
</tr>
</table>
<div id="container"></div>
<script>function addQ(){if(!(qCount+2>parseInt(document.getElementById("p").value,10)))return++qCount,document.getElementById("additional_qs").insertAdjacentHTML("beforeend",`<span id="q${qCount}container"><label for="q${qCount}">q<sub>${qCount}</sub></label><input id="q${qCount}" type="number" min="1" value="1"/><br/></span>`)}function removeQ(){qCount<1||(document.getElementById(`q${qCount}container`).remove(),--qCount)}function resetCanvas(){document.getElementById("container").innerHTML="",document.getElementById("container").innerHTML='<canvas id="canvas" height="2000" width="2000"></canvas>'}function resetResults(){document.getElementById("edges").innerHTML="",document.getElementById("angles_rad").innerHTML="",document.getElementById("angles_deg").innerHTML="",document.getElementById("intersections").innerHTML="",document.getElementById("segments").innerHTML="",document.getElementById("ratios_ext").innerHTML="",document.getElementById("ratios_int").innerHTML="",document.getElementById("ratios_ratio").innerHTML="",document.getElementById("roots").innerHTML="",document.getElementById("phis").innerHTML="",document.getElementById("sequences").innerHTML=""}function drawPoint(u,t,s,n="",e="#000",r=1){let i=Math.round(t),o=Math.round(s);if(u.beginPath(),u.fillStyle=e,u.arc(i,o,r,0,2*Math.PI),u.fill(),""!==n){let t=i,s=Math.round(o-r-3);u.font="Italic 10px Georgia",u.fillStyle=e,u.textAlign="center",u.fillText(n,t,s)}}function drawLabel(u,t,s,n,e,r,i="#000"){let o=Math.round(t+n),b=Math.round(s+e);u.font="Italic 10px Georgia",u.fillStyle=i,u.textAlign="center",u.fillText(r,o,b)}function drawLine(u,t,s,n,e,r="",i="#000",o=1){if(u.strokeStyle="#000",u.lineWidth=o,u.beginPath(),u.moveTo(t,s),u.lineTo(n,e),u.stroke(),""!==r){let b=Math.round((n+t)/2),a=Math.round((e+s)/2-o-3);u.font="Italic 10px Georgia",u.fillStyle=i,u.textAlign="center",u.fillText(r,b,a)}}function drawCircle(u,t,s,n,e,r,i="#000",o=1){u.strokeStyle=i,u.lineWidth=o,u.beginPath(),u.arc(t,s,n,e,r),u.stroke()}function translateToCanvas(u,t=10){const s=[],n=[];u.forEach((function(u){s.push(u[0]),n.push(u[1])}));const e=-1*Math.min(...s),r=-1*Math.min(...n),i=[];for(let s=0,n=u.length;s<n;++s)i.push([u[s][0]+e+t,u[s][1]+r+t]);return[i,[e+t,r+t]]}function dotProductMatrixAndPoint(u,t){let s=u[0],n=u[1],e=u[2],r=u[3],i=t[0],o=t[1];return[i*s+o*e,i*n+o*r]}function rotate(u,t,s="anticlockwise"){return dotProductMatrixAndPoint("anticlockwise"===s?[Math.cos(t),-Math.sin(t),Math.sin(t),Math.cos(t)]:[Math.cos(t),Math.sin(t),-Math.sin(t),Math.cos(t)],u)}function distance(u,t,s,n){return Math.sqrt(Math.pow(s-u,2)+Math.pow(n-t,2))}function vectorLength(u){return Math.sqrt(Math.pow(u[0],2)+Math.pow(u[1],2))}function dotProductVectors(u,t){return u[0]*t[0]+u[1]*t[1]}function vector(u,t){return[t[0]-u[0],t[1]-u[1]]}function calcAngle(u,t,s,n="degrees"){let e=vector(t,u),r=vector(t,s),i=Math.acos(dotProductVectors(e,r)/(vectorLength(e)*vectorLength(r)));return"radians"!==n?180*i/Math.PI:i}function round(u,t=4){return Math.round((u+Number.EPSILON)*Math.pow(10,t))/Math.pow(10,t)}function printResult(u,t){document.getElementById(t).insertAdjacentHTML("beforeend",`<div>${u}</div>`)}function calcIntersection(u,t,s,n){let e=(u[0]-s[0])*(s[1]-n[1])-(u[1]-s[1])*(s[0]-n[0]),r=(u[0]-t[0])*(s[1]-n[1])-(u[1]-t[1])*(s[0]-n[0]);if(0===r||e>r||e<0&&r>0||e>0&&r<0)return null;let i=(u[0]-s[0])*(u[1]-t[1])-(u[1]-s[1])*(u[0]-t[0]),o=(u[0]-t[0])*(s[1]-n[1])-(u[1]-t[1])*(s[0]-n[0]);if(0===o||i>o||i<0&&o>0||i>0&&o<0)return null;let b=e/r,a=i/o;return b>1||b<0||a>1||a<0?null:[u[0]+b*(t[0]-u[0]),u[1]+b*(t[1]-u[1])]}function printRatios(u,t,s,n,e,r){let i,o,b,a,l=distance(u[s][5][0],u[s][5][1],r[0],r[1]),d=u[s][7]-l,$=distance(u[s][0][0],u[s][0][1],t[0],t[1]),p=u[s][4]-$;$>=p?(printResult(`p<sub>${u[s][2]}</sub>i<sub>${e}</sub>=${round(l)}`,"segments"),printResult(`p<sub>${u[s][3]}</sub>i<sub>${e}</sub>=${round(d)}`,"segments"),i=round(u[s][4]/$),printResult(`p<sub>${u[s][2]}</sub>p<sub>${u[s][3]}</sub>/p<sub>${u[s][2]}</sub>i<sub>${e}</sub>=${i}`,"ratios_ext"),o=round($/p),printResult(`p<sub>${u[s][2]}</sub>i<sub>${e}</sub>/p<sub>${u[s][3]}</sub>i<sub>${e}</sub>=${o}`,"ratios_int"),b=round(o/i),printResult(`(p<sub>${u[s][2]}</sub>i<sub>${e}</sub>/p<sub>${u[s][3]}</sub>i<sub>${e}</sub>)/(p<sub>${u[s][2]}</sub>p<sub>${u[s][3]}</sub>/p<sub>${u[s][2]}</sub>i<sub>${e}</sub>)=${b}`,"ratios_ratio"),a=`(p<sub>${u[s][2]}</sub>i<sub>${e}</sub>/p<sub>${u[s][3]}</sub>i<sub>${e}</sub>)/(p<sub>${u[s][2]}</sub>p<sub>${u[s][3]}</sub>/p<sub>${u[s][2]}</sub>i<sub>${e}</sub>)`):(printResult(`p<sub>${u[s][3]}</sub>i<sub>${e}</sub>=${round(d)}`,"segments"),printResult(`p<sub>${u[s][2]}</sub>i<sub>${e}</sub>=${round(l)}`,"segments"),i=round(u[s][4]/p),printResult(`p<sub>${u[s][2]}</sub>p<sub>${u[s][3]}</sub>/p<sub>${u[s][3]}</sub>i<sub>${e}</sub>=${i}`,"ratios_ext"),o=round(p/$),printResult(`p<sub>${u[s][3]}</sub>i<sub>${e}</sub>/p<sub>${u[s][2]}</sub>i<sub>${e}</sub>=${o}`,"ratios_int"),b=round(o/i),printResult(`(p<sub>${u[s][3]}</sub>i<sub>${e}</sub>/p<sub>${u[s][2]}</sub>i<sub>${e}</sub>)/(p<sub>${u[s][2]}</sub>p<sub>${u[s][3]}</sub>/p<sub>${u[s][3]}</sub>i<sub>${e}</sub>)=${b}`,"ratios_ratio"),a=`(p<sub>${u[s][3]}</sub>i<sub>${e}</sub>/p<sub>${u[s][2]}</sub>i<sub>${e}</sub>)/(p<sub>${u[s][2]}</sub>p<sub>${u[s][3]}</sub>/p<sub>${u[s][3]}</sub>i<sub>${e}</sub>)`),printQuadraticRoots(quadraticRoots(1,-(2+b),1),"",`-(2+(${a}))`,"+1","roots"),printQuadraticRoots(quadraticRoots(1,-b,-b),"",`-(${a})`,`-(${a})`,"phis"),printSequences(b),l=distance(u[n][5][0],u[n][5][1],r[0],r[1]),d=u[n][7]-l,$=distance(u[n][0][0],u[n][0][1],t[0],t[1]),p=u[n][4]-$,$>=p?(printResult(`p<sub>${u[n][2]}</sub>i<sub>${e}</sub>=${round(l)}`,"segments"),printResult(`p<sub>${u[n][3]}</sub>i<sub>${e}</sub>=${round(d)}`,"segments"),i=round(u[n][4]/$),printResult(`p<sub>${u[n][2]}</sub>p<sub>${u[n][3]}</sub>/p<sub>${u[n][2]}</sub>i<sub>${e}</sub>=${i}`,"ratios_ext"),o=round($/p),printResult(`p<sub>${u[n][2]}</sub>i<sub>${e}</sub>/p<sub>${u[n][3]}</sub>i<sub>${e}</sub>=${o}`,"ratios_int"),b=round(o/i),printResult(`(p<sub>${u[n][2]}</sub>i<sub>${e}</sub>/p<sub>${u[n][3]}</sub>i<sub>${e}</sub>)/(p<sub>${u[n][2]}</sub>p<sub>${u[n][3]}</sub>/p<sub>${u[n][2]}</sub>i<sub>${e}</sub>)=${b}`,"ratios_ratio"),a=`(p<sub>${u[n][2]}</sub>i<sub>${e}</sub>/p<sub>${u[n][3]}</sub>i<sub>${e}</sub>)/(p<sub>${u[n][2]}</sub>p<sub>${u[n][3]}</sub>/p<sub>${u[n][2]}</sub>i<sub>${e}</sub>)`):(printResult(`p<sub>${u[n][3]}</sub>i<sub>${e}</sub>=${round(d)}`,"segments"),printResult(`p<sub>${u[n][2]}</sub>i<sub>${e}</sub>=${round(l)}`,"segments"),i=round(u[n][4]/p),printResult(`p<sub>${u[n][2]}</sub>p<sub>${u[n][3]}</sub>/p<sub>${u[n][3]}</sub>i<sub>${e}</sub>=${i}`,"ratios_ext"),o=round(p/$),printResult(`p<sub>${u[n][3]}</sub>i<sub>${e}</sub>/p<sub>${u[n][2]}</sub>i<sub>${e}</sub>=${o}`,"ratios_int"),b=round(o/i),printResult(`(p<sub>${u[n][3]}</sub>i<sub>${e}</sub>/p<sub>${u[n][2]}</sub>i<sub>${e}</sub>)/(p<sub>${u[n][2]}</sub>p<sub>${u[n][3]}</sub>/p<sub>${u[n][3]}</sub>i<sub>${e}</sub>)=${b}`,"ratios_ratio"),a=`(p<sub>${u[n][3]}</sub>i<sub>${e}</sub>/p<sub>${u[n][2]}</sub>i<sub>${e}</sub>)/(p<sub>${u[n][2]}</sub>p<sub>${u[n][3]}</sub>/p<sub>${u[n][3]}</sub>i<sub>${e}</sub>)`),printQuadraticRoots(quadraticRoots(1,-(2+b),1),"",`-(2+(${a}))`,"+1","roots"),printQuadraticRoots(quadraticRoots(1,-b,-b),"",`-(${a})`,`-(${a})`,"phis"),printSequences(b)}function quadraticRoots(u,t,s){let n,e,r=t*t-4*u*s;if(r>0)return n=(-t+Math.sqrt(r))/(2*u),e=(-t-Math.sqrt(r))/(2*u),[n,e];if(0===r)return n=-t/(2*u),[n,null];{let s=(-t/(2*u)).toFixed(2),n=(Math.sqrt(-r)/(2*u)).toFixed(2);return[[s,n],[s,-n]]}}function printQuadraticRoots(u,t="",s="+",n="+1",e="roots"){null===u[1]?printResult(`${t}x<sup>2</sup>${s}x${n}=0 → x=${round(u[0])}`,e):void 0!==u[0][0]?printResult(`${t}x<sup>2</sup>${s}x${n}=0 → x<sub>0</sub>=${round(u[0])[0]}+${round(u[0][1])}i, x<sub>1</sub>=${round(u[1][0])} + ${round(u[1][1])}i`,e):printResult(`${t}x<sup>2</sup>${s}x${n}=0 → x<sub>0</sub>=${round(u[0])}, x<sub>1</sub>=${round(u[1])}`,e)}function printSequences(u,t=8){let s=[],n=[];for(let e=0,r=t;e<r;++e)0!==e?(s.push(s[e-1]*u+n[e-1]),n.push(s[e-1]*u)):(s.push(u),n.push(u));let e=s.map((u=>round(u,2))).join(", "),r=n.map((u=>round(u,2))).join(", ");printResult(`${e}...`,"sequences"),printResult(`${r}...`,"sequences")}function draw(){resetCanvas(),resetResults();const u=document.getElementById("canvas"),t=parseInt(document.getElementById("p").value,10),s=[];for(let u=0,t=qCount+1;u<t;++u)s.push(parseInt(document.getElementById(`q${u}`).value,10));const n=parseFloat(document.getElementById("r").value),e=parseInt(document.getElementById("scale").value,10),r=[0,-1*n],i=[0,0],o=[0,n*e*-1],b=2*Math.PI/t;if(u.getContext){const a=u.getContext("2d"),l=[];l.push(r);for(let u=1,s=t;u<s;++u)l.push(rotate(l[u-1],b,"anticlockwise"));let d,$=[];$.push(o);for(let u=1,s=t;u<s;++u)$.push(rotate($[u-1],b,"anticlockwise"));[$,d]=translateToCanvas($,50),drawCircle(a,i[0]+d[0],i[1]+d[1],n*e,0,2*Math.PI,"#d3d3d3");let p,c,h=0,f=[],g=[];for(let u=0,n=t;u<n;++u){void 0===s[h]&&(h=0),p=s[h++],c=void 0!==$[u+p]?u+p:u+p-t,drawLine(a,$[u][0],$[u][1],$[c][0],$[c][1],`e${u}`,"purple");let n=round(distance(l[u][0],l[u][1],l[c][0],l[c][1]));printResult(`e<sub>${u}</sub> = ${n}`,"edges"),void 0===f[u]?f[u]=[l[c],null]:f[u][1]=l[c],void 0===f[c]?f[c]=[l[u],null]:f[c][1]=l[u];let e=round(distance($[u][0],$[u][1],$[c][0],$[c][1]));g.push([$[u],$[c],u,c,e,l[u],l[c],n])}for(let u=0,t=$.length;u<t;++u)drawPoint(a,$[u][0],$[u][1],`p${u}`,"green");for(let u=0,s=t;u<s;++u){if(null===f[u][0]||null===f[u][1])continue;let t=calcAngle(f[u][0],l[u],f[u][1]);if(isNaN(t)||t<=0)continue;let s=calcAngle(f[u][0],l[u],f[u][1],"radians");drawLabel(a,$[u][0],$[u][1],10,10,`θ${u}`,"blue"),printResult(`θ<sub>${u}</sub> = ${round(t)}°`,"angles_deg"),printResult(`θ<sub>${u}</sub> = ${round(s)}`,"angles_rad")}let m=0,M=[],R=[];for(let u=0,s=t;u<s;++u)for(let t=0,s=g.length;t<s;++t){if(t===u)continue;let s=calcIntersection(g[u][0],g[u][1],g[t][0],g[t][1]);if(null===s||s[0]<0||s[1]<0||round(s[0])===round(g[u][0][0])&&round(s[1])===round(g[u][0][1])||round(s[0])===round(g[u][1][0])&&round(s[1])===round(g[u][1][1])||round(s[0])===round(g[t][0][0])&&round(s[1])===round(g[t][1][1])||round(s[0])===round(g[t][1][0])&&round(s[1])===round(g[t][1][1]))continue;let n=!1,e=0,r=M.length;for(;e<r;++e)if(round(M[e][0])===round(s[0])&&round(M[e][1])===round(s[1])){n=!0;break}let i=calcIntersection(g[u][5],g[u][6],g[t][5],g[t][6]);n?(printResult(`e<sub>${u}</sub>∩e<sub>${t}</sub>=i<sub>${e}</sub>`,"intersections"),printRatios(g,s,u,t,m,i)):(M.push(s),R.push(i),drawLabel(a,s[0],s[1],-10,10,`i${m}`,"red"),printResult(`e<sub>${u}</sub>∩e<sub>${t}</sub>=i<sub>${m}</sub>`,"intersections"),printRatios(g,s,u,t,m,i),++m)}}}qCount=0;</script>
</body>
</html>