Commit 3851d492 authored by Starbeamrainbowlabs's avatar Starbeamrainbowlabs
Browse files

Initial algorithm implementation

parent 1b98d4f4
......@@ -20,6 +20,8 @@ body
position: absolute;
top: 0; right: 0; bottom: 0; left: 0;
cursor: crosshair;
background: var(--canvas-background-style);
z-index: 500;
......
......@@ -17,8 +17,8 @@
<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="lib/Vector.js" charset="utf-8"></script>
<script src="lib/Mouse.js" charset="utf-8"></script>
<script src="ramer-douglas-peucker.js" charset="utf-8"></script>
</head>
</html>
......@@ -9,12 +9,22 @@ class RDPDemo
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.rawLine = {
width: 2,
colour: "hsl(232, 55%, 58%)",
crossSize: 3,
crossLineWidth: 1,
crossColour: "hsl(240, 54%, 44%)"
};
this.simpleLine = {
width: 2,
colour: "hsl(107, 56%, 53%)",
crossSize: 3,
crossLineWidth: 1,
crossColour: "hsl(66, 49%, 47%)"
};
// ---------------------------
......@@ -24,6 +34,9 @@ class RDPDemo
// ---------------------------
this.points = [];
this.simplePoints = [];
this.epsilon = 2;
this.matchWindowSize();
}
......@@ -62,6 +75,9 @@ class RDPDemo
update()
{
this.simplePoints = simplify_line(this.points, this.epsilon)
// Update the interface
document.getElementById("output-point-count").innerHTML = this.points.length;
}
......@@ -73,6 +89,11 @@ class RDPDemo
// Clear the screen
canvas.width = canvas.width;
this.draw_line(canvas, context, this.points, this.rawLine);
this.draw_line(canvas, context, this.simplePoints, this.simpleLine)
}
draw_line(canvas, context, points, settings) {
// Draw the points
context.beginPath();
context.moveTo(this.points[0], this.points[0]);
......@@ -80,22 +101,22 @@ class RDPDemo
context.lineTo(point.x, point.y);
}
context.lineWidth = this.lineWidth;
context.strokeStyle = this.lineColour;
context.lineWidth = settings.width;
context.strokeStyle = settings.colour;
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 - settings.crossSize, point.y - settings.crossSize);
context.lineTo(point.x + settings.crossSize, point.y + settings.crossSize);
context.moveTo(point.x + this.crossSize, point.y - this.crossSize);
context.lineTo(point.x - this.crossSize, point.y + this.crossSize);
context.moveTo(point.x + settings.crossSize, point.y - settings.crossSize);
context.lineTo(point.x - settings.crossSize, point.y + settings.crossSize);
}
context.lineWidth = this.crossLineWidth;
context.strokeStyle = this.crossColour;
context.lineWidth = settings.crossLineWidth;
context.strokeStyle = settings.crossColour;
context.stroke();
}
}
......
"use strict";
window.EventEmitter = require("event-emitter-es6");
window.keycode = require("keycode");
/**
* Makes handling keyboard input just that little bit easier.
*/
class Keyboard extends EventEmitter
{
constructor()
{
super();
/**
* The keyCodes of the keyboard keys that are currently pressed down.
* @type {[number]}
*/
this.DownKeys = [];
document.addEventListener("keydown", this.handleKeyDown.bind(this));
document.addEventListener("keyup", this.handleKeyUp.bind(this));
}
/**
* Handles keydown events.
* @param {KeyboardEvent} event The keyboard event to handle.
*/
handleKeyDown(event) {
if(!this.DownKeys.includes(event.keyCode))
this.DownKeys.push(event.keyCode);
console.log("DownKeys:", this.DownKeys);
console.debug("[keyboard] Emitting key down event", `keydown-${keycode(event.keyCode)}`);
this.emit(`keydown-${keycode(event.keyCode)}`, event);
}
/**
* Handles keyup events.
* @param {KeyboardEvent} event The keyboard event to handle.
*/
handleKeyUp(event) {
if(this.DownKeys.indexOf(event.keyCode) !== -1)
this.DownKeys.splice(this.DownKeys.indexOf(event.keyCode), 1);
console.log("DownKeys:", this.DownKeys);
console.debug("[keyboard] Emitting key up event", `keyup-${keycode(event.keyCode)}`);
this.emit(`keyup-${keycode(event.keyCode)}`, event);
}
}
export default Keyboard;
{
"presets": [
"stage-0",
"es2015"
]
}
.idea/
node_modules/
\ No newline at end of file
(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.EventEmitter = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
'use strict';
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
var DEFAULT_VALUES = {
emitDelay: 10,
strictMode: false
};
/**
* @typedef {object} EventEmitterListenerFunc
* @property {boolean} once
* @property {function} fn
*/
/**
* @class EventEmitter
*
* @private
* @property {Object.<string, EventEmitterListenerFunc[]>} _listeners
* @property {string[]} events
*/
var EventEmitter = function () {
/**
* @constructor
* @param {{}} [opts]
* @param {number} [opts.emitDelay = 10] - Number in ms. Specifies whether emit will be sync or async. By default - 10ms. If 0 - fires sync
* @param {boolean} [opts.strictMode = false] - is true, Emitter throws error on emit error with no listeners
*/
function EventEmitter() {
var opts = arguments.length <= 0 || arguments[0] === undefined ? DEFAULT_VALUES : arguments[0];
_classCallCheck(this, EventEmitter);
var emitDelay = void 0,
strictMode = void 0;
if (opts.hasOwnProperty('emitDelay')) {
emitDelay = opts.emitDelay;
} else {
emitDelay = DEFAULT_VALUES.emitDelay;
}
this._emitDelay = emitDelay;
if (opts.hasOwnProperty('strictMode')) {
strictMode = opts.strictMode;
} else {
strictMode = DEFAULT_VALUES.strictMode;
}
this._strictMode = strictMode;
this._listeners = {};
this.events = [];
}
/**
* @protected
* @param {string} type
* @param {function} listener
* @param {boolean} [once = false]
*/
_createClass(EventEmitter, [{
key: '_addListenner',
value: function _addListenner(type, listener, once) {
if (typeof listener !== 'function') {
throw TypeError('listener must be a function');
}
if (this.events.indexOf(type) === -1) {
this._listeners[type] = [{
once: once,
fn: listener
}];
this.events.push(type);
} else {
this._listeners[type].push({
once: once,
fn: listener
});
}
}
/**
* Subscribes on event type specified function
* @param {string} type
* @param {function} listener
*/
}, {
key: 'on',
value: function on(type, listener) {
this._addListenner(type, listener, false);
}
/**
* Subscribes on event type specified function to fire only once
* @param {string} type
* @param {function} listener
*/
}, {
key: 'once',
value: function once(type, listener) {
this._addListenner(type, listener, true);
}
/**
* Removes event with specified type. If specified listenerFunc - deletes only one listener of specified type
* @param {string} eventType
* @param {function} [listenerFunc]
*/
}, {
key: 'off',
value: function off(eventType, listenerFunc) {
var _this = this;
var typeIndex = this.events.indexOf(eventType);
var hasType = eventType && typeIndex !== -1;
if (hasType) {
if (!listenerFunc) {
delete this._listeners[eventType];
this.events.splice(typeIndex, 1);
} else {
(function () {
var removedEvents = [];
var typeListeners = _this._listeners[eventType];
typeListeners.forEach(
/**
* @param {EventEmitterListenerFunc} fn
* @param {number} idx
*/
function (fn, idx) {
if (fn.fn === listenerFunc) {
removedEvents.unshift(idx);
}
});
removedEvents.forEach(function (idx) {
typeListeners.splice(idx, 1);
});
if (!typeListeners.length) {
_this.events.splice(typeIndex, 1);
delete _this._listeners[eventType];
}
})();
}
}
}
/**
* Applies arguments to specified event type
* @param {string} eventType
* @param {*[]} eventArguments
* @protected
*/
}, {
key: '_applyEvents',
value: function _applyEvents(eventType, eventArguments) {
var typeListeners = this._listeners[eventType];
if (!typeListeners || !typeListeners.length) {
if (this._strictMode) {
throw 'No listeners specified for event: ' + eventType;
} else {
return;
}
}
var removableListeners = [];
typeListeners.forEach(function (eeListener, idx) {
eeListener.fn.apply(null, eventArguments);
if (eeListener.once) {
removableListeners.unshift(idx);
}
});
removableListeners.forEach(function (idx) {
typeListeners.splice(idx, 1);
});
}
/**
* Emits event with specified type and params.
* @param {string} type
* @param eventArgs
*/
}, {
key: 'emit',
value: function emit(type) {
var _this2 = this;
for (var _len = arguments.length, eventArgs = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
eventArgs[_key - 1] = arguments[_key];
}
if (this._emitDelay) {
setTimeout(function () {
_this2._applyEvents.call(_this2, type, eventArgs);
}, this._emitDelay);
} else {
this._applyEvents(type, eventArgs);
}
}
/**
* Emits event with specified type and params synchronously.
* @param {string} type
* @param eventArgs
*/
}, {
key: 'emitSync',
value: function emitSync(type) {
for (var _len2 = arguments.length, eventArgs = Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) {
eventArgs[_key2 - 1] = arguments[_key2];
}
this._applyEvents(type, eventArgs);
}
/**
* Destroys EventEmitter
*/
}, {
key: 'destroy',
value: function destroy() {
this._listeners = {};
this.events = [];
}
}]);
return EventEmitter;
}();
module.exports = EventEmitter;
},{}]},{},[1])(1)
});
\ No newline at end of file
(function(e){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=e()}else if(typeof define==="function"&&define.amd){define([],e)}else{var t;if(typeof window!=="undefined"){t=window}else if(typeof global!=="undefined"){t=global}else if(typeof self!=="undefined"){t=self}else{t=this}t.EventEmitter=e()}})(function(){var e,t,n;return function i(e,t,n){function r(f,o){if(!t[f]){if(!e[f]){var l=typeof require=="function"&&require;if(!o&&l)return l(f,!0);if(s)return s(f,!0);var a=new Error("Cannot find module '"+f+"'");throw a.code="MODULE_NOT_FOUND",a}var u=t[f]={exports:{}};e[f][0].call(u.exports,function(t){var n=e[f][1][t];return r(n?n:t)},u,u.exports,i,e,t,n)}return t[f].exports}var s=typeof require=="function"&&require;for(var f=0;f<n.length;f++)r(n[f]);return r}({1:[function(e,t,n){"use strict";var i=function(){function e(e,t){for(var n=0;n<t.length;n++){var i=t[n];i.enumerable=i.enumerable||false;i.configurable=true;if("value"in i)i.writable=true;Object.defineProperty(e,i.key,i)}}return function(t,n,i){if(n)e(t.prototype,n);if(i)e(t,i);return t}}();function r(e,t){if(!(e instanceof t)){throw new TypeError("Cannot call a class as a function")}}var s={emitDelay:10,strictMode:false};var f=function(){function e(){var t=arguments.length<=0||arguments[0]===undefined?s:arguments[0];r(this,e);var n=void 0,i=void 0;if(t.hasOwnProperty("emitDelay")){n=t.emitDelay}else{n=s.emitDelay}this._emitDelay=n;if(t.hasOwnProperty("strictMode")){i=t.strictMode}else{i=s.strictMode}this._strictMode=i;this._listeners={};this.events=[]}i(e,[{key:"_addListenner",value:function t(e,n,i){if(typeof n!=="function"){throw TypeError("listener must be a function")}if(this.events.indexOf(e)===-1){this._listeners[e]=[{once:i,fn:n}];this.events.push(e)}else{this._listeners[e].push({once:i,fn:n})}}},{key:"on",value:function n(e,t){this._addListenner(e,t,false)}},{key:"once",value:function f(e,t){this._addListenner(e,t,true)}},{key:"off",value:function o(e,t){var n=this;var i=this.events.indexOf(e);var r=e&&i!==-1;if(r){if(!t){delete this._listeners[e];this.events.splice(i,1)}else{(function(){var r=[];var s=n._listeners[e];s.forEach(function(e,n){if(e.fn===t){r.unshift(n)}});r.forEach(function(e){s.splice(e,1)});if(!s.length){n.events.splice(i,1);delete n._listeners[e]}})()}}}},{key:"_applyEvents",value:function l(e,t){var n=this._listeners[e];if(!n||!n.length){if(this._strictMode){throw"No listeners specified for event: "+e}else{return}}var i=[];n.forEach(function(e,n){e.fn.apply(null,t);if(e.once){i.unshift(n)}});i.forEach(function(e){n.splice(e,1)})}},{key:"emit",value:function a(e){var t=this;for(var n=arguments.length,i=Array(n>1?n-1:0),r=1;r<n;r++){i[r-1]=arguments[r]}if(this._emitDelay){setTimeout(function(){t._applyEvents.call(t,e,i)},this._emitDelay)}else{this._applyEvents(e,i)}}},{key:"emitSync",value:function u(e){for(var t=arguments.length,n=Array(t>1?t-1:0),i=1;i<t;i++){n[i-1]=arguments[i]}this._applyEvents(e,n)}},{key:"destroy",value:function c(){this._listeners={};this.events=[]}}]);return e}();t.exports=f},{}]},{},[1])(1)});
\ No newline at end of file
const DEFAULT_VALUES = {
emitDelay: 10,
strictMode: false
};
/**
* @typedef {object} EventEmitterListenerFunc
* @property {boolean} once
* @property {function} fn
*/
/**
* @class EventEmitter
*
* @private
* @property {Object.<string, EventEmitterListenerFunc[]>} _listeners
* @property {string[]} events
*/
class EventEmitter {
/**
* @constructor
* @param {{}} [opts]
* @param {number} [opts.emitDelay = 10] - Number in ms. Specifies whether emit will be sync or async. By default - 10ms. If 0 - fires sync
* @param {boolean} [opts.strictMode = false] - is true, Emitter throws error on emit error with no listeners
*/
constructor(opts = DEFAULT_VALUES) {
let emitDelay, strictMode;
if (opts.hasOwnProperty('emitDelay')) {
emitDelay = opts.emitDelay;
} else {
emitDelay = DEFAULT_VALUES.emitDelay;
}
this._emitDelay = emitDelay;
if (opts.hasOwnProperty('strictMode')) {
strictMode = opts.strictMode;
} else {
strictMode = DEFAULT_VALUES.strictMode;
}
this._strictMode = strictMode;
this._listeners = {};
this.events = [];
}
/**
* @protected
* @param {string} type
* @param {function} listener
* @param {boolean} [once = false]
*/
_addListenner(type, listener, once) {
if (typeof listener !== 'function') {
throw TypeError('listener must be a function');
}
if (this.events.indexOf(type) === -1) {
this._listeners[type] = [{
once: once,
fn: listener
}];
this.events.push(type);
} else {
this._listeners[type].push({
once: once,
fn: listener
});
}
}
/**
* Subscribes on event type specified function
* @param {string} type
* @param {function} listener
*/
on(type, listener) {
this._addListenner(type, listener, false);
}
/**
* Subscribes on event type specified function to fire only once
* @param {string} type
* @param {function} listener
*/
once(type, listener) {
this._addListenner(type, listener, true);
}
/**
* Removes event with specified type. If specified listenerFunc - deletes only one listener of specified type
* @param {string} eventType
* @param {function} [listenerFunc]
*/
off(eventType, listenerFunc) {
let typeIndex = this.events.indexOf(eventType);
let hasType = eventType && typeIndex !== -1;
if (hasType) {
if (!listenerFunc) {
delete this._listeners[eventType];
this.events.splice(typeIndex, 1);
} else {
let removedEvents = [];
let typeListeners = this._listeners[eventType];
typeListeners.forEach(
/**
* @param {EventEmitterListenerFunc} fn
* @param {number} idx
*/
function (fn, idx) {
if (fn.fn === listenerFunc) {
removedEvents.unshift(idx);
}
}
);
removedEvents.forEach(function (idx) {
typeListeners.splice(idx,1);
});
if (!typeListeners.length) {
this.events.splice(typeIndex, 1);
delete this._listeners[eventType];
}
}
}
}
/**
* Applies arguments to specified event type