Lot of doc

This commit is contained in:
Thomas FORGIONE 2015-07-06 11:14:42 +02:00
parent c0eb2d26f5
commit f11b1ed7dc
15 changed files with 634 additions and 134 deletions

View File

@ -4,7 +4,6 @@ block title
title #{title} - Test
block extrajs
script(src='/static/js/List.min.js')
script(src='/static/js/ListTest.min.js')
block content

View File

@ -6,13 +6,14 @@ else
CLOSURE=../utils/simple-compiler/compiler.sh
endif
all: L3D L3DP Socket Three Stats Bouncing Multisphere StreamingSimulator PrototypeReplay PrototypeInteractive Tutorial
all: L3D L3DP Socket Three Stats Bouncing Multisphere StreamingSimulator PrototypeReplay PrototypeInteractive Tutorial TestList
L3D:
$(CLOSURE) $(OPT) \
--js l3d/src/l3d.js \
--js l3d/src/math/Tools.js \
--js l3d/src/math/Hermite.js \
--js l3d/src/utils/List.js \
--js l3d/src/utils/CameraSelecter.js \
--js l3d/src/utils/Logger.js \
--js l3d/src/utils/Objects.js \
@ -33,6 +34,13 @@ L3D:
--js l3d/src/scenes/initScene.js \
--js_output_file ../static/js/l3d.min.js
TestList:
$(CLOSURE) $(OPT) \
--js l3d/src/l3d.js \
--js l3d/src/utils/List.js \
--js l3d/src/utils/ListTest.js \
--js_output_file ../static/js/ListTest.min.js
L3DP:
$(CLOSURE) $(OPT) \
--js l3d/apps/prototype/ButtonManager.js \

View File

@ -142,13 +142,6 @@ function init() {
function initListeners() {
window.addEventListener('resize', onWindowResize, false);
// Transmit click event to camera selecter
document.addEventListener('mousedown', function(event) {
if (event.which == 1)
cameraSelecter.clickPointer(event);
}, false
);
// Transmit click event to camera selecter
container.addEventListener('mousedown', function(event) {
if (event.which == 1)

View File

@ -1,19 +1,89 @@
/**
* Contains a canvas to place over the renderer for FPS-style pointer
* It's based on a javascript 2d-canvas : you'll need to render it manually.
*
* @example
* var container = documeng.getElementById('container');
* var renderer = new THREE.WebGLRenderer();
* renderer.setSize(width, height);
*
* var pointerCamera = new L3D.PointerCamera(50, width/height, near, fat, renderer, container);
* var mousePointer = new L3D.MousePointer(pointerCamera);
* mousePointer.domElement.width = width;
* mousePointer.domElement.height = height;
*
* container.appendChild(mousePointer.domElement);
* container.appendChild(renderer.domElement);
*
* mousePointer.render(L3D.MousePointer.BLACK);
* @memberof L3D
* @constructor
*/
L3D.MousePointer = function(camera) {
/**
* @type {elemnt}
* @description The document element to add on top of the renderer
*/
this.domElement = document.createElement('canvas');
this.domElement.style.position = 'absolute';
this.domElement.style.cssFloat = 'top-left';
/**
* @type {CanvasRenderingContext2D}
* @description The context of the canvas
*/
this.ctx = this.domElement.getContext('2d');
/**
* @type {Number}
* @description The size of the gun sight
*/
this.size = 10;
this.drawn = false;
camera.mousePointer = this;
/**
* @type {Number}
* @description a L3D.MousePointer style. The current style of the mouse pointer
*/
this.style = L3D.MousePointer.NONE;
};
/**
* @memberof L3D.MousePointer
* @type {Number}
* @static
* @description Empty style : the canvas is fully transparent
*/
L3D.MousePointer.NONE = 0;
/**
* @memberof L3D.MousePointer
* @type {Number}
* @static
* @description Black style : the canvas contains only a white cross in the middle of the screen
*/
L3D.MousePointer.BLACK = 1;
/**
* @memberof L3D.MousePointer
* @type {Number}
* @static
* @description Red style : the canvas contains only a white and red cross in the midlle
* (used for hovering stuff)
*/
L3D.MousePointer.RED = 2;
/**
* @memberof L3D.MousePointer
* @static
* @description Converts a style to a color
* @param {Number} style a L3D.MousePointer style (NONE, BLACK, or RED)
* @returns {string} null if input is NONE, a hex color string else
*/
L3D.MousePointer.toColor = function(style) {
switch (style) {
@ -29,9 +99,28 @@ L3D.MousePointer.toColor = function(style) {
};
L3D.MousePointer.prototype.render = function(style) {
/**
* Re-renders the canvas
* For performance reasons, the rendering is done only if the style changed.
* @param {Number} style the L3D.MousePointer style you want to render
* @param {Boolean} force force the re-rendering (even if the style did not change)
*
*/
L3D.MousePointer.prototype.render = function(style, force) {
if (this.style !== style) {
if (style === undefined) {
style = L3D.MousePointer.NONE;
}
if (force === undefined) {
force = false;
}
if (this.style !== style || force) {
if (style === L3D.MousePointer.NONE) {
@ -75,8 +164,18 @@ L3D.MousePointer.prototype.render = function(style) {
};
L3D.MousePointer.prototype.clear = function() {
/**
* Clears the canvas
* @param {Boolean} force force the clearing (even if the style did not change)
*/
L3D.MousePointer.prototype.clear = function(force) {
this.render(L3D.MousePointer.NONE);
if (force === undefined) {
force = false;
}
this.render(L3D.MousePointer.NONE, force);
};

View File

@ -2,16 +2,72 @@ Math.clamp = Math.clamp || function(number, min, max) {
return Math.max(Math.min(number, max), min);
};
/**
* @memberof L3D
* @constructor
* @param {THREE.Renderer} renderer the renderer to use
* @param {THREE.Scene} scene the scene to render
* @description Displays a small preview of a camera
*/
L3D.Previewer = function(renderer, scene) {
/**
* @type {element}
* @description The document element to add on top of the renderer
*/
this.domElement = document.createElement('canvas');
/**
* @type {CanvasRenderingContext2D}
* @description The context of domElement
*/
this.ctx = this.domElement.getContext('2d');
/**
* @type {THREE.Renderer}
* @description The renderer to use
*/
this.renderer = renderer;
this.fixed = false;
/**
* @type {THREE.Scene}
* @description The scene to render
*/
this.scene = scene;
/**
* @type {Boolean}
* @description true if the preview should be stuck at the bottom left of the container,
* false if it should appear near the mouse
*/
this.fixed = false;
/**
* @private
* @type {Boolean}
* @description true if the rendering as already been done
*/
this.drawn = false;
/**
* @private
* @type {Boolean}
* @description true if the rendering was done before
*/
this.drawnBefore = false;
};
/**
* Renders the preview
* @param {Object} pref an object containing :
* <ul>
* <li><code>go</code> : a boolean if the rendering should be done</li>
* <li><code>x</code> : the x coordinate of the mouse</li>
* <li><code>y</code> : the y coordinate of the mouse</li>
* <li><code>camera</code> : the camera to use for the preview</li>
* </ul>
* @param {Number} container_width width of the container
* @param {Number} container_height height of the container
*/
L3D.Previewer.prototype.render = function(prev, container_width, container_height) {
var width, height, left, bottom;
@ -79,6 +135,9 @@ L3D.Previewer.prototype.render = function(prev, container_width, container_heigh
};
/**
* Clears the borders of the preview
*/
L3D.Previewer.prototype.clear = function() {
if (this.clearNeeded) {
this.domElement.width = this.domElement.width;
@ -86,10 +145,19 @@ L3D.Previewer.prototype.clear = function() {
}
};
/**
* Setter for the fixed preview
* @param {Boolean} true if you want to fix the preview, false otherwise
*/
L3D.Previewer.prototype.fixedRecommendation = function(bool) {
this.fixed = bool;
};
/**
* @private
* @description Update flags
* @param {Boolean} arg if the update drew something
*/
L3D.Previewer.prototype.update = function(arg) {
this.drawnBefore = this.drawn;
this.drawn = arg;

View File

@ -1,15 +1,37 @@
/**
* @memberof L3D
* @constructor
* @description Displays a translucid canvas over the renderer to enable interaction to lock pointer
*/
L3D.StartCanvas = function(camera) {
/**
* @type {elemnt}
* @description The document element to add on top of the renderer
*/
this.domElement = document.createElement('canvas');
this.domElement.style.position = 'absolute';
this.domElement.style.cssFloat = 'top-left';
/**
* @type {CanvasRenderingContext2D}
* @description The context of the canvas
*/
this.ctx = this.domElement.getContext('2d');
/**
* @type {Boolean}
* @description true if the canvas is displayed
*/
this.shown = false;
camera.startCanvas = this;
};
/**
* Shows the canvas with a string in the middle of it
*/
L3D.StartCanvas.prototype.render = function() {
if (!this.shown) {
@ -30,6 +52,9 @@ L3D.StartCanvas.prototype.render = function() {
};
/**
* Hide canvas
*/
L3D.StartCanvas.prototype.clear = function() {
if (this.shown) {

View File

@ -2,3 +2,11 @@
* @namespace
*/
var L3D = {};
if (typeof module !== 'undefined' && module.exports) {
var THREE = require('three');
module.exports = L3D;
}

View File

@ -1,10 +1,42 @@
/**
* @memberof L3D
* @namespace
* @description Contains eveything linked to hermite polynoms
*/
L3D.Hermite = {};
/**
* @memberof L3D.Hermite
* @constructor
* @description creates a hermite polynom
* @param t {Number[]|THREE.Vector3[]} time indices of the interpolation
* @param f {Number[]|THREE.Vector3[]} values of the polynom at each time
* @param fp {Number[]|THREE.Vector3[]} values of the derivative of the polynom at each time
*/
L3D.Hermite.Polynom = function(t, f, fp) {
/**
* @type {Number[]|THREE.Vector3[]}
* @description time indices of the interpolation
*/
this.times = t;
/**
* @type {Number[]|THREE.Vector3[]}
* @description values of the polynom at each time
*/
this.evals = f;
/**
* @type {Number[]|THREE.Vector3[]}
* @description values of the derivatives of the polynom at each time
*/
this.primes = fp;
/**
* @type {L3D.Hermite.BaseFunction[]}
* @description array of the base functions to evaluate the poylnom
*/
this.baseFunctions = [];
for (var i in this.times) {
@ -12,6 +44,14 @@ L3D.Hermite.Polynom = function(t, f, fp) {
}
// Let's do something at least a little reusable
/**
* @type {Object}
* @description an object containing
* <ul>
* <li><code>whatType</code> : a string being <code>THREE.Vector3</code> or <code>number</code></li>
* <li><code>tools</code> : an object containg sum and mul, functions of the correct type</li>
* </ul>
*/
this.tools = {};
if (f[0] instanceof THREE.Vector3) {
this.tools.whatType = 'THREE.Vector3';
@ -24,6 +64,11 @@ L3D.Hermite.Polynom = function(t, f, fp) {
}
};
/**
* Evaluates the polynom at a certain time
* @param t {Number} time at which you want to evaluate the polynom
* @return {Number|THREE.Vector3} the evaluation of the polynom at the given time
*/
L3D.Hermite.Polynom.prototype.eval = function(t) {
var ret;
@ -67,6 +112,11 @@ L3D.Hermite.Polynom.prototype.eval = function(t) {
return ret;
};
/**
* Evaluates the derivate of the polynom at a certain time
* @param t {Number} time at which you want to evaluate the derivative of the polynom
* @return {Number|THREE.Vector3} the evaluation of the derivative of the polynom at the given time
*/
L3D.Hermite.Polynom.prototype.prime = function(t) {
var ret;
@ -141,11 +191,32 @@ L3D.Hermite.Polynom.prototype.prime = function(t) {
return ret;
};
/**
* @memberof L3D.Hermite
* @constructor
* @description Represents a base function for evaluation of hermite polynoms
* @param index {Number} the index of the base function
* @param times {Number[]} the times for polynom interpolation
*/
L3D.Hermite.BaseFunction = function(index, times) {
/**
* @type {Number}
* @description the index of the base function
*/
this.index = index;
/**
* @type {Number[]}
* @description the times for polynom interpolation
*/
this.times = times;
};
/**
* Returns the evaluation of the base function
* @param t {Number} time at which you want to evaluate the base function
* @returns {Number} the evaluation of the base function at the given time
*/
L3D.Hermite.BaseFunction.prototype.eval = function(t) {
var ret = 1;
@ -158,6 +229,11 @@ L3D.Hermite.BaseFunction.prototype.eval = function(t) {
return ret * ret;
};
/**
* Returns the evaluation of the derivative of the base function
* @param t {Number} time at which you want to evaluate the derivative of the base function
* @returns {Number} the evaluation of the derivative of the base function at the given time
*/
L3D.Hermite.BaseFunction.prototype.prime = function(t) {
var ret = 0;
@ -170,16 +246,40 @@ L3D.Hermite.BaseFunction.prototype.prime = function(t) {
return this.eval(t) * ret;
};
/**
* @memberof L3D.Hermite
* @namespace
*/
L3D.Hermite.special = {};
// This polynom interpolates with two coords and one derivative
// t = [0,1]
/**
* @memberof L3D.Hermite.special
* @description Represents a simple hermite polynom where the times are [0, 1], and where
* the position is known at 0, 1 and where the derivative is only known at 1
* @constructor
* @param P0 {Number|THREE.Vector3} polynom at instant 0
* @param P1 {Number|THREE.Vector3} polynom at instant 1
* @param PP1 {Number|THREE.Vector3} derivative of the polynom at instant 1
*/
L3D.Hermite.special.Polynom = function(P0, P1, PP1) {
/**
* @type {Object}
* @description an object containing
* <ul>
* <li><code>whatType</code> : a string being <code>THREE.Vector3</code> or <code>number</code></li>
* <li><code>tools</code> : an object containg sum and mul, functions of the correct type</li>
* </ul>
*/
this.tools = {};
if (P0 instanceof THREE.Vector3) {
this.tools.sum = L3D.Tools.sum;
this.tools.mul = L3D.Tools.mul;
this.tools.diff = L3D.Tools.diff;
/**
* @type {Number|THREE.Vector3}
* @description b of ax²+bx+c
*/
this.c = P0.clone();
} else {
this.tools.sum = function(a,b) { return a+b; };
@ -188,14 +288,33 @@ L3D.Hermite.special.Polynom = function(P0, P1, PP1) {
this.c = P0;
}
/**
* @type {Number}
* @description a of ax²+bx+c
*/
this.a = this.tools.sum(PP1, this.tools.diff(P0, P1));
/**
* @type {Number}
* @description b of ax²+bx+c
*/
this.b = this.tools.diff(this.tools.mul(this.tools.diff(P1,P0), 2), PP1);
};
/**
* Returns the evaluation of the polynom
* @param t {Number} time at which you want to evaluate the polynom
* @returns {Number|THREE.Vector3} the evaluation of the polynom at the given time
*/
L3D.Hermite.special.Polynom.prototype.eval = function(t) {
return this.tools.sum(this.tools.mul(this.a, t*t), this.tools.sum(this.tools.mul(this.b, t), this.c));
};
/**
* Returns the evaluation of the derivative of the polynom
* @param t {Number} time at which you want to evaluate the derivative of the polynom
* @returns {Number|THREE.Vector3} the evaluation of the derivative of the polynom at the given time
*/
L3D.Hermite.special.Polynom.prototype.prime = function(t) {
return this.tools.sum(this.tools.mul(this.a,2*t), this.b);
};

View File

@ -1,17 +1,52 @@
/**
* @namespace
* @memberof L3D
* @description Contains various functions for manipulating THREE.Vector3
* Note that all these functions also work objects {x: x, y: y, z: z}, even if
* they're not THREE.Vector3
*/
L3D.Tools = {};
/**
* @memberof L3D.Tools
* @description Computes the sum of two vectors
* @param v1 {Vector} first vector of the sum
* @param v2 {Vector} second vector of the sum
* @returns {THREE.Vector3} v1 + v2
*/
L3D.Tools.sum = function(v1, v2) {
return new THREE.Vector3(v1.x + v2.x, v1.y + v2.y, v1.z + v2.z);
};
/**
* @memberof L3D.Tools
* @description Computes the difference between two vectors
* @param v1 {Vector} first vector of the difference
* @param v2 {Vector} second vector of the difference
* @returns {THREE.Vector3} v1 - v2
*/
L3D.Tools.diff = function(v1, v2) {
return new THREE.Vector3(v1.x - v2.x, v1.y - v2.y, v1.z - v2.z);
};
/**
* @memberof L3D.Tools
* @description Computes the dot product of two vectors
* @param v1 {Vector} first vector of the dot product
* @param v2 {Vector} second vector of the dot product
* @returns {THREE.Vector3} v1 * v2
*/
L3D.Tools.dot = function(v1, v2) {
return v1.x * v2.x + v1.y * v2.y + v1.z * v2.z;
};
/**
* @memberof L3D.Tools
* @description Computes the cross product of two vectors
* @param v1 {Vector} first vector of the cross product
* @param v2 {Vector} second vector of the cross product
* @returns {THREE.Vector3} v1 ^ v2
*/
L3D.Tools.cross = function(v1, v2) {
return new THREE.Vector3(
v1.y * v2.z - v1.z * v2.y,
@ -20,18 +55,33 @@ L3D.Tools.cross = function(v1, v2) {
);
};
/**
* @memberof L3D.Tools
* @description Computes the product of a vector and a number
* @param v1 {Vector} vector of the product
* @param lambda {Number} number of the product
* @returns {THREE.Vector3} v1 * lambda
*/
L3D.Tools.mul = function(v1, lambda) {
return new THREE.Vector3(v1.x * lambda, v1.y * lambda, v1.z * lambda);
};
L3D.Tools.equals = function(v1, v2) {
return v1.x == v2.x && v1.y == v2.y && v1.z == v2.z;
};
/**
* @memberof L3D.Tools
* @description Computes the square norm of a vector
* @param v {Vector} vector you want to compute the norm of
* @returns {Number} ||v||²
*/
L3D.Tools.norm2 = function(v) {
return v.x * v.x + v.y * v.y + v.z * v.z;
};
/**
* @memberof L3D.Tools
* @description Computes the norm of a vector
* @param v {Vector} vector you want to compute the norm of
* @returns {Number} ||v||
*/
L3D.Tools.norm = function(v) {
return Math.sqrt(L3D.Tools.norm2(v));
};

View File

@ -1,6 +1,8 @@
// Initialization
// class camera extends THREE.PerspectiveCamera
/**
* @description Represents a reccomendation displayed as an arrow
* @constructor
* @extends L3D.BaseRecommendation
*/
L3D.ArrowRecommendation = function(arg1, arg2, arg3, arg4, position, target) {
L3D.BaseRecommendation.apply(this, arguments);
};

View File

@ -1,6 +1,10 @@
// Initialization
// class camera extends THREE.PerspectiveCamera
/**
* @memberof L3D
* @description The base class for recommendation
* @constructor
* @extends THREE.PerspectiveCamera
* @abstract
*/
L3D.BaseRecommendation = function(arg1, arg2, arg3, arg4, position, target) {
THREE.PerspectiveCamera.apply(this, arguments);
@ -41,6 +45,9 @@ L3D.BaseRecommendation = function(arg1, arg2, arg3, arg4, position, target) {
L3D.BaseRecommendation.prototype = Object.create(THREE.PerspectiveCamera.prototype);
L3D.BaseRecommendation.prototype.constructor = L3D.BaseRecommendation;
/**
* Changes the color of the meshes like a HTML link
*/
L3D.BaseRecommendation.prototype.check = function() {
this.object3D.traverse(function(obj) {
if (obj instanceof THREE.Mesh)
@ -48,6 +55,9 @@ L3D.BaseRecommendation.prototype.check = function() {
});
};
/**
* Initialize the extremity of the arrow
*/
L3D.BaseRecommendation.prototype.initExtremity = function() {
var geometry = new THREE.Geometry();
@ -92,6 +102,9 @@ L3D.BaseRecommendation.prototype.initExtremity = function() {
return this.mesh;
};
/**
* Updates the extremity of the arrow
*/
L3D.BaseRecommendation.prototype.updateExtremity = function() {
var direction = this.target.clone();
direction.sub(this.position);
@ -118,12 +131,22 @@ L3D.BaseRecommendation.prototype.updateExtremity = function() {
};
/**
* Changes the size of the element
* @param size {Number} new size
* @deprecated this function doesn't work since there are lots of things to
* keep in mind (length of the arrow, width, size of the body, size of the
* extremity...)
*/
L3D.BaseRecommendation.prototype.setSize = function(size) {
this.size = size;
this.updateExtremity();
};
// Update function
/**
* Updates the arrow. The arrow is moving according to the position of the camera
* @param {Object} a camera containing two THREE.Vector3 (position, and target)
*/
L3D.BaseRecommendation.prototype.update = function(mainCamera) {
// Compute distance between center of camera and position
dist = L3D.Tools.norm2(L3D.Tools.diff(mainCamera.position, this.center));
@ -156,6 +179,10 @@ L3D.BaseRecommendation.prototype.update = function(mainCamera) {
this.regenerateArrow(mainCamera);
};
/**
* Regenerates the arrow according to the position of the camera
* @param {Object} a camera containing two THREE.Vector3 (position, and target)
*/
L3D.BaseRecommendation.prototype.regenerateArrow = function(mainCamera) {
var i;
var vertices = [];
@ -266,20 +293,34 @@ L3D.BaseRecommendation.prototype.regenerateArrow = function(mainCamera) {
};
// Look function
/**
* Look at function. Just like OpenGL gluLookAt (from position to target)
*/
L3D.BaseRecommendation.prototype.look = function() {
this.lookAt(this.target);
};
/**
* Add the camera and its mesh representation to the scene
* @param scene {THREE.Scene} scene to add the camera to
*/
L3D.BaseRecommendation.prototype.addToScene = function(scene) {
scene.add(this);
scene.add(this.object3D);
};
/**
* Apply a callback to all objects representing the camera
* @param callback {function} callback to call on each mesh
*/
L3D.BaseRecommendation.prototype.traverse = function(callback) {
this.object3D.traverse(callback);
};
/**
* Checks if an object is contained in the representation of the camera
* @param object {THREE.Object3D} Object that could belong the camera
*/
L3D.BaseRecommendation.prototype.containsObject = function(object) {
return object.parent === this.object3D;
};

View File

@ -1,3 +1,9 @@
/**
* @constructor
* @memberof L3D
* @description Different representation of 3D recommendation (kind of a weird one)
* @extends L3D.BaseRecommendation
*/
L3D.ReverseRecommendation = function(arg1, arg2, arg3, arg4, position, target) {
L3D.BaseRecommendation.apply(this, arguments);
};

View File

@ -1,6 +1,9 @@
// Initialization
// class camera extends THREE.PerspectiveCamera
/**
* @memberof L3D
* @extends L3D.BaseRecommendation
* @description Reprensents a recommendation as a viewport (3D representation of a camera)
* @constructor
*/
L3D.ViewportRecommendation = function(arg1, arg2, arg3, arg4, position, target) {
THREE.PerspectiveCamera.apply(this, arguments);

View File

@ -116,8 +116,6 @@ L3D.CameraSelecter.prototype.update = function(event, y) {
L3D.CameraSelecter.prototype.click = function(event) {
var e;
if (this.cameras.mainCamera().pointerLocked === false) {
var newCamera = this.pointedCamera();
if (newCamera !== undefined && !(newCamera instanceof Coin)) {
@ -140,35 +138,4 @@ L3D.CameraSelecter.prototype.click = function(event) {
}
}
};
L3D.CameraSelecter.prototype.clickPointer = function(event) {
var e;
if (this.cameras.mainCamera().pointerLocked) {
var newCamera = this.pointedCamera();
if (newCamera !== undefined && !(newCamera instanceof Coin)) {
e = new L3D.BD.Event.ArrowClicked();
e.arrow_id = this.cameras.cameras.indexOf(newCamera);
e.send();
newCamera.check();
this.cameras.mainCamera().moveHermite(newCamera);
buttonManager.updateElements();
} else if (newCamera instanceof Coin) {
// Coin found, notify server
e = new L3D.BD.Event.CoinClicked();
e.coin_id = this.coins.indexOf(newCamera);
e.send();
newCamera.get();
}
}
};

View File

@ -1,21 +1,55 @@
/**
* @namespace
* @memberof L3D
*/
L3D.utils = (function() {
var utils = {};
// Defines a double linked-list class
utils.List = function() {
/**
* @constructor
* @description Linked list in javascript
* @memberof L3D.utils
*/
var List = function() {
/**
* @private
* @type {Number}
* @description number of elements in the list
*/
this._size = 0;
/**
* @private
* @type {Object}
* @description first chain element of the list
*/
this._begin = null;
/**
* @private
* @type {Object}
* @description last chain element of the list
*/
this._end = null;
};
// Returns the number of element of a list
utils.List.prototype.size = function() {
/**
* Size of the list
* Complexity O(1)
* @returns {Number} the number of elements in the list
*/
List.prototype.size = function() {
return this._size;
};
// Pushes an element to the end of a class
utils.List.prototype.push = function(element) {
/**
* Push an element at the end of the list
* Complexity O(1)
* @param element {Object} object to push at the end of the list
*/
List.prototype.push = function(element) {
if (this._size === 0) {
this._begin = { data : element, next: null, prev: null };
this._end = this._begin;
@ -28,8 +62,11 @@ utils.List.prototype.push = function(element) {
}
};
// Sort the list
utils.List.prototype.sort = function(comparator) {
/**
* Sorts the list by creating an array, sorting it, and recopying it to the list
* Complexity O(size() * log (size()))
*/
List.prototype.sort = function(comparator) {
if (comparator === undefined) {
comparator = priv.defaultComparator;
@ -52,15 +89,23 @@ utils.List.prototype.sort = function(comparator) {
}
};
// Remove last element and returns it
utils.List.prototype.pop = function() {
/**
* Removes and returns the last element of the list
* Complexity O(1)
* @returns {Object} the last element of the list
*/
List.prototype.pop = function() {
var tmp = this._end;
this._end = null;
return tmp.data;
};
// Apply a function to each element of the list
utils.List.prototype.forEach = function(callback) {
/**
* Apply a call back to each element of the list
* Complexity O(size())
* @param callback {function} callback to call on all elements of the list
*/
List.prototype.forEach = function(callback) {
var chain = this._begin;
while (chain !== null) {
@ -69,8 +114,12 @@ utils.List.prototype.forEach = function(callback) {
}
};
// Apply a function to each element of the list (starting from the end)
utils.List.prototype.forEachInverse = function(callback) {
/**
* Apply a call back to each element of the list in reverse order
* Complexity O(size())
* @param callback {function} callback to call on all elements of the list in reverse order
*/
List.prototype.forEachInverse = function(callback) {
var chain = this._end;
while (chain !== null) {
@ -79,8 +128,13 @@ utils.List.prototype.forEachInverse = function(callback) {
}
};
// Get ith element of the list
utils.List.prototype.at = function(ith) {
/**
* Get the ith element of the list
* Complexity O(ith)
* @param ith {Number} index of the element to get
* @returns {Object} the ith element if it exists, null otherwise
*/
List.prototype.at = function(ith) {
if (ith < 0 || ith >= this.size()) {
return null;
}
@ -93,16 +147,23 @@ utils.List.prototype.at = function(ith) {
return chain.data;
};
// Clear the list
utils.List.prototype.clear = function() {
/**
* Empty the list
*/
List.prototype.clear = function() {
this._begin = null;
this._end = null;
this._size = 0;
};
// Insert an element at the right place in the list
// Precondition : list must be sorted
utils.List.prototype.insertSorted = function(elt, comparator) {
/**
* Insert an element at the right place in a sorted list
* Precondition : the list must be sorted
* Complexity : O(i) where i is the number of elements lower than elt
* @param elt {Object} element to add
* @param comparator {function} classic js comparator
*/
List.prototype.insertSorted = function(elt, comparator) {
var newElement;
if (comparator === undefined) {
@ -146,8 +207,13 @@ utils.List.prototype.insertSorted = function(elt, comparator) {
}
};
// Check if a list is sorted of not
utils.List.prototype.isSorted = function(comparator) {
/**
* Checks if a list is sorted
* Complexity : O(size()) if the list is sorted, O(i) where i is the first non-sorted element in the list
* @param comparator {function} classic js comparator
* @returns {Boolean} true if the list is sorted, false otherwise
*/
List.prototype.isSorted = function(comparator) {
var chain = this._begin;
if (comparator === undefined) {
@ -164,61 +230,107 @@ utils.List.prototype.isSorted = function(comparator) {
return true;
};
// Gives an iterator to the begin of the list
utils.List.prototype.begin = function() {
return new utils.List.Iterator(this._begin, 0);
/**
* Returns an iterator to the begin of the list
* @returns {Iterator} an interator to the first element
*/
List.prototype.begin = function() {
return new Iterator(this._begin, 0);
};
// Gives an iterator to the end of the list
utils.List.prototype.end = function() {
return new utils.List.Iterator(this._end, this.size() - 1);
/**
* Returns an iterator to the end of the list
* @returns {Iterator} an interator to the first element
*/
List.prototype.end = function() {
return new Iterator(this._end, this.size() - 1);
};
// Class iterator
utils.List.Iterator = function(chain, counter) {
/**
* @constructor
* @description Reprensents an iterator to an element of a list
* @param chain {Object} chain element of a list
* @param counter {Number} index of the current element
* @memberof L3D.utils
*/
var Iterator = function(chain, counter) {
this._chain = chain;
this._counter = counter;
};
// Go to the next element
utils.List.Iterator.prototype.next = function() {
/**
* Go to the next element
* @method
*/
Iterator.prototype.next = function() {
this._chain = this._chain.next;
this._counter ++;
};
// Go to the previous element
utils.List.Iterator.prototype.prev = function() {
/**
* Go to the previous element
* @method
*/
Iterator.prototype.prev = function() {
this._chain = this._chain.prev;
this._counter --;
};
// Return the current element
utils.List.Iterator.prototype.get = function() {
/**
* Returns the current element
* @method
* @returns {Object} current element
*/
Iterator.prototype.get = function() {
return this._chain.data;
};
// Check if there is another element next
utils.List.Iterator.prototype.hasNext = function() {
/**
* Checks if there is a element after the current element
* @method
* @returns {Boolean} true if the element exists, false otherwise
*/
Iterator.prototype.hasNext = function() {
return this._chain.next !== null;
};
// Check if there is another element before
utils.List.Iterator.prototype.hasPrev = function() {
/**
* Checks if there is a element before the current element
* @method
* @returns {Boolean} true if the element exists, false otherwise
*/
Iterator.prototype.hasPrev = function() {
return this._chain.prev !== null;
};
// Compares to another iterator of the same list
utils.List.Iterator.prototype.lowerThan = function(it2) {
return utils.distance(this, it2) > 0;
/**
* Compares two iterators of the same list
* @param it2 {Iterator} second iterator of the comparison
* @returns {Boolean} result of this < it2
*/
Iterator.prototype.lowerThan = function(it2) {
return distance(this, it2) > 0;
};
// Compares to another iterator of the same list
utils.List.Iterator.prototype.greaterThan = function(it2) {
return utils.distance(this, it2) < 0;
/**
* Compares two iterators of the same list
* @method
* @param it2 {Iterator} second iterator of the comparison
* @returns {Boolean} result of this > it2
*/
Iterator.prototype.greaterThan = function(it2) {
return distance(this, it2) < 0;
};
// Returns the distance between two iterators of the same list
utils.distance = function(it1, it2) {
/**
* Compute the distance between two iterators
* @method
* @private
* @param it1 {Iterator} first iterator of the computation
* @param it2 {Iterator} second iterator of the computation
* @returns {Number} distance between it1 and it2
*/
var distance = function(it1, it2) {
return it2._counter - it1._counter;
};
@ -232,11 +344,11 @@ priv.defaultComparator = function(a,b) {
return 0;
};
// Support for NodeJs
if (typeof module !== 'undefined' && module.exports) {
module.exports = utils;
} else {
utils.List = List;
utils.Iterator = Iterator;
return utils;
}
console.log("Hello");
})();