Commit e69ee71d authored by Starbeamrainbowlabs's avatar Starbeamrainbowlabs
Browse files

Initial commit.

parents
# Created by https://www.gitignore.io/api/git
### Git ###
*.orig
# End of https://www.gitignore.io/api/git
"use strict";
/*****************************************************************************
******************************** Mouse class ********************************
********************************************************************* v0.1 **
* A simple mouse class, records and stores mouse information later use
* outside an event listener. Depends on my earlier Vector class.
*
* Author: Starbeamrainbowlabs
* Twitter: @SBRLabs
* Email: feedback at starbeamrainbowlabs dot com
*
* From https://gist.github.com/sbrl/06db619f2a1f75305fbd54f66402459b
*****************************************************************************
* Originally written for the Nibriboard client.
*****************************************************************************
* Changelog
*****************************************************************************
* v0.1 - 28th March 2017
* Initial release.
* v0.2 - 7th October 2017
* Fixed typo in pressure
*/
//import Vector from './Vector.js';
/**
* A reference for the different mouse button types.
* @type {Object}
*/
var MouseButtons = {
/**
* The left mouse button.
* @type {Number}
*/
Left: 0,
/**
* The right mouse button.
* @type {Number}
*/
Right: 2,
/**
* The middle mouse button.
* @type {Number}
*/
Middle: 1
};
class Mouse
{
constructor()
{
/**
* Whether the left mouse button is down or not.
* @type {boolean}
*/
this.leftDown = false;
/**
* Whether the right mouse button is down or not.
* @type {boolean}
*/
this.rightDown = false;
/**
* Whether the middle mouse button is down or not.
* @type {boolean}
*/
this.middleDown = false;
/**
* The last known position of the mouse in document-space.
* @type {Vector}
*/
this.position = new Vector(0, 0);
// Register the required event listeners
document.addEventListener("mouseup", this.handleMouseUp.bind(this));
document.addEventListener("mousedown", this.handleMouseDown.bind(this));
document.addEventListener("mousemove", this.handleMouseMove.bind(this));
}
handleMouseUp(event)
{
switch(event.button)
{
case MouseButtons.Left:
this.leftDown = false;
break;
case MouseButtons.Right:
this.rightDown = false;
break;
case MouseButtons.Middle:
this.middleDown = false;
break;
default:
console.warn(`Unknown mouse up button type ${even.button}`);
break;
}
}
handleMouseDown(event)
{
switch(event.button)
{
case MouseButtons.Left:
this.leftDown = true;
break;
case MouseButtons.Right:
this.rightDown = true;
break;
case MouseButtons.Middle:
this.middleDown = true;
break;
default:
console.warn(`Unknown mouse down button type ${even.button}`);
break;
}
}
handleMouseMove(event)
{
this.position.x = event.clientX;
this.position.y = event.clientY;
this.pressur = typeof event.pressure === "number" ? event.pressure : event.mozPressure;
}
}
//export { Mouse, MouseButtons };
//export default Mouse;
"use strict";
/******************************************************
************** Simple ES6 Vector Class **************
******************************************************
* Author: Starbeamrainbowlabs
* Twitter: @SBRLabs
* Email: feedback at starbeamrainbowlabs dot com
*
* From https://gist.github.com/sbrl/69a8fa588865cacef9c0
******************************************************
* Originally written for my 2D Graphics ACW at Hull
* University.
******************************************************
* Changelog
******************************************************
* 19th December 2015:
* Added this changelog.
* 28th December 2015:
* Rewrite tests with klud.js + Node.js
* 30th January 2016:
* Tweak angleFrom function to make it work properly.
* 31st January 2016:
* Add the moveTowards function.
* Add the minComponent getter.
* Add the maxComponent getter.
* Add the equalTo function.
* Tests still need to be written for all of the above.
* 19th September 2016:
* Added Vector support to the multiply method.
*/
class Vector {
// Constructor
constructor(inX, inY) {
if(typeof inX != "number")
throw new Error("Invalid x value.");
if(typeof inY != "number")
throw new Error("Invalid y value.");
// Store the (x, y) coordinates
this.x = inX;
this.y = inY;
}
/**
* Add another vector to this vector.
* @param {Vector} v The vector to add.
* @return {Vector} The current vector. useful for daisy-chaining calls.
*/
add(v) {
this.x += v.x;
this.y += v.y;
return this;
}
/**
* Take another vector from this vector.
* @param {Vector} v The vector to subtrace from this one.
* @return {Vector} The current vector. useful for daisy-chaining calls.
*/
subtract(v) {
this.x -= v.x;
this.y -= v.y;
return this;
}
/**
* Divide the current vector by a given value.
* @param {number} value The value to divide by.
* @return {Vector} The current vector. Useful for daisy-chaining calls.
*/
divide(value) {
if(typeof value != "number")
throw new Error("Can't divide by non-number value.");
this.x /= value;
this.y /= value;
return this;
}
/**
* Multiply the current vector by a given value.
* @param {(number|Vector)} value The number (or Vector) to multiply the current vector by.
* @return {Vector} The current vector. useful for daisy-chaining calls.
*/
multiply(value) {
if(value instanceof Vector)
{
this.x *= value.x;
this.y *= value.y;
}
else if(typeof value == "number")
{
this.x *= value;
this.y *= value;
}
else
throw new Error("Can't multiply by non-number value.");
return this;
}
/**
* Move the vector towards the given vector by the given amount.
* @param {Vector} v The vector to move towards.
* @param {number} amount The distance to move towards the given vector.
*/
moveTowards(v, amount)
{
// From http://stackoverflow.com/a/2625107/1460422
var dir = new Vector(
v.x - this.x,
v.y - this.y
).limitTo(amount);
this.x += dir.x;
this.y += dir.y;
return this;
}
/**
* Limit the length of the current vector to value without changing the
* direction in which the vector is pointing.
* @param {number} value The number to limit the current vector's length to.
* @return {Vector} The current vector. useful for daisy-chaining calls.
*/
limitTo(value) {
if(typeof value != "number")
throw new Error("Can't limit to non-number value.");
this.divide(this.length);
this.multiply(value);
return this;
}
/**
* Return the dot product of the current vector and another vector.
* @param {Vector} v The other vector we should calculate the dot product with.
* @return {Vector} The current vector. useful for daisy-chaining calls.
*/
dotProduct(v) {
return (this.x * v.x) + (this.y * v.y);
}
/**
* Calculate the angle, in radians, from north to another vector.
* @param {Vector} v The other vector to which to calculate the angle.
* @return {Vector} The current vector. useful for daisy-chaining calls.
*/
angleFrom(v) {
// From http://stackoverflow.com/a/16340752/1460422
var angle = Math.atan2(v.y - this.y, v.x - this.x) - (Math.PI / 2);
angle += Math.PI/2;
if(angle < 0) angle += Math.PI * 2;
return angle;
}
/**
* Clones the current vector.
* @return {Vector} A clone of the current vector. Very useful for passing around copies of a vector if you don't want the original to be altered.
*/
clone() {
return new Vector(this.x, this.y);
}
/*
* Returns a representation of the current vector as a string.
* @returns {string} A representation of the current vector as a string.
*/
toString() {
return `(${this.x}, ${this.y})`;
}
/**
* Whether the vector is equal to another vector.
* @param {Vector} v The vector to compare to.
* @return {boolean} Whether the current vector is equal to the given vector.
*/
equalTo(v)
{
if(this.x == v.x && this.y == v.y)
return true;
else
return false;
}
/**
* Get the unit vector of the current vector - that is a vector poiting in the same direction with a length of 1. Note that this does *not* alter the original vector.
* @return {Vector} The current vector's unit form.
*/
get unitVector() {
var length = this.length;
return new Vector(
this.x / length,
this.y / length);
}
/**
* Get the length of the current vector.
* @return {number} The length of the current vector.
*/
get length() {
return Math.sqrt((this.x * this.x) + (this.y * this.y));
}
/**
* Get the value of the minimum component of the vector.
* @return {number} The minimum component of the vector.
*/
get minComponent() {
return Math.min(this.x, this.y);
}
/**
* Get the value of the maximum component of the vector.
* @return {number} The maximum component of the vector.
*/
get maxComponent() {
return Math.min(this.x, this.y);
}
}
//export default Vector;
:root
{
--canvas-background-style: hsl(271, 61%, 74%);
--debug-border-style: 2px dashed hsl(247, 93%, 69%);
--debug-background-style: hsla(221, 77%, 39%, 0.4);
--debug-value-background-style: hsl(355, 54%, 52%);
}
html, body { font-size: 100%; }
body
{
font-family: sans-serif;
overflow: hidden;
}
#canvas-main
{
position: absolute;
top: 0; right: 0; bottom: 0; left: 0;
background: var(--canvas-background-style);
z-index: 500;
}
.debug-data
{
position: absolute;
top: 0; right: 0;
padding: 1em;
background: var(--debug-background-style);
border-left: var(--debug-border-style);
border-bottom: var(--debug-border-style);
z-index: 1000;
}
.debug-data > ul
{
list-style-type: none;
margin: 0;
padding: 0;
}
.debug-data output
{
padding: 0.25em 0.45em;
background: var(--debug-value-background-style);
border-radius: 0.2em;
}
<!DOCTYPE html>
<html>
<head>
<meta charset='utf-8' />
<title>Ramer Douglas Peucker Demo</title>
</head>
<body>
<canvas id="canvas-main"></canvas>
<div class="debug-data">
<ul>
<li>Points: <output id="output-point-count"></output></li>
</ul>
</div>
<!---------------->
<link rel="stylesheet" href="demo.css" />
<script src="demo.js" charset="utf-8"></script>
<script src="Vector.js" charset="utf-8"></script>
<script src="Mouse.js" charset="utf-8"></script>
<script src="ramer-douglas-peucker.js" charset="utf-8"></script>
</head>
</html>
"use strict";
class RDPDemo
{
constructor()
{
this.canvas = document.getElementById("canvas-main");
this.context = this.canvas.getContext("2d");
this.mouse = new Mouse();
this.lineWidth = 2;
this.lineColour = "hsl(232, 55%, 58%)";
this.crossSize = 5;
this.crossLineWidth = 2;
this.crossColour = "hsl(240, 54%, 44%)";
// ---------------------------
this.canvas.addEventListener("mousedown", this.handleMouseDown.bind(this));
this.canvas.addEventListener("mousemove", this.handleMouseMove.bind(this));
// ---------------------------
this.points = [];
this.matchWindowSize();
}
trackWindowSize()
{
document.addEventListener("resize", this.matchWindowSize.bind(this));
}
matchWindowSize()
{
this.canvas.width = window.innerWidth;
this.canvas.height = window.innerHeight;
}
handleMouseDown(event)
{
this.points.length = 0;
}
handleMouseMove(event)
{
if(!this.mouse.leftDown)
return;
this.points.push(new Vector(event.clientX, event.clientY));
}
nextFrame()
{
this.update();
this.render(this.canvas, this.context);
requestAnimationFrame(this.nextFrame.bind(this));
}
update()
{
document.getElementById("output-point-count").innerHTML = this.points.length;
}
render(canvas, context)
{
if(this.points.length == 0)
return;
// Clear the screen
canvas.width = canvas.width;
// Draw the points
context.beginPath();
context.moveTo(this.points[0], this.points[0]);
for (let point of this.points) {
context.lineTo(point.x, point.y);
}
context.lineWidth = this.lineWidth;
context.strokeStyle = this.lineColour;
context.stroke();
// Draw crosses at all the points
context.beginPath();
for (let point of this.points) {
context.moveTo(point.x - this.crossSize, point.y - this.crossSize);
context.lineTo(point.x + this.crossSize, point.y + this.crossSize);
context.moveTo(point.x + this.crossSize, point.y - this.crossSize);
context.lineTo(point.x - this.crossSize, point.y + this.crossSize);
}
context.lineWidth = this.crossLineWidth;
context.strokeStyle = this.crossColour;
context.stroke();
}
}
window.addEventListener("load", function(event) {
this.rdpDemo = new RDPDemo();
this.rdpDemo.nextFrame();
});
"use strict";
//import Vector from './Vector';
/**
* Simplifies a set of input poitns with the ramer-douglas-peucker algorithm.
* @param {Vector[]} points The list of points to simplify.
* @param {number} euler The amount of simplification to perform.
* @return {Vector[]} The simplfied line.
*/
function simplify_line(points, euler)
{
let first_point = this.points[0],
last_point = this.points[this.points.length - 1];
let farthest_index = 0, farthest_distance = 0;
for (let i = 1; i < points.length - 1; i++) {
let next_distance = sq_distance_from_line(first_point, last_point, this.points[i]);
// todo: set the farthest_* variables and then recurse
}
}
/**
* Calculates the squared shortest distance between a point and the specified line.
* @param {Vector} line_start The point at which the line starts.
* @param {Vector} line_end The point at which the line ends.
* @param {Vector} point The point to calculate the distance for.
* @return {number} The shortest distance between the specified point
* and the specified line.
*/
function sq_distance_from_line(line_start, line_end, point)
{
let main_line_length = line_end.clone().subtract(line_start).length;
let direct_line_length = line_end.clone().subtract(point).length;
return ((main_line_length/2)*(main_line_length/2)) - (direct_line_length*direct_line_length);
}
//export { simplify_line };
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment