Add projects and tutorials
This commit is contained in:
Binary file not shown.
Binary file not shown.
83
tutorials/summed_area/cStyle.scss
Normal file
83
tutorials/summed_area/cStyle.scss
Normal file
@@ -0,0 +1,83 @@
|
||||
@import "../nord.scss";
|
||||
@import url('https://fonts.googleapis.com/css2?family=Roboto&display=swap');
|
||||
|
||||
$roboto-slab: 'Roboto', sans-serif;
|
||||
|
||||
html {
|
||||
background-color: $nord0;
|
||||
}
|
||||
|
||||
h1 {
|
||||
color: $nord6;
|
||||
font-family: $roboto-slab;
|
||||
font-size: 48pt;
|
||||
}
|
||||
|
||||
p {
|
||||
color: $nord4;
|
||||
font-family: $roboto-slab;
|
||||
font-size: 16pt;
|
||||
}
|
||||
|
||||
code {
|
||||
font-size: 14pt;
|
||||
border: 4px solid $nord13;
|
||||
}
|
||||
|
||||
a {
|
||||
color: $nord4;
|
||||
font-family: $roboto-slab;
|
||||
font-size: 24pt;
|
||||
}
|
||||
|
||||
#subsetOutput {
|
||||
color: $nord8;
|
||||
}
|
||||
|
||||
#wholeOutput {
|
||||
color: $nord15;
|
||||
}
|
||||
|
||||
#tlOutput{
|
||||
color: $nord12;
|
||||
}
|
||||
|
||||
#tOutput{
|
||||
color: $nord13;
|
||||
}
|
||||
|
||||
#lOutput{
|
||||
color: $nord14;
|
||||
}
|
||||
|
||||
#sumDiv {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
button {
|
||||
display: inline-block;
|
||||
width: 25%;
|
||||
padding: 10px 25px;
|
||||
margin: 0.1em;
|
||||
border: 4px solid $nord8;
|
||||
box-sizing: border-box;
|
||||
text-decoration: none;
|
||||
font-family: 'Roboto',sans-serif;
|
||||
font-size: 14pt;
|
||||
color: $nord2;
|
||||
background-color: $nord6;
|
||||
text-align: center;
|
||||
position: relative;
|
||||
transition: all 0.15s;
|
||||
|
||||
&:hover {
|
||||
background-color: $nord3;
|
||||
color: $nord6;
|
||||
border-color: $nord10;
|
||||
}
|
||||
|
||||
&:focus {
|
||||
border: 4px solid $nord8;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
}
|
||||
86
tutorials/summed_area/index.html
Normal file
86
tutorials/summed_area/index.html
Normal file
@@ -0,0 +1,86 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.11.1/highlight.min.js"></script>
|
||||
<link rel="stylesheet"
|
||||
href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.11.1/styles/atom-one-dark.min.css" />
|
||||
<link rel="stylesheet" href="style.css" />
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.2.0/p5.min.js"
|
||||
integrity="sha512-b/htz6gIyFi3dwSoZ0Uv3cuv3Ony7EeKkacgrcVg8CMzu90n777qveu0PBcbZUA7TzyENGtU+qZRuFAkfqgyoQ=="
|
||||
crossorigin="anonymous"></script>
|
||||
<script src="script.js"></script>
|
||||
<script>
|
||||
fetch("snippets/defineCount.js")
|
||||
.then(r => r.text())
|
||||
.then(code => {
|
||||
document.getElementById("define-count").textContent = code;
|
||||
if (window.hljs) hljs.highlightElement(document.getElementById("define-count"));
|
||||
});
|
||||
fetch("snippets/countSquares.js")
|
||||
.then(r => r.text())
|
||||
.then(code => {
|
||||
document.getElementById("count-squares").textContent = code;
|
||||
if (window.hljs) hljs.highlightElement(document.getElementById("count-squares"));
|
||||
});
|
||||
</script>
|
||||
|
||||
<head>
|
||||
<h1>Summed-area Table</h1>
|
||||
<p>
|
||||
A Summed-area table is a data structure and algorithm for quickly and
|
||||
efficiently generating the sum of values in a rectangular grid. In image
|
||||
processing it is also known as an integral image.
|
||||
</p>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<p>
|
||||
To generate a summed-area table, each cell is given a value which is the
|
||||
sum of all values in a rectangular subset where the top left corner is the
|
||||
first cell in the grid and where the bottom right cell is the cell you're
|
||||
calculating the value for (assumuing the array starts top left).
|
||||
</p>
|
||||
<pre>
|
||||
<code id="define-count" class="js">
|
||||
</code>
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
Now each cell has its own count value. This isn't much help on it's own,
|
||||
however we can use it to calculate the sum value of any subset of the grid
|
||||
by interrogating 4 cells and performing only 4 additions. NOTE: we have to
|
||||
add the 'top left' region as it as been subtracted twice.
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
<code id="count-squares" class="js">
|
||||
</code>
|
||||
</pre>
|
||||
|
||||
<p><b>Click</b> a sqaure on the grid to turn it on or off.</p>
|
||||
<p><b>Shift+Click</b> two square to define a rectangle.</p>
|
||||
<p>
|
||||
Press the <b>show count</b> button to display the sum value of each cell
|
||||
(in this example a cell's value can only be 0 or 1).
|
||||
</p>
|
||||
<p>
|
||||
Press <b>show rectangles</b> to see the different regions simplified and
|
||||
see how
|
||||
it changes the sum below.
|
||||
</p>
|
||||
<div id="sumDiv">
|
||||
<a id="subsetOutput">0</a>
|
||||
<a> = </a>
|
||||
<a id="wholeOutput"> 0</a>
|
||||
<a> + </a>
|
||||
<a id="tlOutput"> 0</a>
|
||||
<a> - </a>
|
||||
<a id="lOutput"> 0</a>
|
||||
<a> - </a>
|
||||
<a id="tOutput"> 0</a>
|
||||
</div>
|
||||
|
||||
<button onclick="showCountToggle()">Show count</button>
|
||||
<button onclick="toggleRectMode()">Show rectangles</button>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
278
tutorials/summed_area/script.js
Normal file
278
tutorials/summed_area/script.js
Normal file
@@ -0,0 +1,278 @@
|
||||
let myWidth = 800, myHeight = 800, offset = 5;
|
||||
let r, n = 10;
|
||||
|
||||
let t = [];
|
||||
let tl = null
|
||||
let br = null;
|
||||
|
||||
let showCount = false;
|
||||
let drawRectMode = 0;
|
||||
|
||||
let sOutput, wOutput, tlOutput, tOutput, lOutput;
|
||||
|
||||
|
||||
function setup()
|
||||
{
|
||||
createCanvas(myWidth + 2*offset, myHeight + 2*offset);
|
||||
r = myWidth / n;
|
||||
for (y = 0; y < n; y ++)
|
||||
{
|
||||
for (x = 0; x < n; x ++)
|
||||
{
|
||||
t.push(new cTile(x*r + offset, y*r + offset, r));
|
||||
}
|
||||
}
|
||||
sOutput = document.getElementById('subsetOutput');
|
||||
wOutput = document.getElementById('wholeOutput');
|
||||
tlOutput = document.getElementById('tlOutput');
|
||||
tOutput = document.getElementById('tOutput');
|
||||
lOutput = document.getElementById('lOutput');
|
||||
|
||||
}
|
||||
|
||||
function draw()
|
||||
{
|
||||
background(46, 52, 64);
|
||||
t.forEach(e => e.show());
|
||||
|
||||
stroke(156,212,228);
|
||||
noFill();
|
||||
strokeWeight(5);
|
||||
if (tl)
|
||||
{
|
||||
if (!br)
|
||||
{
|
||||
rect(tl.x, tl.y, tl.w);
|
||||
} else {
|
||||
rect(tl.x, tl.y, br.x - tl.x + r, br.y - tl.y + r);
|
||||
drawRect(drawRectMode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function defineCount(br)
|
||||
{
|
||||
let cols = Math.floor(br.x/ r) + 1;
|
||||
let rows = Math.floor(br.y/ r) + 1;
|
||||
let c = 0;
|
||||
// let index = cols + n * rows;
|
||||
|
||||
for (y = 0; y < rows; y++) {
|
||||
for (x = 0; x < cols; x++){
|
||||
var i = x + n * y;
|
||||
if (t[i].s){
|
||||
c++;
|
||||
}
|
||||
}
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
function countSquares(tl, br)
|
||||
{
|
||||
let topLeft, left, top, whole;
|
||||
let tlx, tly, brx, bry;
|
||||
|
||||
tlx = Math.floor(tl.x / r);
|
||||
tly = Math.floor(tl.y / r);
|
||||
brx = Math.floor(br.x / r);
|
||||
bry = Math.floor(br.y / r);
|
||||
|
||||
topLeft = t[(tlx-1) + n * (tly-1)].count;
|
||||
left = t[(tlx-1) + n * bry ].count;
|
||||
top = t[brx + n * (tly-1)].count;
|
||||
whole = t[brx + n * bry ].count;
|
||||
|
||||
var s = whole + topLeft - top - left;
|
||||
if (s < 0)
|
||||
s = 0;
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
function drawRect(n)
|
||||
{
|
||||
strokeWeight(5);
|
||||
noFill();
|
||||
|
||||
switch(n)
|
||||
{
|
||||
case 1:
|
||||
//whole
|
||||
stroke(180,142,173);
|
||||
fill('rgba(180, 142, 173, 0.05)');
|
||||
rect(offset, offset, br.x - offset + br.w, br.y - offset + br.w);
|
||||
break;
|
||||
case 2:
|
||||
//topleft
|
||||
stroke(208,135,112);
|
||||
fill('rgba(208,135,112, 0.05)');
|
||||
rect(offset, offset, tl.x - offset, tl.y - offset);
|
||||
break;
|
||||
case 3:
|
||||
//left
|
||||
stroke(163,190,140);
|
||||
fill('rgba(163,190,140, 0.05)');
|
||||
rect(offset, offset, tl.x - offset, br.y - offset + br.w);
|
||||
break;
|
||||
case 4:
|
||||
//top
|
||||
stroke(235,203,139);
|
||||
fill('rgba(235,203,139, 0.05)');
|
||||
rect(offset, offset, br.x - offset + br.w, tl.y - offset);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
strokeWeight(1);
|
||||
}
|
||||
|
||||
function showCountToggle(){
|
||||
showCount = !showCount;
|
||||
}
|
||||
|
||||
function toggleRectMode(){
|
||||
if (tl && br)
|
||||
{
|
||||
var tlx = Math.floor(tl.x / r);
|
||||
var tly = Math.floor(tl.y / r);
|
||||
var brx = Math.floor(br.x / r);
|
||||
var bry = Math.floor(br.y / r);
|
||||
|
||||
var topLeft = t[(tlx-1) + n * (tly-1)].count;
|
||||
var left = t[(tlx-1) + n * bry ].count;
|
||||
var top = t[brx + n * (tly-1)].count;
|
||||
var whole = t[brx + n * bry ].count;
|
||||
|
||||
if (drawRectMode == 0){
|
||||
wOutput.innerHTML = whole.toString(10);
|
||||
wOutput.style.fontWeight = "bold";
|
||||
drawRectMode ++;
|
||||
} else if (drawRectMode == 1){
|
||||
tlOutput.innerHTML = topLeft.toString(10);
|
||||
tlOutput.style.fontWeight = "bold";
|
||||
wOutput.style.fontWeight = "normal";
|
||||
drawRectMode ++;
|
||||
} else if (drawRectMode == 2){
|
||||
lOutput.innerHTML = left.toString(10);
|
||||
lOutput.style.fontWeight = "bold";
|
||||
tlOutput.style.fontWeight = "normal";
|
||||
drawRectMode ++;
|
||||
} else if (drawRectMode == 3) {
|
||||
tOutput.innerHTML = top.toString(10);
|
||||
tOutput.style.fontWeight = "bold";
|
||||
lOutput.style.fontWeight = "normal";
|
||||
drawRectMode ++;
|
||||
} else if (drawRectMode == 4) {
|
||||
tOutput.style.fontWeight = "normal";
|
||||
drawRectMode = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function updateSum()
|
||||
{
|
||||
var tlx = Math.floor(tl.x / r);
|
||||
var tly = Math.floor(tl.y / r);
|
||||
var brx = Math.floor(br.x / r);
|
||||
var bry = Math.floor(br.y / r);
|
||||
|
||||
var topLeft = t[(tlx-1) + n * (tly-1)].count;
|
||||
var left = t[(tlx-1) + n * bry ].count;
|
||||
var top = t[brx + n * (tly-1)].count;
|
||||
var whole = t[brx + n * bry ].count;
|
||||
|
||||
wOutput.innerHTML = whole.toString(10);
|
||||
tlOutput.innerHTML = topLeft.toString(10);
|
||||
lOutput.innerHTML = left.toString(10);
|
||||
tOutput.innerHTML = top.toString(10);
|
||||
sOutput.innerHTML = countSquares(tl,br).toString(10);
|
||||
}
|
||||
|
||||
function mouseClicked(event)
|
||||
{
|
||||
if (event.shiftKey)
|
||||
{
|
||||
if (mouseX > offset && mouseX < myWidth && mouseY > offset && mouseY < myHeight)
|
||||
{
|
||||
let col = Math.floor(mouseX / r);
|
||||
let row = Math.floor(mouseY / r);
|
||||
|
||||
if (tl != null && br != null)
|
||||
{
|
||||
tl = null;
|
||||
br = null;
|
||||
}
|
||||
|
||||
if (!tl)
|
||||
{
|
||||
tl = t[col + n * row];
|
||||
} else {
|
||||
br = t[col + n * row];
|
||||
}
|
||||
|
||||
if (tl != null && br != null)
|
||||
{
|
||||
updateSum();
|
||||
}
|
||||
|
||||
}
|
||||
} else {
|
||||
if (mouseX > 0 && mouseX < myWidth && mouseY > 0 && mouseY < myHeight)
|
||||
{
|
||||
let col = Math.floor(mouseX / r);
|
||||
let row = Math.floor(mouseY / r);
|
||||
t[col + n * row].setState();
|
||||
|
||||
t.forEach(tile => tile.setCount(defineCount(tile)));
|
||||
|
||||
if (tl != null && br != null)
|
||||
{
|
||||
updateSum();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class cTile
|
||||
{
|
||||
constructor(_x, _y, _w)
|
||||
{
|
||||
this.x = _x;
|
||||
this.y = _y;
|
||||
this.s = false;
|
||||
this.w = _w;
|
||||
this.count = 0;
|
||||
}
|
||||
|
||||
show()
|
||||
{
|
||||
if (this.s)
|
||||
{
|
||||
fill(191,97,106);
|
||||
} else {
|
||||
noFill();
|
||||
}
|
||||
stroke(236,239,244);
|
||||
strokeWeight(1);
|
||||
rect(this.x, this.y, this.w, this.w);
|
||||
if (showCount)
|
||||
{
|
||||
textSize(18);
|
||||
stroke(255);
|
||||
fill(255);
|
||||
text(this.count.toString(10), this.x + this.w/2 - 3, this.y + this.w/2 + 5);
|
||||
}
|
||||
}
|
||||
|
||||
setState()
|
||||
{
|
||||
this.s = !this.s;
|
||||
}
|
||||
|
||||
setCount(c)
|
||||
{
|
||||
this.count = c;
|
||||
}
|
||||
};
|
||||
14
tutorials/summed_area/snippets/countSquares.js
Normal file
14
tutorials/summed_area/snippets/countSquares.js
Normal file
@@ -0,0 +1,14 @@
|
||||
// where tl and br are the top left and bottom right cell respectively
|
||||
function countSquares(tl, br) {
|
||||
|
||||
// these are the four cells to interrogate
|
||||
let topLeft, left, top, whole;
|
||||
|
||||
// 1d index = x + #rows * y
|
||||
topLeft = t[(tl.x - 1) + n * (tl.y - 1)].count;
|
||||
left = t[(tl.x - 1) + n * bry].count;
|
||||
top = t[br.x + n * (tl.y - 1)].count;
|
||||
whole = t[br.x + n * br.y].count;
|
||||
|
||||
return whole + topLeft - top - left;
|
||||
}
|
||||
16
tutorials/summed_area/snippets/defineCount.js
Normal file
16
tutorials/summed_area/snippets/defineCount.js
Normal file
@@ -0,0 +1,16 @@
|
||||
// where br is the cell we're calculating
|
||||
function defineCount(br) {
|
||||
let c = 0;
|
||||
|
||||
// br.x is the column number
|
||||
// br.y is the row number
|
||||
for (y = 0; y <= br.y; y++) { // loop through all rows above br (and the row br is on)
|
||||
for (x = 0; x <= br.x; x++) { // loop through all columns to the left of br (and br column)
|
||||
var i = x + n * y; // convert 2d array format to 1d index
|
||||
if (t[i].s) { // if cell[i].status==true then increase count
|
||||
c++;
|
||||
}
|
||||
}
|
||||
}
|
||||
return c;
|
||||
}
|
||||
68
tutorials/summed_area/style.css
Normal file
68
tutorials/summed_area/style.css
Normal file
@@ -0,0 +1,68 @@
|
||||
@import url("https://fonts.googleapis.com/css2?family=Roboto&display=swap");
|
||||
html {
|
||||
background-color: #2e3440; }
|
||||
|
||||
h1 {
|
||||
color: #eceff4;
|
||||
font-family: "Roboto", sans-serif;
|
||||
font-size: 48pt; }
|
||||
|
||||
p {
|
||||
color: #d8dee9;
|
||||
font-family: "Roboto", sans-serif;
|
||||
font-size: 16pt; }
|
||||
|
||||
code {
|
||||
font-size: 14pt;
|
||||
border: 4px solid #ebcb8b; }
|
||||
|
||||
a {
|
||||
color: #d8dee9;
|
||||
font-family: "Roboto", sans-serif;
|
||||
font-size: 24pt; }
|
||||
|
||||
#subsetOutput {
|
||||
color: #88c0d0; }
|
||||
|
||||
#wholeOutput {
|
||||
color: #b48ead; }
|
||||
|
||||
#tlOutput {
|
||||
color: #d08770; }
|
||||
|
||||
#tOutput {
|
||||
color: #ebcb8b; }
|
||||
|
||||
#lOutput {
|
||||
color: #a3be8c; }
|
||||
|
||||
#sumDiv {
|
||||
text-align: center; }
|
||||
|
||||
button {
|
||||
display: inline-block;
|
||||
width: 25%;
|
||||
padding: 10px 25px;
|
||||
margin: 0.1em;
|
||||
border: 4px solid #88c0d0;
|
||||
box-sizing: border-box;
|
||||
text-decoration: none;
|
||||
font-family: 'Roboto',sans-serif;
|
||||
font-size: 14pt;
|
||||
color: #434c5e;
|
||||
background-color: #eceff4;
|
||||
text-align: center;
|
||||
position: relative;
|
||||
transition: all 0.15s; }
|
||||
button:hover {
|
||||
background-color: #4c566a;
|
||||
color: #eceff4;
|
||||
border-color: #5e81ac; }
|
||||
button:focus {
|
||||
border: 4px solid #88c0d0;
|
||||
box-sizing: border-box; }
|
||||
|
||||
#chillin {
|
||||
display: none; }
|
||||
|
||||
/*# sourceMappingURL=style.css.map */
|
||||
7
tutorials/summed_area/style.css.map
Normal file
7
tutorials/summed_area/style.css.map
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"version": 3,
|
||||
"mappings": "AACQ,2EAAmE;AAI3E,IAAK;EACD,gBAAgB,EC+BZ,OAAO;;AD5Bf,EAAG;EACC,KAAK,ECuID,OAAO;EDtIX,WAAW,EARD,oBAAoB;EAS9B,SAAS,EAAE,IAAI;;AAGnB,CAAE;EACE,KAAK,EC2GD,OAAO;ED1GX,WAAW,EAdD,oBAAoB;EAe9B,SAAS,EAAE,IAAI;;AAGnB,IAAK;EACD,SAAS,EAAE,IAAI;EACf,MAAM,EAAE,iBAAiB;;AAG7B,CAAE;EACE,KAAK,ECgGD,OAAO;ED/FX,WAAW,EAzBD,oBAAoB;EA0B9B,SAAS,EAAE,IAAI;;AAGnB,aAAc;EACV,KAAK,ECuID,OAAO;;ADpIf,YAAa;EACT,KAAK,ECqMA,OAAO;;ADlMhB,SAAS;EACL,KAAK,ECoKA,OAAO;;ADjKhB,QAAQ;EACJ,KAAK,EC0KA,OAAO;;ADvKhB,QAAQ;EACJ,KAAK,ECgLA,OAAO;;AD7KhB,OAAQ;EACJ,UAAU,EAAE,MAAM;;AAGtB,MAAO;EACH,OAAO,EAAE,YAAY;EACrB,KAAK,EAAE,GAAG;EACV,OAAO,EAAE,SAAS;EAClB,MAAM,EAAE,KAAK;EACb,MAAM,EAAE,iBAAgB;EACxB,UAAU,EAAE,UAAU;EACtB,eAAe,EAAE,IAAI;EACrB,WAAW,EAAE,mBAAmB;EAChC,SAAS,EAAE,IAAI;EACf,KAAK,ECMD,OAAO;EDLX,gBAAgB,EC8EZ,OAAO;ED7EX,UAAU,EAAE,MAAM;EAClB,QAAQ,EAAE,QAAQ;EAClB,UAAU,EAAE,SAAS;EAErB,YAAQ;IACJ,gBAAgB,EC+BhB,OAAO;ID9BP,KAAK,ECuEL,OAAO;IDtEP,YAAY,ECgHX,OAAO;ED7GZ,YAAQ;IACJ,MAAM,EAAE,iBAAgB;IACxB,UAAU,EAAE,UAAU;;AAI9B,QAAS;EACL,OAAO,EAAE,IAAI",
|
||||
"sources": ["cStyle.scss","../nord.scss"],
|
||||
"names": [],
|
||||
"file": "style.css"
|
||||
}
|
||||
Reference in New Issue
Block a user