archive complete

This commit is contained in:
John Gatward
2026-03-16 19:04:56 +00:00
parent 4e94902f01
commit da5879fc6e
20 changed files with 1034 additions and 1002 deletions

View File

@@ -101,38 +101,36 @@
<div class="projects"> <div class="projects">
<h3 id="projectjump">Projects</h3> <h3 id="projectjump">Projects</h3>
<a href="/gameoflife.php"> <a href="/projects/game_of_life.html">
<p> Game of Life</p> <p> Game of Life</p>
</a> </a>
<a href="mazeGen.php"> <a href="/projects/maze_generation.html">
<p>Maze Generator</p> <p>Maze Generator</p>
</a> </a>
<a href="oscil.php"> <a href="/projects/oscillations_in_3d.html">
<p>Oscilations in 3D</p> <p>Oscilations in 3D</p>
</a> </a>
<a href="poissonDist.php"> <a href="/projects/poisson_distribution.html">
<p>Poisson Distribution</p> <p>Poisson Distribution</p>
</a> </a>
<a href="piApprox.php"> <a href="/projects/pi_approximation.html">
<p>Approximating PI</p> <p>Approximating PI</p>
</a> </a>
<a href="cardioid.php"> <a href="cardioid.php">
<p>Cardioids</p> <p>Cardioids</p>
</a> </a>
<a href="/ellipseConst/index.php"> <a href="/projects/ellipse_construction.html">
<p>Constructing an ellipse</p> <p>Constructing an ellipse</p>
</a> </a>
<a href="/weatherApp/index.php">
<p>Weather App</p>
</a>
<h3>Tutorials</h3> <h3>Tutorials</h3>
<a href="/TSP_files/index.php"> <a href="/tutorials/tsp/index.html">
<p>Travelling salesman problem</p> <p>Travelling salesman problem</p>
</a> </a>
<a href="/terrainGen/index.php"> <a href="/tutorials/midpoint_displacement/index.html">
<p>Midpoint displacement terrain generator</p> <p>Midpoint displacement terrain generator</p>
</a> </a>
<a href="/jarvisMarsh/index.php"> <a href="/tutorials/convex_hull/index.html">
<p>Convex hull generator</p> <p>Convex hull generator</p>
</a> </a>

View File

@@ -10,114 +10,128 @@
</nav> </nav>
<h1>Havox.org V2</h1> <h1>Havox.org V2</h1>
<article id="s1"> <article id="s1">
<h2>About havox&nbsp<i class="far fa-address-card"></i></h2> <h2>About havox&nbsp<i class="far fa-address-card"></i></h2>
<p>This is havox - havox is a collection of my projects and tutorials that I've written over the years. The tutorials written are more to consolidate my knowledge of whatever I've been working on however if they help even one person, I'll consider that a win.</p> <p>This is havox - havox is a collection of my projects and tutorials that I've written over the years. The
<p>Feel free to check out any of my <span class="nav"><a href="#s2">tutorials</a></span> or one of my various js <span class="nav"><a href="#s3">projects</a></span></p> tutorials written are more to consolidate my knowledge of whatever I've been working on however if they help
<p><b>Why V2?</b></p> even one person, I'll consider that a win.</p>
<p> <p>Feel free to check out any of my <span class="nav"><a href="#s2">tutorials</a></span> or one of my various js
This is the second revision of Havox. After havox's initial conception in late 2017, it has suffered from a chronic case of spaghetti code. An update with: neater <strike>and better</strike> code, updated theming and overall cleaner UI was long overdue. <span class="nav"><a href="#s3">projects</a></span>
</p> </p>
<p><b>Why is Havox on umbra.cyou?</b></p> <p><b>Why V2?</b></p>
<p>Havox has domain hopped a fair bit since 2017 (where it used to be hosted on jayomayo.host - lol) however since losing the <code>havox.org</code> domain, I will be using <code>umbra.cyou</code> for the foreseeable future</p> <p>
<h2>Daily Trump Quote</h2> This is the second revision of Havox. After havox's initial conception in late 2017, it has suffered from a
<p><?=$quote;?></p> chronic case of spaghetti code. An update with: neater <strike>and better</strike> code, updated theming and
overall cleaner UI was long overdue.
</p>
<p><b>Why is Havox on umbra.cyou?</b></p>
<p>Havox has domain hopped a fair bit since 2017 (where it used to be hosted on jayomayo.host - lol) however since
losing the <code>havox.org</code> domain, I will be using <code>umbra.cyou</code> for the foreseeable future</p>
<h2>Daily Trump Quote</h2>
<p>
<?=$quote;?>
</p>
</article> </article>
<article id="s2"> <article id="s2">
<h2>Tutorials&nbsp<i class="fas fa-code"></i></h2> <h2>Tutorials&nbsp<i class="fas fa-code"></i></h2>
<div onclick="window.location='imgTut/summed-area.html'" class="tut_box"> <div onclick="window.location='/tutorials/summed_area/index.html'" class="tut_box">
<p class="tut_date">3 Jan 2021</p> <p class="tut_date">3 Jan 2021</p>
<a href="imgTut/summed-area.html" class="tutName">Summed area tables</a> <a href="/tutorials/summed_area/index.html" class="tutName">Summed area tables</a>
<p>This tutorial looks at intergral images and how they're useful.</p> <p>This tutorial looks at intergral images and how they're useful.</p>
</div> </div>
<div onclick="window.location='terrainGen/index.html'" class="tut_box">
<p class="tut_date">3 Feb 2019</p>
<a href="terrainGen/index.html" class="tutName">Midpoint displacement terrain generation</a>
<p>This tutorial looks at generating random and natural looking 2D terrains.</p>
</div>
<div onclick="window.location='jarvisMarsh/index.php'" class="tut_box"> <div onclick="window.location='/tutorials/midpoint_displacement/index.html'" class="tut_box">
<p class="tut_date">14 Feb 2018</p> <p class="tut_date">3 Feb 2019</p>
<a href="jarvisMarsh/index.php" class="tutName">Convex hull Generator</a> <a href="/tutorials/midpoint_displacement/index.html" class="tutName">Midpoint displacement terrain
<p>This tutorial looks at wrapping algorithms.</p> generation</a>
</div> <p>This tutorial looks at generating random and natural looking 2D terrains.</p>
</div>
<div onclick="window.location='TSP_files/index.php'" class="tut_box"> <div onclick="window.location='/tutorials/convex_hull/index.html'" class="tut_box">
<p class="tut_date">22 Sep 2018</p> <p class="tut_date">14 Feb 2018</p>
<a href="TSP_files/index.php" class="tutName">Travelling sales person</a> <a href="/tutorials/convex_hull/index.html" class="tutName">Convex hull Generator</a>
<p>This tutorial looks at different implementations of the TSP problem and how different solutions can be implemented.</p> <p>This tutorial looks at wrapping algorithms.</p>
</div> </div>
<div onclick="window.location='/tutorials/tsp/index.html'" class="tut_box">
<p class="tut_date">22 Sep 2018</p>
<a href="/tutorials/tsp/index.html" class="tutName">Travelling sales person</a>
<p>This tutorial looks at different implementations of the TSP problem and how different solutions can be
implemented.</p>
</div>
</article> </article>
<article id="s3"> <article id="s3">
<h2>Projects&nbsp<i class="fas fa-code"></i></h2> <h2>Projects&nbsp<i class="fas fa-code"></i></h2>
<p>Please note a lot of these projects use <code>mouseClicked()</code> functions which don't work with mobile :(</p> <p>Please note a lot of these projects use <code>mouseClicked()</code> functions which don't work with mobile :(</p>
<div onclick="window.location='projects/drawing_curves/index.html'" class="tut_box"> <div onclick="window.location='/projects/cubic_bezier_curve/index.html'" class="tut_box">
<p class="tut_date">1 Oct 2021</p> <p class="tut_date">1 Oct 2021</p>
<a class="tutName">Drawing bezier curves</a> <a class="tutName">Drawing bezier curves</a>
<p>An interactive animated diagram on drawing quadatric and cubic Bezier curves. Click anywhere on the canvas to place points.</p> <p>An interactive animated diagram on drawing quadatric and cubic Bezier curves. Click anywhere on the canvas to
</div> place points.</p>
</div>
<div onclick="window.location='projects/marching_squares.html'" class="tut_box"> <div onclick="window.location='/projects/marching_squares.html'" class="tut_box">
<p class="tut_date">23 Sept 2021</p> <p class="tut_date">23 Sept 2021</p>
<a class="tutName">2D Marching Squares</a> <a class="tutName">2D Marching Squares</a>
<p>A demonstration of marching squares, click a tile to edit the terrain.</p> <p>A demonstration of marching squares, click a tile to edit the terrain.</p>
</div> </div>
<div onclick="window.location='projects/sorting_vis.html'" class="tut_box"> <div onclick="window.location='/projects/warping_lines.html'" class="tut_box">
<p class="tut_date">11 Apr 2020</p> <p class="tut_date">2 Apr 2020</p>
<a class="tutName">Bubble sort visualiser</a> <a class="tutName">Warping lines illusion</a>
<p>A classic bubble sort visualiser where bars are sorted by height. One frame being one loop.</p> <p>A visualisation of the <a class="out_link"
</div> href="https://en.wikipedia.org/wiki/M%C3%BCller-Lyer_illusion#:~:text=The%20M%C3%BCller%2DLyer%20illusion%20is,consisting%20of%20three%20stylized%20arrows.&text=The%20fins%20can%20point%20inwards,the%20arrow%20with%20two%20heads.">M&uuml;ller-Lyer</a>
illusion shown in js</p>
</div>
<div onclick="window.location='projects/warp_lines.html'" class="tut_box"> <div onclick="window.location='/projects/fourier_series.html'" class="tut_box">
<p class="tut_date">2 Apr 2020</p> <p class="tut_date">27 Feb 2019</p>
<a class="tutName">Warping lines illusion</a> <a class="tutName">Fourier Series</a>
<p>A visualisation of the <a class="out_link" href="https://en.wikipedia.org/wiki/M%C3%BCller-Lyer_illusion#:~:text=The%20M%C3%BCller%2DLyer%20illusion%20is,consisting%20of%20three%20stylized%20arrows.&text=The%20fins%20can%20point%20inwards,the%20arrow%20with%20two%20heads.">M&uuml;ller-Lyer</a> illusion shown in js</p> <p>A project showing how a square wave can be made with just sin waves.</p>
</div> </div>
<div onclick="window.location='projects/fourier_series.html'" class="tut_box"> <div onclick="window.location='/projects/ellipse_construction.html'" class="tut_box">
<p class="tut_date">27 Feb 2019</p> <p class="tut_date">23 Feb 2019</p>
<a class="tutName">Fourier Series</a> <a class="tutName">Constructing an ellispse</a>
<p>A project showing how a square wave can be made with just sin waves.</p> <p>A visualisation of how an ellipse can be constructed with a circle and radial lines. <a class="out_link"
</div> href="https://twitter.com/3blue1brown/status/1016936129117937664?lang=en">inspo</a></p>
</div>
<div onclick="window.location='projects/ellipse_const.html'" class="tut_box"> <div onclick="window.location='/projects/game_of_life.html'" class="tut_box">
<p class="tut_date">23 Feb 2019</p> <p class="tut_date">2 May 2018</p>
<a class="tutName">Constructing an ellispse</a> <a class="tutName">Game of Life</a>
<p>A visualisation of how an ellipse can be constructed with a circle and radial lines. <a class="out_link" href="https://twitter.com/3blue1brown/status/1016936129117937664?lang=en">inspo</a></p> <p>A js implementation of the classic Game of Life - John Conway.</p>
</div> </div>
<div onclick="window.location='projects/gameoflife.php'" class="tut_box"> <div onclick="window.location='/projects/pi_approximation.html'" class="tut_box">
<p class="tut_date">2 May 2018</p> <p class="tut_date">18 Mar 2018</p>
<a class="tutName">Game of Life</a> <a class="tutName">Calculating PI</a>
<p>A js implementation of the classic Game of Life - John Conway.</p> <p>A simulation that looks at the ratio of randomly placed dots between a square and circle to calulate PI.</p>
</div> </div>
<div onclick="window.location='projects/piApprox.php'" class="tut_box"> <div onclick="window.location='/projects/oscillations_in_3d.html'" class="tut_box">
<p class="tut_date">18 Mar 2018</p> <p class="tut_date">17 Dec 2017</p>
<a class="tutName">Calculating PI</a> <a class="tutName">Oscillations in 3D</a>
<p>A simulation that looks at the ratio of randomly placed dots between a square and circle to calulate PI.</p> <p>A js implementation of <a class="out_link"
</div> href="https://twitter.com/beesandbombs/status/940639806522085376">Bees and Bomb's gif.</a></p>
</div>
<div onclick="window.location='projects/oscil.php'" class="tut_box"> <div onclick="window.location='/projects/maze_generation.html'" class="tut_box">
<p class="tut_date">17 Dec 2017</p> <p class="tut_date">13 Nov 2017</p>
<a class="tutName">Oscillations in 3D</a> <a class="tutName">Maze Generator</a>
<p>A js implementation of <a class="out_link" href="https://twitter.com/beesandbombs/status/940639806522085376">Bees and Bomb's gif.</a></p> <p>A maze generator built in js.</p>
</div> </div>
<div onclick="window.location='projects/mazeGen.php'" class="tut_box">
<p class="tut_date">13 Nov 2017</p>
<a class="tutName">Maze Generator</a>
<p>A maze generator built in js.</p>
</div>
</article> </article>
<article class="margin" id="s4"> <article class="margin" id="s4">
<h2>Credits</h2> <h2>Credits</h2>
<p>Thank you to @uixmat for inspiration <strike>and some code</strike> for this webpage, check out his <a href="https://twitter.com/uixmat/" target="_blank">twitter</a>.</p> <p>Thank you to @uixmat for inspiration <strike>and some code</strike> for this webpage, check out his <a
<p>Also shoutout to <a href="https://www.youtube.com/user/shiffman">Daniel Shiffman</a> and the <a href="https://p5js.org">P5 team</a>. P5 is used extensively in these tutorials & projects</p> href="https://twitter.com/uixmat/" target="_blank">twitter</a>.</p>
<p>Also shoutout to <a href="https://www.youtube.com/user/shiffman">Daniel Shiffman</a> and the <a
href="https://p5js.org">P5 team</a>. P5 is used extensively in these tutorials & projects</p>
</article> </article>
</html> </html>

View File

@@ -1,195 +1,177 @@
<!doctype html> <!doctype html>
<html> <html>
<head> <head>
<title>Projects</title> <title>Projects</title>
<meta charset="utf-8" /> <meta charset="utf-8" />
<meta name="viewport" <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no" />
content="width=device-width, initial-scale=1, user-scalable=no" />
<link rel="stylesheet" href="assets/css/main.css" /> <link rel="stylesheet" href="assets/css/main.css" />
<noscript> <noscript>
<link rel="stylesheet" href="assets/css/noscript.css" /> <link rel="stylesheet" href="assets/css/noscript.css" />
</noscript> </noscript>
<link rel="apple-touch-icon" sizes="180x180" <link rel="apple-touch-icon" sizes="180x180" href="favicon/apple-touch-icon.png" />
href="favicon/apple-touch-icon.png" /> <link rel="icon" type="image/png" sizes="32x32" href="favicon/favicon-32x32.png" />
<link rel="icon" type="image/png" sizes="32x32" <link rel="icon" type="image/png" sizes="16x16" href="favicon/favicon-16x16.png" />
href="favicon/favicon-32x32.png" />
<link rel="icon" type="image/png" sizes="16x16"
href="favicon/favicon-16x16.png" />
<link rel="manifest" href="favicon/site.webmanifest" /> <link rel="manifest" href="favicon/site.webmanifest" />
</head> </head>
<body class="is-preload"> <body class="is-preload">
<!-- Wrapper --> <!-- Wrapper -->
<div id="wrapper"> <div id="wrapper">
<!-- Header --> <!-- Header -->
<header> <header>
<h1>Projects</h1> <h1>Projects</h1>
</header> </header>
<!-- Main --> <!-- Main -->
<div id="main"> <div id="main">
<!-- Content --> <!-- Content -->
<section id="content" class="main"> <section id="content" class="main">
<span class="image main"><img src="images/dddepth-088.jpg" <span class="image main"><img src="images/dddepth-088.jpg" alt="" /></span>
alt="" /></span> <h2>Projects</h2>
<h2>Projects</h2> <p>
<p> Here are some Projects I've worked on over the years, I do this to
Here are some Projects I've worked on over the years, I do this to further my understanding of a topic.
further my understanding of a topic.
</p>
<div class="card-container">
<a class="box-wrapper" href="https://samstoreymusic.com">
<div class="card">
<h2 class="title">Sam Storey Music</h2>
<img src="images/samstoreymusic.png" />
<p class="description">
I designed this website for the client as a portfolio of his
music and achievements. samstoreymusic.com is also hosted by
myself.
</p> </p>
<p class="date">20th Jun 2023</p> <div class="card-container">
</div> <a class="box-wrapper" href="https://samstoreymusic.com">
</a> <div class="card">
<a class="box-wrapper" href="projects/drawing_curves/index.html"> <h2 class="title">Sam Storey Music</h2>
<div class="card"> <img src="images/samstoreymusic.png" />
<h2 class="title">Drawing Bezier Curves</h2> <p class="description">
<img src="images/bezier_curves.jpg" /> I designed this website for the client as a portfolio of his
<p class="description"> music and achievements. samstoreymusic.com is also hosted by
An interactive animated diagram on drawing quadratic and cubic myself.
Bezier curves. Click anywhere on the canvas to place your </p>
points. <p class="date">20th Jun 2023</p>
</p> </div>
<p class="date">1st Oct 2021</p> </a>
</div> <a class="box-wrapper" href="/projects/cubic_bezier_curve/index.html">
</a> <div class="card">
<a class="box-wrapper" href="projects/marching_squares.html"> <h2 class="title">Drawing Bezier Curves</h2>
<div class="card"> <img src="images/bezier_curves.jpg" />
<h2 class="title">2D Marching Squares</h2> <p class="description">
<img src="images/marching_squares.png" /> An interactive animated diagram on drawing quadratic and cubic
<p class="description"> Bezier curves. Click anywhere on the canvas to place your
A demonstration of marching squares. Click a tile to edit the points.
terrain. </p>
</p> <p class="date">1st Oct 2021</p>
<p class="date">23rd Sept 2021</p> </div>
</div> </a>
</a> <a class="box-wrapper" href="/projects/marching_squares.html">
<a class="box-wrapper" href="projects/sorting_vis.html"> <div class="card">
<div class="card"> <h2 class="title">2D Marching Squares</h2>
<h2 class="title">Bubble Sort Visualiser</h2> <img src="images/marching_squares.png" />
<img src="images/bubble_sort.png" /> <p class="description">
<p class="description"> A demonstration of marching squares. Click a tile to edit the
A classic bubble sort visualiser where bars are sorted by terrain.
height. Where two elements are swapped each frame. </p>
</p> <p class="date">23rd Sept 2021</p>
<p class="date">11th Apr 2020</p> </div>
</div> </a>
</a> <!-- <a class="box-wrapper" href="#"> -->
<!-- <a class="box-wrapper" href="#"> --> <!-- <div class="card"> -->
<!-- <div class="card"> --> <!-- <h2 class="title">Warping Lines Illusion</h2> -->
<!-- <h2 class="title">Warping Lines Illusion</h2> --> <!-- <img src="images/tsp.png" /> -->
<!-- <img src="images/tsp.png" /> --> <!-- <p class="description"> -->
<!-- <p class="description"> --> <!-- A visualisation of the -->
<!-- A visualisation of the --> <!-- <a -->
<!-- <a --> <!-- href="https://en.wikipedia.org/wiki/M%C3%BCller-Lyer_illusion#:~:text=The%20M%C3%BCller%2DLyer%20illusion%20is,consisting%20of%20three%20stylized%20arrows.&text=The%20fins%20can%20point%20inwards,the%20arrow%20with%20two%20heads." -->
<!-- href="https://en.wikipedia.org/wiki/M%C3%BCller-Lyer_illusion#:~:text=The%20M%C3%BCller%2DLyer%20illusion%20is,consisting%20of%20three%20stylized%20arrows.&text=The%20fins%20can%20point%20inwards,the%20arrow%20with%20two%20heads." --> <!-- >Muller-Lyer</a -->
<!-- >Muller-Lyer</a --> <!-- > -->
<!-- > --> <!-- illusion. -->
<!-- illusion. --> <!-- </p> -->
<!-- </p> --> <!-- <p class="date">2nd Apr 2019</p> -->
<!-- <p class="date">2nd Apr 2019</p> --> <!-- </div> -->
<!-- </div> --> <!-- </a> -->
<!-- </a> --> <a class="box-wrapper" href="/projects/fourier_series.html">
<a class="box-wrapper" href="projects/fourier_series.html"> <div class="card">
<div class="card"> <h2 class="title">Fourier Series</h2>
<h2 class="title">Fourier Series</h2> <img src="images/fourier_series.png" />
<img src="images/fourier_series.png" /> <p class="description">
<p class="description"> A project showing how a square wave can be constructed by
A project showing how a square wave can be constructed by additive sin waves.
additive sin waves. </p>
</p> <p class="date">27th Feb 2019</p>
<p class="date">27th Feb 2019</p> </div>
</div> </a>
</a> <a class="box-wrapper" href="/projects/ellipse_construction.html">
<a class="box-wrapper" href="projects/ellipse_const.html"> <div class="card">
<div class="card"> <h2 class="title">Constructing an Ellipse</h2>
<h2 class="title">Constructing an Ellipse</h2> <img src="images/construct_ellipse.png" />
<img src="images/construct_ellipse.png" /> <p class="description">
<p class="description"> A visualisation of how an ellipse can be constructed with a
A visualisation of how an ellipse can be constructed with a circle and radial lines. Inspired by Feyman's Lost Lecture.
circle and radial lines. Inspired by Feyman's Lost Lecture. <!-- <a -->
<!-- <a --> <!-- href="https://www.amazon.co.uk/Feynmans-Lost-Lecture-Motions-Planets/dp/0099736217" -->
<!-- href="https://www.amazon.co.uk/Feynmans-Lost-Lecture-Motions-Planets/dp/0099736217" --> <!-- >Feynam's Lost Lecture</a -->
<!-- >Feynam's Lost Lecture</a --> <!-- >. -->
<!-- >. --> </p>
</p> <p class="date">23rd Feb 2019</p>
<p class="date">23rd Feb 2019</p> </div>
</div> </a>
</a> <a class="box-wrapper" href="/projects/game_of_life.html">
<a class="box-wrapper" href="projects/gameoflife.php"> <div class="card">
<div class="card"> <h2 class="title">Game of Life</h2>
<h2 class="title">Game of Life</h2> <img src="images/game_of_life.png" />
<img src="images/game_of_life.png" /> <p class="description">
<p class="description"> An implementation of the classic cellular automata: Game of
An implementation of the classic cellular automata: Game of Life in javascript.
Life in javascript. </p>
</p> <p class="date">2nd May 2018</p>
<p class="date">2nd May 2018</p> </div>
</div> </a>
</a> <a class="box-wrapper" href="/projects/pi_approximation.html">
<a class="box-wrapper" href="projects/piApprox.php"> <div class="card">
<div class="card"> <h2 class="title">Calculating PI</h2>
<h2 class="title">Calculating PI</h2> <img src="images/calc_pi.png" />
<img src="images/calc_pi.png" /> <p class="description">
<p class="description"> A simulation that randomly places dots on the canvas, the
A simulation that randomly places dots on the canvas, the ratio of dots that are placed in the cirlce vs not approximate
ratio of dots that are placed in the cirlce vs not approximate PI.
PI. </p>
</p> <p class="date">14th March 2018</p>
<p class="date">14th March 2018</p> </div>
</div> </a>
</a> <a class="box-wrapper" href="/projects/oscillations_in_3d.html">
<a class="box-wrapper" href="projects/oscil.php"> <div class="card">
<div class="card"> <h2 class="title">Oscillations in 3D</h2>
<h2 class="title">Oscillations in 3D</h2> <img src="images/bees_and_bombs.png" />
<img src="images/bees_and_bombs.png" /> <p class="description">
<p class="description"> An implementation of bees and bomb's
An implementation of bees and bomb's <!-- <a -->
<!-- <a --> <!-- href="https://twitter.com/beesandbombs/status/940639806522085376" -->
<!-- href="https://twitter.com/beesandbombs/status/940639806522085376" --> <!-- >Bees and Bomb's gif</a -->
<!-- >Bees and Bomb's gif</a --> <!-- > -->
<!-- > --> in p5js.
in p5js. </p>
</p> <p class="date">17th Dec 2017</p>
<p class="date">17th Dec 2017</p> </div>
</div> </a>
</a> </div>
</div> </section>
</section> </div>
</div>
<!-- Footer --> <!-- Footer -->
<footer id="footer"> <footer id="footer">
<section> <section>
<h2>Contact me</h2> <h2>Contact me</h2>
<p>Feel free to get in touch through:</p> <p>Feel free to get in touch through:</p>
<dl class="alt"> <dl class="alt">
<dt>Email</dt> <dt>Email</dt>
<dd><a href="#">information@untitled.tld</a></dd> <dd><a href="#">information@untitled.tld</a></dd>
</dl> </dl>
<ul class="icons"> <ul class="icons">
<li> <li>
<a href="#" class="icon brands fa-github alt"><span <a href="#" class="icon brands fa-github alt"><span class="label">GitHub</span></a>
class="label">GitHub</span></a> </li>
</li> <li>
<li> <a href="#" class="icon brands fa-linkedin alt"><span class="label">Linkedin</span></a>
<a href="#" class="icon brands fa-linkedin alt"><span </li>
class="label">Linkedin</span></a> </ul>
</li> </section>
</ul> </footer>
</section>
</footer>
</div> </div>
<!-- Scripts --> <!-- Scripts -->
@@ -200,6 +182,6 @@
<script src="assets/js/breakpoints.min.js"></script> <script src="assets/js/breakpoints.min.js"></script>
<script src="assets/js/util.js"></script> <script src="assets/js/util.js"></script>
<script src="assets/js/main.js"></script> <script src="assets/js/main.js"></script>
</body> </body>
</html> </html>

View File

@@ -1,113 +1,106 @@
<!doctype html> <!doctype html>
<html> <html>
<head> <head>
<title>Tutorials</title> <title>Tutorials</title>
<meta charset="utf-8" /> <meta charset="utf-8" />
<meta name="viewport" <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no" />
content="width=device-width, initial-scale=1, user-scalable=no" />
<link rel="stylesheet" href="assets/css/main.css" /> <link rel="stylesheet" href="assets/css/main.css" />
<noscript> <noscript>
<link rel="stylesheet" href="assets/css/noscript.css" /> <link rel="stylesheet" href="assets/css/noscript.css" />
</noscript> </noscript>
<link rel="apple-touch-icon" sizes="180x180" <link rel="apple-touch-icon" sizes="180x180" href="favicon/apple-touch-icon.png" />
href="favicon/apple-touch-icon.png" /> <link rel="icon" type="image/png" sizes="32x32" href="favicon/favicon-32x32.png" />
<link rel="icon" type="image/png" sizes="32x32" <link rel="icon" type="image/png" sizes="16x16" href="favicon/favicon-16x16.png" />
href="favicon/favicon-32x32.png" />
<link rel="icon" type="image/png" sizes="16x16"
href="favicon/favicon-16x16.png" />
<link rel="manifest" href="favicon/site.webmanifest" /> <link rel="manifest" href="favicon/site.webmanifest" />
</head> </head>
<body class="is-preload"> <body class="is-preload">
<!-- Wrapper --> <!-- Wrapper -->
<div id="wrapper"> <div id="wrapper">
<!-- Header --> <!-- Header -->
<header> <header>
<h1>Tutorials</h1> <h1>Tutorials</h1>
</header> </header>
<!-- Main --> <!-- Main -->
<div id="main"> <div id="main">
<!-- Content --> <!-- Content -->
<section id="content" class="main"> <section id="content" class="main">
<span class="image main"><img src="images/dddepth-301.jpg" <span class="image main"><img src="images/dddepth-301.jpg" alt="" /></span>
alt="" /></span> <h2>Tutorials</h2>
<h2>Tutorials</h2> <p>
<p> Here are some tutorials I've worked on over the years, I do this to
Here are some tutorials I've worked on over the years, I do this to further my understanding of a topic.
further my understanding of a topic.
</p>
<div class="card-container">
<a class="box-wrapper" href="tutorials/summed_area/">
<div class="card">
<h2 class="title">Summed Area Tables</h2>
<img src="images/summed_area.png" />
<p class="description">
This tutorial looks at intergral images and how they're
useful.
</p> </p>
<p class="date">3rd Jan 2021</p> <div class="card-container">
</div> <a class="box-wrapper" href="/tutorials/summed_area/index.html">
</a> <div class="card">
<a class="box-wrapper" href="tutorials/terrainGen/index.html"> <h2 class="title">Summed Area Tables</h2>
<div class="card"> <img src="images/summed_area.png" />
<h2 class="title">Midpoint Displacement Terrain Generation</h2> <p class="description">
<img src="images/midpoint_displacement.png" /> This tutorial looks at intergral images and how they're
<p class="description"> useful.
This tutorial looks at generating random and natural looking </p>
2D terrains. <p class="date">3rd Jan 2021</p>
</p> </div>
<p class="date">3rd Feb 2019</p> </a>
</div> <a class="box-wrapper" href="/tutorials/midpoint_displacement/index.html">
</a> <div class="card">
<a class="box-wrapper" href="tutorials/jarvisMarsh/index.php"> <h2 class="title">Midpoint Displacement Terrain Generation</h2>
<div class="card"> <img src="images/midpoint_displacement.png" />
<h2 class="title">Convex Hull Generator</h2> <p class="description">
<img src="images/convex_hull.png" /> This tutorial looks at generating random and natural looking
<p class="description"> 2D terrains.
This tutorial looks at wrapping algorithms. </p>
</p> <p class="date">3rd Feb 2019</p>
<p class="date">14th Feb 2018</p> </div>
</div> </a>
</a> <a class="box-wrapper" href="/tutorials/convex_hull/index.html">
<a class="box-wrapper" href="tutorials/TSP_files/index.php"> <div class="card">
<div class="card"> <h2 class="title">Convex Hull Generator</h2>
<h2 class="title">Travelling Sales Person</h2> <img src="images/convex_hull.png" />
<img src="images/tsp.png" /> <p class="description">
<p class="description"> This tutorial looks at wrapping algorithms.
This tutorial looks at different implementations of the TSP </p>
problem and how different solutions can be implemented. <p class="date">14th Feb 2018</p>
</p> </div>
<p class="date">22nd Sept 2018</p> </a>
</div> <a class="box-wrapper" href="/tutorials/tsp/index.html">
</a> <div class="card">
</div> <h2 class="title">Travelling Sales Person</h2>
</section> <img src="images/tsp.png" />
</div> <p class="description">
This tutorial looks at different implementations of the TSP
problem and how different solutions can be implemented.
</p>
<p class="date">22nd Sept 2018</p>
</div>
</a>
</div>
</section>
</div>
<!-- Footer --> <!-- Footer -->
<footer id="footer"> <footer id="footer">
<section> <section>
<h2>Contact me</h2> <h2>Contact me</h2>
<p>Feel free to get in touch through:</p> <p>Feel free to get in touch through:</p>
<dl class="alt"> <dl class="alt">
<dt>Email</dt> <dt>Email</dt>
<dd><a href="#">information@untitled.tld</a></dd> <dd><a href="#">information@untitled.tld</a></dd>
</dl> </dl>
<ul class="icons"> <ul class="icons">
<li> <li>
<a href="#" class="icon brands fa-github alt"><span <a href="#" class="icon brands fa-github alt"><span class="label">GitHub</span></a>
class="label">GitHub</span></a> </li>
</li> <li>
<li> <a href="#" class="icon brands fa-linkedin alt"><span class="label">Linkedin</span></a>
<a href="#" class="icon brands fa-linkedin alt"><span </li>
class="label">Linkedin</span></a> </ul>
</li> </section>
</ul> </footer>
</section>
</footer>
</div> </div>
<!-- Scripts --> <!-- Scripts -->
@@ -118,6 +111,6 @@
<script src="assets/js/breakpoints.min.js"></script> <script src="assets/js/breakpoints.min.js"></script>
<script src="assets/js/util.js"></script> <script src="assets/js/util.js"></script>
<script src="assets/js/main.js"></script> <script src="assets/js/main.js"></script>
</body> </body>
</html> </html>

View File

@@ -217,14 +217,12 @@
<p class="section-label reveal">projects</p> <p class="section-label reveal">projects</p>
<h2 class="section-heading reveal" style="transition-delay:0.05s">Things I <em>built</em></h2> <h2 class="section-heading reveal" style="transition-delay:0.05s">Things I <em>built</em></h2>
<p class="section-intro reveal" style="transition-delay:0.1s"> <p class="section-intro reveal" style="transition-delay:0.1s">
Mostly p5.js — visualising algorithms in ways that look more interesting than they have any right to. Most Recent projects & things I found interesting. I have gone to painstaking lengths to not edit my older
use <code projects... we all start somewhere.
style="background:var(--surface0);color:var(--peach);padding:1px 5px;border-radius:3px;font-size:0.8em">mouseClicked()</code>
so desktop only, sorry mobile.
</p> </p>
<div class="card-grid reveal" style="transition-delay:0.15s"> <div class="card-grid reveal" style="transition-delay:0.15s">
<a class="card" href="projects/drawing_curves/index.html"> <a class="card" href="projects/cubic_bezier_curve/index.html">
<span class="card-date">1 Oct 2021</span> <span class="card-date">1 Oct 2021</span>
<span class="card-title">Drawing Bézier curves</span> <span class="card-title">Drawing Bézier curves</span>
<span class="card-desc">Interactive animated diagram for quadratic and cubic Bézier curves. Click to <span class="card-desc">Interactive animated diagram for quadratic and cubic Bézier curves. Click to
@@ -237,7 +235,7 @@
<span class="card-desc">Marching squares in action — click a tile to edit the terrain.</span> <span class="card-desc">Marching squares in action — click a tile to edit the terrain.</span>
<span class="card-arrow"></span> <span class="card-arrow"></span>
</a> </a>
<a class="card" href="projects/warp_lines.html"> <a class="card" href="projects/warping_lines.html">
<span class="card-date">2 Apr 2020</span> <span class="card-date">2 Apr 2020</span>
<span class="card-title">Müller-Lyer illusion</span> <span class="card-title">Müller-Lyer illusion</span>
<span class="card-desc">A visualisation of the Müller-Lyer optical illusion rendered in JS.</span> <span class="card-desc">A visualisation of the Müller-Lyer optical illusion rendered in JS.</span>

View File

@@ -0,0 +1,13 @@
class cLine {
constructor(a, b, col = color(180, 180, 180, 140), w = 2) {
this.a = a;
this.b = b;
this.col = col;
this.w = w;
}
drawLine() {
stroke(this.col);
strokeWeight(this.w);
line(this.a.x, this.a.y, this.b.x, this.b.y);
}
}

View File

@@ -0,0 +1,44 @@
class cPoint {
constructor(x, y, kind = 'control') {
this.x = x;
this.y = y;
this.kind = kind;
this.r = 9;
}
set changeX(nx) { this.x = nx; }
set changeY(ny) { this.y = ny; }
get changeX() { return this.x; }
get changeY() { return this.y; }
isHit(mx, my, r = HIT_R) {
return dist(mx, my, this.x, this.y) <= r;
}
drawPoint(hovered = false, selected = false, styleOverride = null) {
strokeWeight(2);
if (styleOverride) {
stroke(...styleOverride.stroke);
fill(...styleOverride.fill);
} else {
if (this.kind === 'end') {
stroke(0, 220, 90, 240);
fill(40, 240, 120, 200);
} else if (this.kind === 'control') {
stroke(240, 140, 0, 240);
fill(255, 180, 40, 200);
} else {
stroke(140, 160);
fill(190, 160);
}
}
if (selected) {
stroke(255, 255, 0);
strokeWeight(3);
} else if (hovered) {
stroke(255);
}
circle(this.x, this.y, this.r * 2);
}
}

View File

@@ -1,14 +1,15 @@
<!DOCTYPE html> <!DOCTYPE html>
<html> <html>
<head>
<head>
<meta name="viewport" width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0> <meta name="viewport" width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0>
<script src="https://cdn.jsdelivr.net/npm/p5@1.4.0/lib/p5.min.js"></script> <script src="https://cdn.jsdelivr.net/npm/p5@1.4.0/lib/p5.min.js"></script>
<script src="cPoint.js"></script> <script src="cPoint.js"></script>
<script src="cLine.js"></script> <script src="cLine.js"></script>
<!-- <script src="quadCurve.js"></script> --> <script src="sketch.js"></script>
<script src="cubicCurve.js"></script> </head>
<!-- <script src="vectorForm.js"></script> -->
</head> <body>
<body> </body>
</body>
</html> </html>

View File

@@ -0,0 +1,239 @@
let p = [], v = [];
let lines = [];
let theta = (3 / 2) * Math.PI, t = 0;
let paused = false;
let showLabels = false;
let showInterPoints = true;
let hoverIndex = -1;
let selectedIndex = -1;
let prevMouse = { x: 0, y: 0 };
let draggingAll = false;
const HIT_R = 10;
const MAX_TRAIL = 1000;
function setup() {
createCanvas(1000, 800);
initCubicCurve(true);
}
function draw() {
background(32);
stroke(120, 120, 120, 180);
strokeWeight(2);
noFill();
beginShape();
vertex(p[0].x, p[0].y);
vertex(p[1].x, p[1].y);
vertex(p[2].x, p[2].y);
vertex(p[3].x, p[3].y);
endShape();
if (!paused) {
if (theta > TWO_PI) theta = 0;
theta += 0.01;
t = (sin(theta) + 1) / 2; // 0..1
}
lerpCubicCurve();
for (let i = 0; i < lines.length; i++) {
lines[i].drawLine();
}
drawCurve();
drawPointsAndLabels();
drawHUD();
}
function drawCurve() {
if (v.length > MAX_TRAIL) v.splice(0, v.length - MAX_TRAIL);
stroke(0, 255, 0, 200);
strokeWeight(5);
noFill();
beginShape();
for (let i = 0; i < v.length; i++) {
vertex(v[i].x, v[i].y);
}
endShape();
}
function drawPointsAndLabels() {
push();
noStroke();
fill(255, 70, 70, 230);
circle(p[9].x, p[9].y, 14);
pop();
for (let i = 0; i < 4; i++) {
const hovered = (i === hoverIndex);
const selected = (i === selectedIndex);
p[i].drawPoint(hovered, selected);
if (showLabels) {
noStroke();
fill(255);
textSize(14);
textAlign(LEFT, BOTTOM);
text(`P${i}`, p[i].x + 10, p[i].y - 10);
}
}
if (showLabels) {
noStroke(); fill(220);
textSize(12); textAlign(LEFT, BOTTOM);
text(`P4`, p[4].x + 8, p[4].y - 8);
}
if (showInterPoints) {
const styleMid = {
stroke: [80, 180, 255, 100],
fill: [80, 180, 255, 50]
};
for (let i = 4; i <= 8; i++) {
p[i].drawPoint(false, false, styleMid);
if (showLabels) {
noStroke(); fill(200);
textSize(12); textAlign(LEFT, BOTTOM);
text(`P${i}`, p[i].x + 8, p[i].y - 8);
}
}
}
}
function drawHUD() {
noStroke();
fill(255);
textSize(14);
textAlign(LEFT, TOP);
const hud = [
`t = ${t.toFixed(3)}`,
`Space = ${paused ? 'Resume' : 'Pause'}`,
`H = Toggle points 5..8 | L = Toggle labels | R = Reset`,
`Drag a handle (P0..P3). Hold Shift to move the entire curve.`
];
for (let i = 0; i < hud.length; i++) {
text(hud[i], 12, 12 + i * 18);
}
}
function initCubicCurve(resetPositions = true) {
p.length = 0;
v.length = 0;
lines.length = 0;
theta = (3 / 2) * Math.PI;
t = 0;
if (resetPositions) {
p[0] = new cPoint(width * 0.15, height * 0.75, 'end');
p[1] = new cPoint(width * 0.35, height * 0.20, 'control');
p[2] = new cPoint(width * 0.65, height * 0.20, 'control');
p[3] = new cPoint(width * 0.85, height * 0.75, 'end');
} else {
for (let i = 0; i < 4; i++) {
if (!p[i]) p[i] = new cPoint(width * (0.15 + i * 0.2), height / 2, i === 0 || i === 3 ? 'end' : 'control');
}
}
// Derived points
p[4] = new cPoint(0, 0, 'derived');
p[5] = new cPoint(0, 0, 'derived');
p[6] = new cPoint(0, 0, 'derived');
p[7] = new cPoint(0, 0, 'derived');
p[8] = new cPoint(0, 0, 'derived');
p[9] = new cPoint(0, 0, 'derived');
lines[0] = new cLine(p[4], p[5], color(160, 160, 160, 200), 2);
lines[1] = new cLine(p[5], p[6], color(160, 160, 160, 200), 2);
lines[2] = new cLine(p[7], p[8], color(200, 200, 200, 220), 3);
}
function lerpCubicCurve() {
// Level 1
p[4].changeX = (1 - t) * p[0].x + t * p[1].x;
p[4].changeY = (1 - t) * p[0].y + t * p[1].y;
p[5].changeX = (1 - t) * p[1].x + t * p[2].x;
p[5].changeY = (1 - t) * p[1].y + t * p[2].y;
p[6].changeX = (1 - t) * p[2].x + t * p[3].x;
p[6].changeY = (1 - t) * p[2].y + t * p[3].y;
// Level 2
p[7].changeX = (1 - t) * p[4].x + t * p[5].x;
p[7].changeY = (1 - t) * p[4].y + t * p[5].y;
p[8].changeX = (1 - t) * p[5].x + t * p[6].x;
p[8].changeY = (1 - t) * p[5].y + t * p[6].y;
// Final on-curve
p[9].changeX = (1 - t) * p[7].x + t * p[8].x;
p[9].changeY = (1 - t) * p[7].y + t * p[8].y;
v.push(new cPoint(p[9].x, p[9].y, 'derived'));
}
function mouseMoved() {
hoverIndex = -1;
for (let i = 0; i < 4; i++) {
if (p[i].isHit(mouseX, mouseY)) {
hoverIndex = i;
break;
}
}
}
function mousePressed() {
prevMouse.x = mouseX;
prevMouse.y = mouseY;
selectedIndex = -1;
for (let i = 0; i < 4; i++) {
if (p[i].isHit(mouseX, mouseY)) {
selectedIndex = i;
break;
}
}
draggingAll = keyIsDown(SHIFT) && selectedIndex === -1;
}
function mouseDragged() {
const dx = mouseX - prevMouse.x;
const dy = mouseY - prevMouse.y;
if (selectedIndex >= 0) {
p[selectedIndex].changeX = mouseX;
p[selectedIndex].changeY = mouseY;
v.length = 0;
} else if (draggingAll) {
for (let i = 0; i < 4; i++) {
p[i].changeX = p[i].x + dx;
p[i].changeY = p[i].y + dy;
}
v.length = 0;
}
prevMouse.x = mouseX;
prevMouse.y = mouseY;
return false;
}
function mouseReleased() {
selectedIndex = -1;
draggingAll = false;
}
function keyPressed() {
if (key === ' ') {
paused = !paused;
} else if (key === 'R' || key === 'r') {
initCubicCurve(true);
} else if (key === 'H' || key === 'h') {
showInterPoints = !showInterPoints;
} else if (key === 'L' || key === 'l') {
showLabels = !showLabels;
}
}

View File

@@ -1,13 +0,0 @@
class cLine{
constructor(p1, p2){
this.p1 = p1;
this.p2 = p2;
}
drawLine(){
stroke(255, 50);
strokeWeight(3);
line(this.p1.x, this.p1.y, this.p2.x, this.p2.y);
}
}

View File

@@ -1,14 +0,0 @@
class cPoint{
constructor(x,y) {this.x = x; this.y=y;}
drawPoint(){
strokeWeight(14);
stroke(255, 200);
point(this.x, this.y);
}
get getX(){return this.x;}
get getY(){return this.y;}
set changeX(_x){this.x = _x;}
set changeY(_y){this.y = _y;}
}

View File

@@ -1,111 +0,0 @@
let p = [], v=[];
let lines = [];
let theta=3/2 * Math.PI, t=0, clicks=0;
function setup(){
createCanvas(1000, 800);
initCubicCurve();
}
function draw(){
background(63);
for(let i = 0; i < p.length; i++){
p[i].drawPoint();
}
if(clicks > 3){
for(let i = 0; i < lines.length; i++){
lines[i].drawLine();
}
lerpCubicCurve();
drawCurve();
}
}
function drawCurve(){
if (v.length > 100*Math.PI){v=[];}
stroke(0, 255, 0, 200);
strokeWeight(5);
beginShape(LINES);
for (let i=0; i < v.length; i++){
vertex(v[i].x, v[i].y);
}
endShape();
}
function mouseClicked(){
if (clicks < 5) {
p[clicks].changeX = mouseX;
p[clicks].changeY = mouseY;
} else {
let c = clicks % 4;
p[c].changeX = mouseX;
p[c].changeY = mouseY;
}
v=[];
clicks ++;
t=0;
theta=3/2 * Math.PI;
}
function mouseDragged(){
p[0].changeX = mouseX;
p[0].changeY = mouseY;
return false;
}
function initCubicCurve(){
p[0] = new cPoint(0,0);
p[1] = new cPoint(0,0);
p[2] = new cPoint(0,0);
p[3] = new cPoint(0,0);
p[4] = new cPoint(0, 0);
p[5] = new cPoint(0, 0);
p[6] = new cPoint(0, 0);
p[7] = new cPoint(0, 0);
p[8] = new cPoint(0, 0);
p[9] = new cPoint(0, 0);
lines[0] = new cLine(p[0], p[1]);
lines[1] = new cLine(p[1], p[2]);
lines[2] = new cLine(p[2], p[3]);
lines[3] = new cLine(p[4], p[5]);
lines[4] = new cLine(p[5], p[6]);
lines[5] = new cLine(p[7], p[8]);
}
function lerpCubicCurve(){
p[4].changeX = (1-t)*p[0].x + t * p[1].x;
p[4].changeY = (1-t)*p[0].y + t * p[1].y;
p[5].changeX = (1-t)*p[1].x + t * p[2].x;
p[5].changeY = (1-t)*p[1].y + t * p[2].y;
p[6].changeX = (1-t)*p[2].x + t * p[3].x;
p[6].changeY = (1-t)*p[2].y + t * p[3].y;
p[7].changeX = (1-t)*p[4].x + t * p[5].x;
p[7].changeY = (1-t)*p[4].y + t * p[5].y;
p[8].changeX = (1-t)*p[5].x + t * p[6].x;
p[8].changeY = (1-t)*p[5].y + t * p[6].y;
p[9].changeX = (1-t)*p[7].x + t * p[8].x;
p[9].changeY = (1-t)*p[7].y + t * p[8].y;
v.push(new cPoint(p[9].x, p[9].y));
if (theta > 2*Math.PI){theta=0;}
theta += 0.01;
t = (Math.sin(theta) + 1) / 2;
}

View File

@@ -1,84 +0,0 @@
let p = [], v=[];
let lines = [];
let theta=3/2 * Math.PI, t=0, clicks=0;
function setup(){
createCanvas(1000, 800);
initQuadCurve();
}
function draw(){
background(63);
for(let i = 0; i < p.length; i++){
p[i].drawPoint();
}
if(clicks > 2){
for(let i = 0; i < lines.length; i++){
lines[i].drawLine();
}
lerpQuadCurve();
drawCurve();
}
}
function drawCurve(){
if (v.length > 100*Math.PI){v=[];}
stroke(0, 255, 0, 200);
strokeWeight(5);
beginShape(LINES);
for (let i=0; i < v.length; i++){
vertex(v[i].x, v[i].y);
}
endShape();
}
function mouseClicked(){
if (clicks < 3){
p[clicks].changeX = mouseX;
p[clicks].changeY = mouseY;
} else {
let c = clicks % 3;
p[c].changeX = mouseX;
p[c].changeY = mouseY;
}
v=[];
clicks ++;
t=0;
theta=3/2 * Math.PI;
}
function initQuadCurve(){
p[0] = new cPoint(0,0);
p[1] = new cPoint(0,0);
p[2] = new cPoint(0,0);
p[3] = new cPoint(0, 0);
p[4] = new cPoint(0, 0);
p[5] = new cPoint(p[0].x, p[0].y);
lines[0] = new cLine(p[0], p[1]);
lines[1] = new cLine(p[1], p[2]);
lines[2] = new cLine(p[3], p[4]);
}
function lerpQuadCurve(){
p[3].changeX = (1-t)*p[0].x + t * p[1].x;
p[3].changeY = (1-t)*p[0].y + t * p[1].y;
p[4].changeX = (1-t)*p[1].x + t * p[2].x;
p[4].changeY = (1-t)*p[1].y + t * p[2].y;
p[5].changeX = (1-t)*p[3].x + t * p[4].x;
p[5].changeY = (1-t)*p[3].y + t * p[4].y;
v.push(new cPoint(p[5].x, p[5].y));
if (theta > 2*Math.PI){theta=0;}
theta += 0.01;
t = (Math.sin(theta) + 1) / 2;
}

View File

@@ -1,37 +0,0 @@
let t=0, theta=0;
let t1,t2,t3,t4;
function setup(){
createCanvas(1000, 1000);
}
function draw(){
background(15,26,38);
theta += 0.01;
t = (Math.sin(theta)+1)/2;
t1 = (-t)^3 + 3*t^2 - 3*t + 1;
strokeWeight(5);
textSize(40);
noFill();
stroke(217, 16, 75);
rect(50, 175, 750, 50);
text('1.00', 850, 215);
fill(217, 16, 75);
rect(50, 175, t1*325, 50);
noFill();
stroke(51, 185, 255);
rect(50, 375, 750, 50);
text('1.00', 850, 415);
stroke(16, 255, 171);
rect(50, 575, 750, 50);
text('1.00', 850, 615);
stroke(221, 192, 76);
rect(50, 775, 750, 50);
text('1.00', 850, 815);
}

View File

@@ -1,9 +1,59 @@
<!DOCTYPE html> <!DOCTYPE html>
<html> <html>
<head>
<head>
<meta name="viewport" width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0> <meta name="viewport" width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0>
<script src="https://cdn.jsdelivr.net/npm/p5@1.4.0/lib/p5.min.js"></script> <script src="https://cdn.jsdelivr.net/npm/p5@1.4.0/lib/p5.min.js"></script>
</head>
<style>
body {
font-family: system-ui, -apple-system, Segoe UI, Roboto, Helvetica, Arial, sans-serif;
margin: 16px;
background: #fafafa;
color: #222;
}
.intro {
max-width: 900px;
margin: 0 auto 18px;
padding: 0 12px;
}
.intro h1 {
font-size: 1.5rem;
margin: 0 0 6px;
}
.intro p {
margin: 4px 0 10px;
line-height: 1.45;
}
canvas {
display: block;
margin: 0 auto;
}
</style>
</head>
<body>
<div class="intro">
<h1>Marching Squares Field Visualizer</h1>
<p>
This sketch uses the <strong>Marching Squares</strong> algorithm to generate and display contour boundaries
on a grid. Each cell is either active or inactive, the algorithm determines the correct line or triangle to
draw based on the surrounding corners.
</p>
<p>
<b>Left-click</b> toggles a cell between the two states.
</p>
<p>
<b>Rightclick</b> shows or hides the contour lines produced by the algorithm.
</p>
</div>
<script> <script>
var reso = 50; var reso = 50;
var cols, rows; var cols, rows;
@@ -27,104 +77,104 @@
const cBlue = color(55, 120, 232); const cBlue = color(55, 120, 232);
const cGreen = color(146, 232, 55); const cGreen = color(146, 232, 55);
for (var i = 0; i < cols * rows; i++){ for (var i = 0; i < cols * rows; i++) {
let x = i % cols; let x = i % cols;
let y = Math.floor(i / cols); let y = Math.floor(i / cols);
let c = field[i] ? cBlue : cGreen; let c = field[i] ? cBlue : cGreen;
fill(c); fill(c);
rect(x*reso - reso*0.5, y*reso - reso*0.5, reso, reso); rect(x * reso - reso * 0.5, y * reso - reso * 0.5, reso, reso);
} }
for (var i = 0; i < cols * rows; i++) { for (var i = 0; i < cols * rows; i++) {
if (i + cols + 1 > cols * rows){break;} if (i + cols + 1 > cols * rows) {break;}
var x = (i % cols) * reso; var x = (i % cols) * reso;
var y = (Math.floor(i / cols)) * reso; var y = (Math.floor(i / cols)) * reso;
const a = [x + reso * 0.5, y ]; const a = [x + reso * 0.5, y];
const b = [x + reso, y + reso * 0.5]; const b = [x + reso, y + reso * 0.5];
const c = [x + reso * 0.5, y + reso ]; const c = [x + reso * 0.5, y + reso];
const d = [x, y + reso * 0.5]; const d = [x, y + reso * 0.5];
var s = getState(field[i], field[i+1], field[i+cols+1], field[i+cols]); var s = getState(field[i], field[i + 1], field[i + cols + 1], field[i + cols]);
noStroke(); noStroke();
switch(s) { switch (s) {
case 1: case 1:
fill(cGreen); fill(cGreen);
triangle(x + reso*0.5, y + reso*0.5, c[0], c[1], d[0], d[1]); triangle(x + reso * 0.5, y + reso * 0.5, c[0], c[1], d[0], d[1]);
break; break;
case 14: case 14:
fill(cBlue); fill(cBlue);
triangle(x + reso*0.5, y + reso*0.5, c[0], c[1], d[0], d[1]); triangle(x + reso * 0.5, y + reso * 0.5, c[0], c[1], d[0], d[1]);
break; break;
case 2: case 2:
fill(cGreen); fill(cGreen);
triangle(x + reso*0.5, y + reso*0.5, b[0], b[1], c[0], c[1]); triangle(x + reso * 0.5, y + reso * 0.5, b[0], b[1], c[0], c[1]);
break; break;
case 13: case 13:
fill(cBlue); fill(cBlue);
triangle(x + reso*0.5, y + reso*0.5, b[0], b[1], c[0], c[1]); triangle(x + reso * 0.5, y + reso * 0.5, b[0], b[1], c[0], c[1]);
break; break;
case 3: case 3:
fill(cBlue); fill(cBlue);
rect(d[0], d[1], reso, reso*0.5); rect(d[0], d[1], reso, reso * 0.5);
break; break;
case 12: case 12:
fill(cGreen); fill(cGreen);
rect(d[0], d[1], reso, reso*0.5); rect(d[0], d[1], reso, reso * 0.5);
break; break;
case 4: case 4:
fill(cGreen); fill(cGreen);
triangle(x + reso*0.5, y + reso*0.5, a[0], a[1], b[0], b[1]); triangle(x + reso * 0.5, y + reso * 0.5, a[0], a[1], b[0], b[1]);
break; break;
case 11: case 11:
fill(cBlue); fill(cBlue);
triangle(x + reso*0.5, y + reso*0.5, a[0], a[1], b[0], b[1]); triangle(x + reso * 0.5, y + reso * 0.5, a[0], a[1], b[0], b[1]);
break; break;
case 5: case 5:
fill(cBlue); fill(cBlue);
triangle(x + reso*0.5, y + reso*0.5, a[0], a[1], d[0], d[1]); triangle(x + reso * 0.5, y + reso * 0.5, a[0], a[1], d[0], d[1]);
triangle(x + reso*0.5, y + reso*0.5, b[0], b[1], c[0], c[1]); triangle(x + reso * 0.5, y + reso * 0.5, b[0], b[1], c[0], c[1]);
break; break;
case 6: case 6:
fill(cBlue); fill(cBlue);
rect(a[0], a[1], reso*0.5, reso); rect(a[0], a[1], reso * 0.5, reso);
break; break;
case 9: case 9:
fill(cGreen); fill(cGreen);
rect(a[0], a[1], reso*0.5, reso); rect(a[0], a[1], reso * 0.5, reso);
break; break;
case 7: case 7:
fill(cBlue); fill(cBlue);
triangle(x + reso*0.5, y + reso*0.5, a[0], a[1], d[0], d[1]); triangle(x + reso * 0.5, y + reso * 0.5, a[0], a[1], d[0], d[1]);
break; break;
case 8: case 8:
fill(cGreen); fill(cGreen);
triangle(x + reso*0.5, y + reso*0.5, a[0], a[1], d[0], d[1]); triangle(x + reso * 0.5, y + reso * 0.5, a[0], a[1], d[0], d[1]);
break; break;
case 10: case 10:
fill(cBlue); fill(cBlue);
triangle(x + reso*0.5, y + reso*0.5, a[0], a[1], b[0], b[1]); triangle(x + reso * 0.5, y + reso * 0.5, a[0], a[1], b[0], b[1]);
triangle(x + reso*0.5, y + reso*0.5, c[0], c[1], d[0], d[1]); triangle(x + reso * 0.5, y + reso * 0.5, c[0], c[1], d[0], d[1]);
break; break;
default: default:
break; break;
}; };
if (draw_lines) { drawLines(s, a, b, c, d); } if (draw_lines) {drawLines(s, a, b, c, d);}
} }
} }
function getState(a,b,c,d){ function getState(a, b, c, d) {
return d * 1 + c * 2 + b * 4 + a * 8; return d * 1 + c * 2 + b * 4 + a * 8;
} }
function drawLines(s, a, b, c, d){ function drawLines(s, a, b, c, d) {
stroke(232,229,55); stroke(232, 229, 55);
strokeWeight(reso * 0.1); strokeWeight(reso * 0.1);
switch(s) { switch (s) {
case 1: case 14: case 1: case 14:
line(c[0], c[1], d[0], d[1]); line(c[0], c[1], d[0], d[1]);
break; break;
@@ -157,17 +207,18 @@
noStroke(); noStroke();
} }
function mousePressed(){ function mousePressed() {
if (mouseButton == LEFT){ if (mouseButton == LEFT) {
var x = Math.floor((mouseX + 0.5*reso) / reso); var x = Math.floor((mouseX + 0.5 * reso) / reso);
var y = Math.floor((mouseY + 0.5*reso) / reso); var y = Math.floor((mouseY + 0.5 * reso) / reso);
var i = Math.floor(y * cols + x); var i = Math.floor(y * cols + x);
field[i] = (field[i] + 1) % 2; field[i] = (field[i] + 1) % 2;
} else if (mouseButton == RIGHT){ } else if (mouseButton == RIGHT) {
draw_lines = !draw_lines; draw_lines = !draw_lines;
} }
} }
</script> </script>
</body>
</html> </html>

View File

@@ -1,110 +0,0 @@
<?php
if($_SERVER['HTTP_X_FORWARDED_PROTO'] !== 'https') {
header('Location: https://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI']);
die();
}
?>
<DOCTYPE! html>
<html>
<script src="https://cdn.jsdelivr.net/npm/p5@1.4.0/lib/p5.min.js"></script>
<script>
var r = 10; //circle size
var k = 30;
var grid = [];
var w = r / Math.sqrt(2);
var active = [];
var cols, rows;
var ordered = [];
function setup() {
createCanvas(900, 900);
background(0);
strokeWeight(4);
colorMode(HSB);
cols = floor(width / w);
rows = floor(height / w);
for (var i = 0; i < cols * rows; i++) {
grid[i] = undefined;
}
var x = width / 2;
var y = height / 2;
var i = floor(x / w);
var j = floor(y / w);
var pos = createVector(x, y);
grid[i + j * cols] = pos;
active.push(pos);
}
function draw() {
background(0);
for (var total = 0; total < 30; total++) {
if (active.length > 0) {
var randIndex = floor(random(active.length));
var pos = active[randIndex];
var found = false;
for (var n = 0; n < k; n++) {
var sample = p5.Vector.random2D();
var m = random(r, 2 * r);
sample.setMag(m);
sample.add(pos);
var col = floor(sample.x / w);
var row = floor(sample.y / w);
if (col > -1 && row > -1 && col < cols && row < rows && !grid[col + row * cols]) {
var flag = true;
for (var i = -1; i <= 1; i++) {
for (var j = -1; j <= 1; j++) {
var index = (col + i) + (row + j) * cols;
var neighbor = grid[index];
if (neighbor) {
var d = p5.Vector.dist(sample, neighbor);
if (d < r) {
flag = false;
}
}
}
}
if (flag) {
found = true;
grid[col + row * cols] = sample;
active.push(sample);
ordered.push(sample);
//break;
}
}
}
if (!found) {
active.splice(randIndex, 1);
}
}
}
for (var i = 0; i < ordered.length; i++) {
stroke(255, 0, 255);
strokeWeight(r * 0.5);
point(ordered[i].x, ordered[i].y);
}
for (var i = 0; i < active.length; i++) {
if (ordered[i]) {
stroke(i % 360, 100, 100);
strokeWeight(r * 0.5);
point(active[i].x, active[i].y);
}
}
}
</script>
</html>

View File

@@ -0,0 +1,104 @@
<!DOCTYPE html>
<html>
<script src="https://cdn.jsdelivr.net/npm/p5@1.4.0/lib/p5.min.js"></script>
<script>
var r = 10; //circle size
var k = 30;
var grid = [];
var w = r / Math.sqrt(2);
var active = [];
var cols, rows;
var ordered = [];
function setup() {
createCanvas(900, 900);
background(0);
strokeWeight(4);
colorMode(HSB);
cols = floor(width / w);
rows = floor(height / w);
for (var i = 0; i < cols * rows; i++) {
grid[i] = undefined;
}
var x = width / 2;
var y = height / 2;
var i = floor(x / w);
var j = floor(y / w);
var pos = createVector(x, y);
grid[i + j * cols] = pos;
active.push(pos);
}
function draw() {
background(0);
for (var total = 0; total < 30; total++) {
if (active.length > 0) {
var randIndex = floor(random(active.length));
var pos = active[randIndex];
var found = false;
for (var n = 0; n < k; n++) {
var sample = p5.Vector.random2D();
var m = random(r, 2 * r);
sample.setMag(m);
sample.add(pos);
var col = floor(sample.x / w);
var row = floor(sample.y / w);
if (col > -1 && row > -1 && col < cols && row < rows && !grid[col + row * cols]) {
var flag = true;
for (var i = -1; i <= 1; i++) {
for (var j = -1; j <= 1; j++) {
var index = (col + i) + (row + j) * cols;
var neighbor = grid[index];
if (neighbor) {
var d = p5.Vector.dist(sample, neighbor);
if (d < r) {
flag = false;
}
}
}
}
if (flag) {
found = true;
grid[col + row * cols] = sample;
active.push(sample);
ordered.push(sample);
//break;
}
}
}
if (!found) {
active.splice(randIndex, 1);
}
}
}
for (var i = 0; i < ordered.length; i++) {
stroke(255, 0, 255);
strokeWeight(r * 0.5);
point(ordered[i].x, ordered[i].y);
}
for (var i = 0; i < active.length; i++) {
if (ordered[i]) {
stroke(i % 360, 100, 100);
strokeWeight(r * 0.5);
point(active[i].x, active[i].y);
}
}
}
</script>
</html>

View File

@@ -1,69 +0,0 @@
<!DOCTYPE html>
<html>
<script src="https://cdn.jsdelivr.net/npm/p5@1.4.0/lib/p5.min.js"></script>
<script>
var values = [];
let i = 0;
let j = 0;
function setup() {
createCanvas(windowWidth -20, windowHeight-20);
stroke(255);
background(0);
for (let i = 0; i < width; i++) {
values[i] = random(height);
line(i, height, i, height - values[i]);
}
}
function draw() {
stroke(243);
background(21);
for (let i = 0; i < width; i++) {
line(i, height, i, height - values[i]);
}
for (let n = 0; n < 50; n++) {
if (values[j] > values[j + 1]) {
tmp = values[j]
values[j] = values[j + 1];
values[j + 1] = tmp;
}
if (i < values.length) {
j += 1;
if (j >= values.length) {
j = 0;
i += 1;
}
} else {
stroke(0, 255, 0);
for (let i = 0; i < width; i++) {
line(i, height, i, height - values[i]);
}
noLoop();
}
}
}
function bSort() {
let tmp;
for (let i = 0; i < values.length; i++) {
for (let j = 0; j < values.length - i - 1; j++) {
if (values[j] > values[j + 1]) {
tmp = values[j]
values[j] = values[j + 1];
values[j + 1] = tmp;
}
}
}
}
</script>
</html>

View File

@@ -1,133 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0>
<script src="https://cdn.jsdelivr.net/npm/p5@1.4.0/lib/p5.min.js"></script>
<style>
body {
padding: 0;
margin: 0;
}
.slidecontainer {
width: 100%;
/* Width of the outside container */
}
/* The slider itself */
.slider {
-webkit-appearance: none;
/* Override default CSS styles */
appearance: none;
width: 100%;
/* Full-width */
height: 25px;
/* Specified height */
background: #d3d3d3;
/* Grey background */
outline: none;
/* Remove outline */
opacity: 1;
/* Set transparency (for mouse-over effects on hover) */
-webkit-transition: .2s;
/* 0.2 seconds transition on hover */
transition: opacity .2s;
}
.slider::-webkit-slider-thumb {
-webkit-appearance: none;
/* Override default look */
appearance: none;
width: 25px;
/* Set a specific slider handle width */
height: 25px;
/* Slider handle height */
background: #434343;
/* Grey background */
cursor: pointer;
/* Cursor on hover */
}
.slider::-moz-range-thumb {
width: 25px;
/* Set a specific slider handle width */
height: 25px;
/* Slider handle height */
background: #434343;
/* Grey background */
cursor: pointer;
/* Cursor on hover */
}
</style>
</head>
<div class="slidecontainer">
<input type="range" min="2" max="11" step="1" value="2" class="slider" id="myRange">
</div>
<script>
let vMargin, hMargin, arrowHeight, t, lineNum;
let lineMove = true;
function setup() {
createCanvas(windowWidth, windowHeight * 0.6);
hMargin = 12;
arrowHeight = 25;
t = 0;
lineNum = 1;
}
function windowResized() {
resizeCanvas(windowWidth, windowHeight * 0.6);
}
function draw() {
background(43);
angleMode(DEGREES);
lineNum = document.getElementById('myRange').value;
drawLine(hMargin, lineNum + 1);
if (lineMove) {
t++;
}
if (t == 360) {
t = 0;
}
}
function drawLine(hm, vm) {
//let changex = map(sin(t), -1, 1, -22, 22);
let changex = sin(t) * 18;
vm /= 10;
for (let j = 1; j < vm - 1; j++) {
stroke(255, 34, 63);
strokeWeight(4);
line(width / hm, j * height / vm, width / 2, j * height / vm); //red line
stroke(69, 98, 255);
line(width / 2, j * height / vm, (hm - 1) * width / hm, j * height / vm); //blue line
stroke(255);
line(width / hm, j * height / vm, width / hm + changex, (j * height / vm) - arrowHeight); //left top
line(width / hm + changex, (j * height / vm) + arrowHeight, width / hm, j * height / vm); //left bottom
line((hm - 1) * width / hm + changex, j * height / vm + arrowHeight, (hm - 1) * width / hm, j * height / vm); //right bottom
line(width / 2 - changex, j * height / vm + arrowHeight, width / 2, j * height / vm); //center bottom
line((hm - 1) * width / hm, j * height / vm, (hm - 1) * width / hm + changex, (j * height / vm) - arrowHeight); //right bottom
line(width / 2, j * height / vm, width / 2 - changex, (j * height / vm) - arrowHeight); //center top
}
}
function mouseClicked() {
lineMove = !lineMove;
}
</script>
</html>

166
projects/warping_lines.html Executable file
View File

@@ -0,0 +1,166 @@
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0>
<script src="https://cdn.jsdelivr.net/npm/p5@1.4.0/lib/p5.min.js"></script>
<style>
body {
padding: 0;
margin: 0;
font-family: system-ui, -apple-system, Segoe UI, Roboto, Helvetica, Arial, sans-serif;
background: #fafafa;
}
.intro {
max-width: 900px;
margin: 20px auto 10px;
padding: 0 16px;
}
.intro h1 {
margin: 0 0 6px;
font-size: 1.5rem;
}
.intro p {
margin: 4px 0 14px;
line-height: 1.45;
}
.slidecontainer {
width: 100%;
/* Width of the outside container */
}
/* The slider itself */
.slider {
-webkit-appearance: none;
/* Override default CSS styles */
appearance: none;
width: 100%;
/* Full-width */
height: 25px;
/* Specified height */
background: #d3d3d3;
/* Grey background */
outline: none;
/* Remove outline */
opacity: 1;
/* Set transparency (for mouse-over effects on hover) */
-webkit-transition: .2s;
/* 0.2 seconds transition on hover */
transition: opacity .2s;
}
.slider::-webkit-slider-thumb {
-webkit-appearance: none;
/* Override default look */
appearance: none;
width: 25px;
/* Set a specific slider handle width */
height: 25px;
/* Slider handle height */
background: #434343;
/* Grey background */
cursor: pointer;
/* Cursor on hover */
}
.slider::-moz-range-thumb {
width: 25px;
/* Set a specific slider handle width */
height: 25px;
/* Slider handle height */
background: #434343;
/* Grey background */
cursor: pointer;
/* Cursor on hover */
}
</style>
</head>
<body>
<div class="intro">
<h1>Oscillating Arrow Field Visualizer</h1>
<p>
A sketch to <s>hopefully</s> demonstrate the illusion of the <a
href="https://en.wikipedia.org/wiki/M%C3%BCller-Lyer_illusion">Müller-Lyer Illusion</a>
</p>
<p>The lines - that are the same length, should look longer and shorter based on the angle of the arrow heads.
</p>
<p>
Increasing the value adds more horizontal slices, creating a denser and more detailed pattern.
Tap or click to pause and resume the motion.
</p>
</div>
<div class="slidecontainer">
<input type="range" min="2" max="11" step="1" value="2" class="slider" id="myRange">
</div>
<script>
let vMargin, hMargin, arrowHeight, t, lineNum;
let lineMove = true;
function setup() {
createCanvas(windowWidth, windowHeight * 0.6);
hMargin = 12;
arrowHeight = 25;
t = 0;
lineNum = 1;
}
function windowResized() {
resizeCanvas(windowWidth, windowHeight * 0.6);
}
function draw() {
background(43);
angleMode(DEGREES);
lineNum = document.getElementById('myRange').value;
drawLine(hMargin, lineNum + 1);
if (lineMove) {
t++;
}
if (t == 360) {
t = 0;
}
}
function drawLine(hm, vm) {
//let changex = map(sin(t), -1, 1, -22, 22);
let changex = sin(t) * 18;
vm /= 10;
for (let j = 1; j < vm - 1; j++) {
stroke(255, 34, 63);
strokeWeight(4);
line(width / hm, j * height / vm, width / 2, j * height / vm); //red line
stroke(69, 98, 255);
line(width / 2, j * height / vm, (hm - 1) * width / hm, j * height / vm); //blue line
stroke(255);
line(width / hm, j * height / vm, width / hm + changex, (j * height / vm) - arrowHeight); //left top
line(width / hm + changex, (j * height / vm) + arrowHeight, width / hm, j * height / vm); //left bottom
line((hm - 1) * width / hm + changex, j * height / vm + arrowHeight, (hm - 1) * width / hm, j * height / vm); //right bottom
line(width / 2 - changex, j * height / vm + arrowHeight, width / 2, j * height / vm); //center bottom
line((hm - 1) * width / hm, j * height / vm, (hm - 1) * width / hm + changex, (j * height / vm) - arrowHeight); //right bottom
line(width / 2, j * height / vm, width / 2 - changex, (j * height / vm) - arrowHeight); //center top
}
}
function mouseClicked() {
lineMove = !lineMove;
}
</script>
</body>
</html>