File: src/math/displacement.js
window.multigraph.util.namespace("window.multigraph.math", function (ns) {
"use strict";
/**
* The Math module provides utility models and functions which correspond to mathematical concepts.
*
* @module multigraph
* @submodule math
* @main math
*/
/**
* A Displacement represents a geometric position along a line
* segment, expressed in terms of two quantities: a relative
* position called `a`, and an absolute offset called `b`. The
* length of the line segment is not known in advance --- the idea
* is that the Displacement object encapsulates a rule for
* determining a location along ANY line segment. The Displacement
* has methods which take the line segment length as an argument
* and return the computed final position.
*
* There are two different position-calcuating methods,
* corresponding to two different interpretations of the relative
* value `a`:
*
* **relative length**:
* `a` is a number between 0 and 1, representing a fraction of
* the total length of the line segment; the relative
* position determined by `a` is the fraction `a` of the
* total length of the segment.
* In this case, the position-calculating method
* `calculateLength(L)` returns the number `a * L + b`, which
* corresponds to moving `a` of the way along the length L,
* then adding `b`:
*
* [--------------------------------X------------]
* |<---- a * L --->|<---- b ------>|
* |<------------------ L -------------------->|
*
* **relative coordinate**:
* `a` is a number between -1 and 1, representing a coordinate
* value in a [-1,1] coordinate system along the line
* segment.
* In this case, the position-calculating method
* `calculateCoordinate(L)` returns the number `(a+1) * L/2 +
* b`. which corresponds to moving to the position
* determined by the `a` coordinate, then adding `b`:
*
* [------------------------------------X--------]
* |<--- (a+1) * L/2 --->|<---- b ----->|
* |<------------------ L -------------------->|
*
* @class Displacement
* @for Displacement
* @constructor
* @param {Number} a
* @param {Integer} b (OPTIONAL)
*/
ns.Displacement = new window.jermaine.Model("Displacement", function () {
this.hasA("a").which.validatesWith(function (a) {
return window.multigraph.utilityFunctions.validateNumberRange(a, -1.0, 1.0);
});
this.hasA("b").which.isA("integer").and.defaultsTo(0);
this.isBuiltWith("a", "%b");
this.respondsTo("calculateLength", function (totalLength) {
return this.a() * totalLength + this.b();
});
this.respondsTo("calculateCoordinate", function (totalLength) {
return (this.a() + 1) * totalLength/2.0 + this.b();
});
});
ns.Displacement.regExp = /^([\+\-]?[0-9\.]+)([+\-])([0-9\.+\-]+)$/;
/**
* Parses a string into a Displacement. The string should be of one of the following forms:
*
* "A+B" ==> a=A b=B
* "A-B" ==> a=A b=-B
* "A" ==> a=A b=0
* "+A" ==> a=A b=0
* "-A" ==> a=-A b=0
*
* @method parse
* @param {String} string
* @static
* @author jrfrimme
*/
ns.Displacement.parse = function (string) {
var ar = ns.Displacement.regExp.exec(string),
d,
a,
b,
sign;
if (string === undefined) {
d = new ns.Displacement(1);
} else if (ar !== null) {
a = parseFloat(ar[1]);
b = parseFloat(ar[3]);
switch (ar[2]) {
case "+":
sign = 1;
break;
case "-":
sign = -1;
break;
default:
sign = 0;
break;
}
/*
if (isNaN(a) || sign == 0 || isNaN(b)) {
throw new ParseError('parse error');
}
*/
d = new ns.Displacement(a, sign * b);
} else {
a = parseFloat(string);
/*n
if (isNaN(a)) {
throw new ParseError('parse error');
}
*/
d = new ns.Displacement(a);
}
return d;
};
});