Migrating the original QuasimondoLibs to Javascript. Mostly 2D Geometry.
48 |
For the drawing part and some of the UI elements Qlib uses EaselJS - for
49 | pure geometric operation it is not required though.
50 |
A big part of the intersection algorithms and their helper methods (most of which I still have to port from my ActionScript library)
51 | were originally taken from Kevin Lindsey: http://www.kevlindev.com/gui/math/intersection/index.htm
114 |
115 |
116 |
117 |
118 |
119 |
--------------------------------------------------------------------------------
/src/qlib/geom/PolygonUtils.js:
--------------------------------------------------------------------------------
1 | /*
2 | * PolygonUtils
3 | *
4 | * Copyright (c) 2013 Mario Klingemann
5 | *
6 | * Permission is hereby granted, free of charge, to any person
7 | * obtaining a copy of this software and associated documentation
8 | * files (the "Software"), to deal in the Software without
9 | * restriction, including without limitation the rights to use,
10 | * copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | * copies of the Software, and to permit persons to whom the
12 | * Software is furnished to do so, subject to the following
13 | * conditions:
14 | *
15 | * The above copyright notice and this permission notice shall be
16 | * included in all copies or substantial portions of the Software.
17 | *
18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
20 | * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
22 | * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
23 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
24 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
25 | * OTHER DEALINGS IN THE SOFTWARE.
26 | */
27 |
28 | // namespace:
29 | window["qlib"] = window.qlib || {};
30 |
31 | (function() {
32 |
33 | /**
34 | * A utility class providing static helper methods for operations related to `qlib.Polygon` objects.
35 | * This class is not intended to be instantiated.
36 | * @class PolygonUtils
37 | * @memberof qlib
38 | */
39 | var PolygonUtils = function() {
40 | // Static class, not meant to be instantiated.
41 | throw new Error("PolygonUtils cannot be instantiated.");
42 | }
43 |
44 | // static methods:
45 | /**
46 | * Creates a smoothed version of a given polygon, returned as a `qlib.MixedPath`.
47 | * This is achieved by converting the polygon to a `qlib.LinearPath` and then calling
48 | * its `getSmoothPath` method. The resulting path is treated as closed.
49 | *
50 | * @static
51 | * @method getSmoothPath
52 | * @param {qlib.Polygon} polygon - The polygon to smooth.
53 | * @param {number} factor - The smoothing factor. Its interpretation depends on the `mode`.
54 | * @param {number} [mode=0] - The smoothing mode, corresponding to constants in `qlib.LinearPath`
55 | * (e.g., `qlib.LinearPath.SMOOTH_PATH_RELATIVE_EDGEWISE`). Defaults to 0.
56 | * @returns {qlib.MixedPath} A new `qlib.MixedPath` instance representing the smoothed polygon.
57 | * @see qlib.LinearPath#getSmoothPath
58 | * @see qlib.LinearPath.SMOOTH_PATH_RELATIVE_EDGEWISE
59 | * @see qlib.LinearPath.SMOOTH_PATH_ABSOLUTE_EDGEWISE
60 | * @see qlib.LinearPath.SMOOTH_PATH_RELATIVE_MINIMUM
61 | * @see qlib.LinearPath.SMOOTH_PATH_ABSOLUTE_MINIMUM
62 | */
63 | PolygonUtils.getSmoothPath = function( polygon, factor, mode)
64 | {
65 | if ( mode == null ) mode = 0; // Corresponds to qlib.LinearPath.SMOOTH_PATH_RELATIVE_EDGEWISE
66 | // Polygon.toArray() returns a copy of points. clonePoints=true ensures they are new Vector2 instances for the LinearPath.
67 | return qlib.LinearPath.fromArray( polygon.toArray(true), false ).getSmoothPath( factor, mode, true ); // Pass true for clonePoints to fromArray if points should be cloned, then false to fromArray itself.
68 | // The polygon.toArray(true) already clones. So, fromArray's clonePoints can be false.
69 | }
70 |
71 | qlib["PolygonUtils"] = PolygonUtils;
72 | }());
--------------------------------------------------------------------------------
/src/qlib/geom/MixedPathPoint.js:
--------------------------------------------------------------------------------
1 | /**
2 | * MixedPath Point
3 | *
4 | * Copyright (c) 2013 Mario Klingemann
5 | *
6 | * Permission is hereby granted, free of charge, to any person
7 | * obtaining a copy of this software and associated documentation
8 | * files (the "Software"), to deal in the Software without
9 | * restriction, including without limitation the rights to use,
10 | * copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | * copies of the Software, and to permit persons to whom the
12 | * Software is furnished to do so, subject to the following
13 | * conditions:
14 | *
15 | * The above copyright notice and this permission notice shall be
16 | * included in all copies or substantial portions of the Software.
17 | *
18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
20 | * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
22 | * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
23 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
24 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
25 | * OTHER DEALINGS IN THE SOFTWARE.
26 | */
27 |
28 | // namespace:
29 | window["qlib"] = window.qlib || {};
30 |
31 | (function() {
32 |
33 | /**
34 | * Represents a point within a `qlib.MixedPath`.
35 | * It extends `qlib.Vector2` and adds a flag to distinguish between
36 | * anchor points (vertices of the path) and control points (used for Bezier curves).
37 | *
38 | * @class MixedPathPoint
39 | * @extends qlib.Vector2
40 | * @memberof qlib
41 | * @constructor
42 | * @param {qlib.Vector2} point - The `qlib.Vector2` instance whose coordinates will be used for this point.
43 | * The x and y values are copied.
44 | * @param {boolean} [isControlPoint=false] - True if this point is a control point, false if it's an anchor point.
45 | */
46 | var MixedPathPoint = function( point, isControlPoint ) {
47 | this.initialize( point, isControlPoint );
48 | }
49 |
50 | var p = MixedPathPoint.prototype = new qlib.Vector2();
51 |
52 | // public properties:
53 | /**
54 | * The type of this object.
55 | * @property {string} type
56 | * @default "MixedPathPoint"
57 | */
58 | p.type = "MixedPathPoint";
59 |
60 | /**
61 | * Flag indicating whether this point is a control point (true) or an anchor point (false).
62 | * Anchor points define the main vertices of the path segments, while control points
63 | * influence the curvature of Bezier segments.
64 | * @property {boolean} isControlPoint
65 | * @default false
66 | */
67 | p.isControlPoint = false;
68 |
69 |
70 | // constructor:
71 | /**
72 | * Initialization method called by the constructor.
73 | * Sets the x and y coordinates from the provided `point` object and the `isControlPoint` flag.
74 | * Calls the superclass (`qlib.Vector2`) initialize method.
75 | * @method initialize
76 | * @protected
77 | * @param {qlib.Vector2} point - The `qlib.Vector2` to copy coordinates from.
78 | * @param {boolean} [isControlPoint=false] - Whether this point is a control point.
79 | * @returns {void}
80 | */
81 | p.initialize = function( point, isControlPoint )
82 | {
83 | // Call superclass initialize. Vector2's initialize can take a Vector2 as its first arg in an array.
84 | qlib.Vector2.prototype.initialize.call(this, [point]);
85 | this.isControlPoint = isControlPoint || false;
86 | }
87 |
88 | /**
89 | * Returns a string representation of this MixedPathPoint.
90 | * Format: "x|y" for anchor points, "x|y|c" for control points.
91 | * @method toString
92 | * @return {string} A string representation of the instance.
93 | **/
94 | p.toString = function() {
95 | return this.x + "|" + this.y + ( this.isControlPoint ? "|c":"" );
96 | }
97 |
98 | qlib["MixedPathPoint"] = MixedPathPoint;
99 | }());
--------------------------------------------------------------------------------
/src/qlib/math/SimplexNoise.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Ported from Stefan Gustavson's java implementation
3 | * http://staffwww.itn.liu.se/~stegu/simplexnoise/simplexnoise.pdf
4 | * Sean McCullough banksean@gmail.com
5 | *
6 | * Original JS code by Peter Nitsch - https://github.com/pnitsch/BitmapData.js
7 | * HTML5 Canvas API implementation of the AS3 BitmapData class.
8 | *
9 | * adapted and augmented by Mario Klingemann for qlib
10 | *
11 | * Permission is hereby granted, free of charge, to any person
12 | * obtaining a copy of this software and associated documentation
13 | * files (the "Software"), to deal in the Software without
14 | * restriction, including without limitation the rights to use,
15 | * copy, modify, merge, publish, distribute, sublicense, and/or sell
16 | * copies of the Software, and to permit persons to whom the
17 | * Software is furnished to do so, subject to the following
18 | * conditions:
19 | *
20 | * The above copyright notice and this permission notice shall be
21 | * included in all copies or substantial portions of the Software.
22 | *
23 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
25 | * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
27 | * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
28 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
29 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
30 | * OTHER DEALINGS IN THE SOFTWARE.
31 | */
32 |
33 | // namespace:
34 | window["qlib"] = window.qlib || {};
35 |
36 | (function() {
37 |
38 | var SimplexNoise = function(gen) {
39 | this.rand = gen;
40 |
41 | };
42 |
43 | SimplexNoise.grad3 = [
44 | [1,1,0],[-1,1,0],[1,-1,0],[-1,-1,0],
45 | [1,0,1],[-1,0,1],[1,0,-1],[-1,0,-1],
46 | [0,1,1],[0,-1,1],[0,1,-1],[0,-1,-1]
47 | ];
48 |
49 | SimplexNoise.simplex = [
50 | [0,1,2,3],[0,1,3,2],[0,0,0,0],[0,2,3,1],[0,0,0,0],[0,0,0,0],[0,0,0,0],[1,2,3,0],
51 | [0,2,1,3],[0,0,0,0],[0,3,1,2],[0,3,2,1],[0,0,0,0],[0,0,0,0],[0,0,0,0],[1,3,2,0],
52 | [0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0],
53 | [1,2,0,3],[0,0,0,0],[1,3,0,2],[0,0,0,0],[0,0,0,0],[0,0,0,0],[2,3,0,1],[2,3,1,0],
54 | [1,0,2,3],[1,0,3,2],[0,0,0,0],[0,0,0,0],[0,0,0,0],[2,0,3,1],[0,0,0,0],[2,1,3,0],
55 | [0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0],
56 | [2,0,1,3],[0,0,0,0],[0,0,0,0],[0,0,0,0],[3,0,1,2],[3,0,2,1],[0,0,0,0],[3,1,2,0],
57 | [2,1,0,3],[0,0,0,0],[0,0,0,0],[0,0,0,0],[3,1,0,2],[0,0,0,0],[3,2,0,1],[3,2,1,0]
58 | ];
59 |
60 | SimplexNoise.F2 = 0.5*(Math.sqrt(3.0)-1.0);
61 | SimplexNoise.G2 = (3.0-Math.sqrt(3.0))/6.0;
62 |
63 | var p = SimplexNoise.prototype;
64 |
65 | p.setSeed = function(seed) {
66 | this.p = [];
67 | this.rand.seed = seed;
68 |
69 | for (var i=0; i<256; i++) {
70 | this.p[i] = (this.rand.nextRange(0, 255) | 0);
71 | }
72 |
73 | this.perm = [];
74 | for(var i=0; i<512; i++) {
75 | this.perm[i]=this.p[i & 255];
76 | }
77 | }
78 |
79 | p.noise = function(xin, yin) {
80 | var n0, n1, n2;
81 |
82 | var s = (xin+yin)*SimplexNoise.F2;
83 | var i = (xin+s) | 0;
84 | var j = (yin+s) | 0;
85 |
86 | var t = (i+j)*SimplexNoise.G2;
87 | var X0 = i-t;
88 | var Y0 = j-t;
89 | var x0 = xin-X0;
90 | var y0 = yin-Y0;
91 |
92 | var i1, j1;
93 | if(x0>y0) {i1=1; j1=0;}
94 | else {i1=0; j1=1;}
95 |
96 | var x1 = x0 - i1 + SimplexNoise.G2;
97 | var y1 = y0 - j1 + SimplexNoise.G2;
98 | var x2 = x0 - 1.0 + 2.0 * SimplexNoise.G2;
99 | var y2 = y0 - 1.0 + 2.0 * SimplexNoise.G2;
100 |
101 | var ii = i & 255;
102 | var jj = j & 255;
103 | var gi0 = SimplexNoise.grad3[this.perm[ii+this.perm[jj]] % 12];
104 | var gi1 = SimplexNoise.grad3[this.perm[ii+i1+this.perm[jj+j1]] % 12];
105 | var gi2 = SimplexNoise.grad3[this.perm[ii+1+this.perm[jj+1]] % 12];
106 |
107 | var t0 = 0.5 - x0*x0-y0*y0;
108 | if(t0<0) n0 = 0.0;
109 | else {
110 | t0 *= t0;
111 | n0 = t0 * t0 * (gi0[0]*x0 + gi0[1]*y0);
112 | }
113 |
114 | var t1 = 0.5 - x1*x1-y1*y1;
115 | if(t1<0) n1 = 0.0;
116 | else {
117 | t1 *= t1;
118 | n1 = t1 * t1 * (gi1[0]*x1 + gi1[1]*y1);
119 | }
120 | var t2 = 0.5 - x2*x2-y2*y2;
121 | if(t2<0) n2 = 0.0;
122 | else {
123 | t2 *= t2;
124 | n2 = t2 * t2 * (gi2[0]*x2 + gi2[1]*y2);
125 | }
126 |
127 | return 70.0 * (n0 + n1 + n2);
128 | };
129 |
130 | qlib["SimplexNoise"] = SimplexNoise;
131 |
132 | }());
--------------------------------------------------------------------------------
/demos/SoddyCircles.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | QuasimondoLibsJS Demo: Soddy Circles
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
22 |
23 |
137 |
138 |
139 |
140 |
141 |
142 |
/**
30 | * MixedPath Point
31 | *
32 | * Copyright (c) 2013 Mario Klingemann
33 | *
34 | * Permission is hereby granted, free of charge, to any person
35 | * obtaining a copy of this software and associated documentation
36 | * files (the "Software"), to deal in the Software without
37 | * restriction, including without limitation the rights to use,
38 | * copy, modify, merge, publish, distribute, sublicense, and/or sell
39 | * copies of the Software, and to permit persons to whom the
40 | * Software is furnished to do so, subject to the following
41 | * conditions:
42 | *
43 | * The above copyright notice and this permission notice shall be
44 | * included in all copies or substantial portions of the Software.
45 | *
46 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
47 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
48 | * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
49 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
50 | * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
51 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
52 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
53 | * OTHER DEALINGS IN THE SOFTWARE.
54 | */
55 |
56 | // namespace:
57 | window["qlib"] = window.qlib || {};
58 |
59 | (function() {
60 |
61 | var MixedPathPoint = function( point, isControlPoint ) {
62 | this.initialize( point, isControlPoint );
63 | }
64 |
65 | var p = MixedPathPoint.prototype = new qlib.Vector2();
66 |
67 | // public properties:
68 | p.type = "MixedPathPoint";
69 |
70 |
71 | // constructor:
72 | /**
73 | * Initialization method.
74 | * @method initialize
75 | * @protected
76 | */
77 | p.initialize = function( point, isControlPoint )
78 | {
79 | qlib.Vector2.prototype.initialize.call(this, [point]);
80 | this.isControlPoint = isControlPoint || false;
81 | }
82 |
83 | /**
84 | * Returns a string representation of this object.
85 | * @method toString
86 | * @return {String} a string representation of the instance.
87 | **/
88 | p.toString = function() {
89 | return this.x + "|" + this.y + ( this.isControlPoint ? "|c":"" );
90 | }
91 |
92 | qlib["MixedPathPoint"] = MixedPathPoint;
93 | }());
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
105 |
106 |
107 |
108 |
111 |
112 |
113 |
114 |
115 |
116 |
--------------------------------------------------------------------------------
/src/qlib/events/Event.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Event
3 | * Visit http://createjs.com/ for documentation, updates and examples.
4 | *
5 | * Copyright (c) 2010 gskinner.com, inc.
6 | *
7 | * Permission is hereby granted, free of charge, to any person
8 | * obtaining a copy of this software and associated documentation
9 | * files (the "Software"), to deal in the Software without
10 | * restriction, including without limitation the rights to use,
11 | * copy, modify, merge, publish, distribute, sublicense, and/or sell
12 | * copies of the Software, and to permit persons to whom the
13 | * Software is furnished to do so, subject to the following
14 | * conditions:
15 | *
16 | * The above copyright notice and this permission notice shall be
17 | * included in all copies or substantial portions of the Software.
18 | *
19 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
20 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
21 | * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
22 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
23 | * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
24 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
25 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
26 | * OTHER DEALINGS IN THE SOFTWARE.
27 | */
28 |
29 | // namespace:
30 | window["qlib"] = window.qlib || {};
31 |
32 | (function() {
33 |
34 | /**
35 | * Represents a basic event dispatched by an object.
36 | * Event instances are passed as parameters to event listeners when an event occurs.
37 | * This class is a fundamental part of the event handling mechanism in qlib,
38 | * often used in conjunction with `qlib.EventDispatcher`.
39 | *
40 | * For example, `qlib.DisplayObject` instances might dispatch `Event` objects (or subclasses of `Event`)
41 | * for interactions like clicks or mouse movements.
42 | *
43 | * While this base `Event` class includes `EventDispatcher` methods through a mixin,
44 | * `Event` instances themselves are typically not used to dispatch further events.
45 | * Rather, they are data objects that carry information about an occurrence.
46 | *
47 | * @class Event
48 | * @constructor
49 | * @param {string} type - The type of the event (e.g., "click", "complete"). This string is used to identify the event.
50 | * @param {Object} target - The object that dispatched the event. This is often the `this` reference from the dispatcher.
51 | * @see qlib.EventDispatcher
52 | * @see qlib.DisplayObject
53 | */
54 | var Event = function(type, target) {
55 | this.initialize(type, target);
56 | }
57 | var p = Event.prototype;
58 |
59 | // properties:
60 |
61 | /**
62 | * The type of the event (e.g., "click", "complete").
63 | * This string is used to identify the specific event that occurred.
64 | * @property {string} type
65 | **/
66 | p.type = null;
67 |
68 |
69 | /**
70 | * The object that dispatched the event.
71 | * This is the source of the event, often an instance of a class that uses `qlib.EventDispatcher`.
72 | * For example, if a `DisplayObject` dispatches an event, `target` would be that `DisplayObject`.
73 | * @property {Object} target
74 | * @default null
75 | */
76 | p.target = null;
77 |
78 |
79 |
80 | // mix-ins:
81 | // EventDispatcher methods are mixed in, but typically not used on Event instances themselves.
82 | // These are more relevant for classes that *dispatch* events.
83 | p.addEventListener = null;
84 | p.removeEventListener = null;
85 | p.removeAllEventListeners = null;
86 | p.dispatchEvent = null;
87 | p.hasEventListener = null;
88 | p._listeners = null;
89 | qlib.EventDispatcher.initialize(p); // inject EventDispatcher methods.
90 |
91 | // constructor:
92 | /**
93 | * Initializes the Event instance with the specified type and target.
94 | * This method is called by the constructor.
95 | * @method initialize
96 | * @protected
97 | * @param {string} type - The type of the event.
98 | * @param {Object} target - The object that dispatched the event.
99 | * @returns {void}
100 | **/
101 | p.initialize = function(type, target) {
102 | this.type = type;
103 | this.target = target;
104 |
105 | }
106 |
107 | // public methods:
108 | /**
109 | * Creates and returns a new Event instance that is a shallow copy of this event object.
110 | * The `target` property is a direct reference copy, not a deep clone.
111 | *
112 | * @method clone
113 | * @return {qlib.Event} A new Event instance with the same `type` and `target` as this one.
114 | **/
115 | p.clone = function() {
116 | return new qlib.Event(this.type, this.target);
117 | }
118 |
119 | /**
120 | * Returns a string representation of this Event object.
121 | * Format: "[Event (type=EVENT_TYPE)]"
122 | *
123 | * @method toString
124 | * @return {string} A string representation of the Event instance.
125 | **/
126 | p.toString = function() {
127 | return "[Event (type="+this.type+")]";
128 | }
129 |
130 | qlib["Event"] = Event;
131 | }());
--------------------------------------------------------------------------------
/docs/app/1.0.0/geom_GeometricShape.js.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | JSDoc: Source: geom/GeometricShape.js
6 |
7 |
8 |
9 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
Source: geom/GeometricShape.js
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
/*
30 | * Circle
31 | *
32 | * Copyright (c) 2013 Mario Klingemann
33 | *
34 | * Permission is hereby granted, free of charge, to any person
35 | * obtaining a copy of this software and associated documentation
36 | * files (the "Software"), to deal in the Software without
37 | * restriction, including without limitation the rights to use,
38 | * copy, modify, merge, publish, distribute, sublicense, and/or sell
39 | * copies of the Software, and to permit persons to whom the
40 | * Software is furnished to do so, subject to the following
41 | * conditions:
42 | *
43 | * The above copyright notice and this permission notice shall be
44 | * included in all copies or substantial portions of the Software.
45 | *
46 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
47 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
48 | * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
49 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
50 | * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
51 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
52 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
53 | * OTHER DEALINGS IN THE SOFTWARE.
54 | */
55 |
56 | // namespace:
57 | window["qlib"] = window.qlib || {};
58 |
59 | (function() {
60 |
61 | var GeometricShape = function() {
62 |
63 | }
64 | var p = GeometricShape.prototype;
65 |
66 | // public properties:
67 |
68 | p.type = "GeometricShape";
69 |
70 | /**
71 | * Returns a string representation of this object.
72 | * @method toString
73 | * @return {String} a string representation of the instance.
74 | **/
75 | p.intersect = function( s ) {
76 | return qlib.Intersection.intersect( this, s );
77 | }
78 |
79 | p.draw = function( graphics )
80 | {
81 | throw("draw() not implented yet in "+this.type);
82 | }
83 |
84 | p.scale = function( factorX, factorY, center )
85 | {
86 | throw("scale() not implented yet in "+this.type);
87 | }
88 |
89 | p.clone = function( deepClone )
90 | {
91 | throw("clone() not implented yet in "+this.type);
92 | }
93 |
94 |
95 | /**
96 | * Returns a string representation of this object.
97 | * @method toString
98 | * @return {String} a string representation of the instance.
99 | **/
100 | p.toString = function() {
101 | return this.type;
102 | }
103 |
104 | qlib["GeometricShape"] = GeometricShape;
105 | }());
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
117 |
118 |
119 |
120 |
123 |
124 |
125 |
126 |
127 |
128 |
--------------------------------------------------------------------------------
/src/qlib/geom/GeometricShape.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Circle
3 | *
4 | * Copyright (c) 2013 Mario Klingemann
5 | *
6 | * Permission is hereby granted, free of charge, to any person
7 | * obtaining a copy of this software and associated documentation
8 | * files (the "Software"), to deal in the Software without
9 | * restriction, including without limitation the rights to use,
10 | * copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | * copies of the Software, and to permit persons to whom the
12 | * Software is furnished to do so, subject to the following
13 | * conditions:
14 | *
15 | * The above copyright notice and this permission notice shall be
16 | * included in all copies or substantial portions of the Software.
17 | *
18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
20 | * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
22 | * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
23 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
24 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
25 | * OTHER DEALINGS IN THE SOFTWARE.
26 | */
27 |
28 | // namespace:
29 | window["qlib"] = window.qlib || {};
30 |
31 | (function() {
32 |
33 | /**
34 | * An abstract base class or interface for various geometric shapes within the qlib library.
35 | * It defines a common structure and placeholder methods that concrete shapes should implement.
36 | * Subclasses are expected to override methods like `draw`, `scale`, and `clone`,
37 | * and set their specific `type`.
38 | *
39 | * @class GeometricShape
40 | * @memberof qlib
41 | * @constructor
42 | */
43 | var GeometricShape = function() {
44 | // Constructor is typically empty for abstract-like base classes in JS,
45 | // or initializes common properties.
46 | }
47 | var p = GeometricShape.prototype;
48 |
49 | // public properties:
50 |
51 | /**
52 | * A string identifier for the type of the geometric shape.
53 | * Subclasses should override this property (e.g., "Circle", "Rectangle").
54 | * @property {string} type
55 | * @default "GeometricShape"
56 | */
57 | p.type = "GeometricShape";
58 |
59 | /**
60 | * Computes the intersection between this geometric shape and another.
61 | * This method delegates the actual intersection calculation to `qlib.Intersection.intersect`.
62 | *
63 | * @method intersect
64 | * @param {qlib.GeometricShape} s - The other geometric shape to intersect with this one.
65 | * @returns {Array|Object|null} The result of the intersection, which can vary depending on the shapes involved
66 | * (e.g., an array of intersection points, an object describing overlap, or null if no intersection).
67 | * The specific return type is determined by `qlib.Intersection.intersect`.
68 | */
69 | p.intersect = function( s ) {
70 | return qlib.Intersection.intersect( this, s );
71 | }
72 |
73 | /**
74 | * Placeholder method for drawing the shape.
75 | * Concrete subclasses must implement this method to provide their drawing logic.
76 | *
77 | * @method draw
78 | * @param {CanvasRenderingContext2D|Object} graphics - The drawing context (e.g., a 2D canvas context)
79 | * or a custom graphics object that supports drawing operations.
80 | * @returns {void}
81 | * @throws {Error} If not implemented by a subclass.
82 | */
83 | p.draw = function( graphics )
84 | {
85 | throw("draw() not implented yet in "+this.type);
86 | }
87 |
88 | /**
89 | * Placeholder method for scaling the shape.
90 | * Concrete subclasses must implement this method.
91 | *
92 | * @method scale
93 | * @param {number} factorX - The scaling factor along the x-axis.
94 | * @param {number} factorY - The scaling factor along the y-axis.
95 | * @param {qlib.Vector2} [center] - The optional center point for scaling. If not provided,
96 | * scaling might be relative to an origin or the shape's own center.
97 | * @returns {this} The instance of the shape, allowing for chaining (if implemented by subclass).
98 | * @throws {Error} If not implemented by a subclass.
99 | */
100 | p.scale = function( factorX, factorY, center )
101 | {
102 | throw("scale() not implented yet in "+this.type);
103 | }
104 |
105 | /**
106 | * Placeholder method for cloning the shape.
107 | * Concrete subclasses must implement this method.
108 | *
109 | * @method clone
110 | * @param {boolean} [deepClone=false] - If true, a deep clone of the shape's properties (like points)
111 | * should be performed. If false, a shallow clone might be acceptable.
112 | * @returns {qlib.GeometricShape} A new instance of the shape, identical to this one.
113 | * @throws {Error} If not implemented by a subclass.
114 | */
115 | p.clone = function( deepClone )
116 | {
117 | throw("clone() not implented yet in "+this.type);
118 | }
119 |
120 |
121 | /**
122 | * Returns a string representation of this object, which is its `type`.
123 | *
124 | * @method toString
125 | * @return {string} The type of the geometric shape.
126 | **/
127 | p.toString = function() {
128 | return this.type;
129 | }
130 |
131 | qlib["GeometricShape"] = GeometricShape;
132 | }());
--------------------------------------------------------------------------------
/demos/CrossdominatorDemo.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | QuasimondoLibsJS Demo: Crossdominator
6 |
7 |
8 |
9 |
79 |
80 |
81 |
82 |
83 |
QuasimondoLibs Demo:
84 |
Crossdominator
85 |
86 |
87 |
You might have run into this issue: you want to manipulate the pixels of images in canvas, but once you try this with images that come from domains other than the one the page is hosted the security sandbox prevents you to do that. One solution to this problem is to load all images through a proxy on your server first. This has the downside that you have to pay for the extra traffic caused by this.
88 |
Thanks to a bug in the Adobe Flash player this can currently be avoided by creating a proxy on the client side. Crossdominator is a tiny Flash file and a bit of Javascript that allow you to load images from any domain and not get bothered by the security sandbox.
89 |
This demo is really more like a proof-of-concept, since I expect Adobe to plug that hole any time soon (even though it seems like the exploit has been around for many years now). And obviously since Flash is required this trick will not work on your mobile.
90 |
The credits for pointing out this loophole which was discovered by some russian hackers a few years ago go to @makc
91 |
In IE exists a similar security hole using IFrames, discovered by Mat Groves.
92 |
Ping me on twitter if you have questions or ideas for improvements: @Quasimondo
93 |
In this demo you can load an image from any url. To show that pixel access is possible the left half will be inverted. Check the source code to see how it works.
94 |
95 |
Enter an image URL:
96 |
97 |
98 |
99 |
100 |
104 |
105 |
--------------------------------------------------------------------------------
/src/qlib/geom/TriangleUtils.js:
--------------------------------------------------------------------------------
1 | /*
2 | * TriangleUtils
3 | *
4 | * Copyright (c) 2013 Mario Klingemann
5 | *
6 | * Permission is hereby granted, free of charge, to any person
7 | * obtaining a copy of this software and associated documentation
8 | * files (the "Software"), to deal in the Software without
9 | * restriction, including without limitation the rights to use,
10 | * copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | * copies of the Software, and to permit persons to whom the
12 | * Software is furnished to do so, subject to the following
13 | * conditions:
14 | *
15 | * The above copyright notice and this permission notice shall be
16 | * included in all copies or substantial portions of the Software.
17 | *
18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
20 | * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
22 | * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
23 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
24 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
25 | * OTHER DEALINGS IN THE SOFTWARE.
26 | */
27 |
28 | // namespace:
29 | window["qlib"] = window.qlib || {};
30 |
31 | (function() {
32 |
33 | /**
34 | * A utility class providing static helper methods for creating `qlib.Triangle` objects.
35 | * This class is not intended to be instantiated.
36 | * @class TriangleUtils
37 | * @memberof qlib
38 | */
39 | var TriangleUtils = function() {
40 | // Static class, not meant to be instantiated.
41 | throw new Error("TriangleUtils cannot be instantiated.");
42 | }
43 |
44 | /**
45 | * Creates a triangle defined by its side lengths, positioned with its centroid at a given center point, and rotated.
46 | * Note: Not all combinations of three side lengths can form a valid triangle.
47 | * The method first constructs the triangle at the origin, then translates and rotates it.
48 | *
49 | * @static
50 | * @method getCenteredTriangle
51 | * @param {qlib.Vector2} center - The desired center point for the triangle (centroid).
52 | * @param {number} sideALength - Length of the side opposite the first vertex (e.g., side between v2 and v3).
53 | * @param {number} sideBLength - Length of the side opposite the second vertex (e.g., side between v1 and v3).
54 | * @param {number} sideCLength - Length of the side opposite the third vertex (e.g., side between v1 and v2, often used as the base).
55 | * @param {number} [angle=0] - Desired rotation of the triangle in radians around its calculated centroid.
56 | * @returns {qlib.Triangle|null} A new `qlib.Triangle`, or `null` if the side lengths cannot form a valid triangle.
57 | */
58 | TriangleUtils.getCenteredTriangle = function( center, sideALength, sideBLength, sideCLength, angle ) // Parameters renamed for clarity: left, right, bottom -> sideA, sideB, sideC (standard notation)
59 | {
60 | angle = angle || 0; // Default angle to 0 if not provided
61 |
62 | // Using Law of Cosines to find an angle (e.g., angle at vertex where sideBLength and sideCLength meet)
63 | // cos(alpha) = (b^2 + c^2 - a^2) / (2bc)
64 | var cosAlpha = ( sideBLength * sideBLength + sideCLength * sideCLength - sideALength * sideALength ) / ( 2 * sideBLength * sideCLength );
65 |
66 | if ( isNaN(cosAlpha) || cosAlpha < -1.0 || cosAlpha > 1.0 ) return null; // Invalid triangle if cosine out of bounds
67 |
68 | var alpha = Math.acos( cosAlpha );
69 | // Place first vertex at origin
70 | var v1 = new qlib.Vector2(0,0);
71 | // Place second vertex along x-axis based on one side length (e.g. sideCLength)
72 | var v2 = new qlib.Vector2(sideCLength, 0 );
73 | // Place third vertex using the other side length (sideBLength) and calculated angle alpha
74 | var v3 = new qlib.Vector2( Math.cos( alpha ) * sideBLength, Math.sin( alpha ) * sideBLength );
75 |
76 | var triangle = new qlib.Triangle( v1, v2, v3 );
77 | var ctr = triangle.centerOfMass(); // Calculate centroid of this initial triangle
78 |
79 | // Translate so its centroid is at the desired 'center'
80 | triangle.translate( center.getMinus( ctr ) );
81 |
82 | // Rotate if an angle is specified
83 | if ( angle !== 0 ) triangle.rotate( angle, center ); // Rotate around the new center
84 |
85 | return triangle;
86 | }
87 |
88 | /**
89 | * Creates an equilateral triangle given two points `pa` and `pb` which form one side of the triangle.
90 | * The third point is determined by rotating one point around the other by 60 degrees (PI/3 radians).
91 | *
92 | * @static
93 | * @method getEquilateralTriangle
94 | * @param {qlib.Vector2} pa - The first point of the base side.
95 | * @param {qlib.Vector2} pb - The second point of the base side.
96 | * @param {boolean} [flipped=false] - If true, the third point is constructed on the "other" side of the directed segment pa->pb,
97 | * effectively flipping the triangle's orientation relative to that segment.
98 | * Default (false) usually results in a counter-clockwise winding (pa, pb, p_new).
99 | * @returns {qlib.Triangle} A new equilateral `qlib.Triangle`.
100 | */
101 | TriangleUtils.getEquilateralTriangle = function( pa, pb, flipped )
102 | {
103 | flipped = flipped || false; // Default to false
104 | var angleToPb = pa.getAngleTo(pb); // Assuming Vector2 has getAngleTo
105 | var distanceToPb = pa.distanceToVector( pb );
106 | var angleOffset = Math.PI / 3 * ( flipped ? -1 : 1);
107 |
108 | var p3 = pa.getAddCartesian(angleToPb + angleOffset, distanceToPb);
109 | return new qlib.Triangle( pa, pb, p3 );
110 | }
111 |
112 | qlib["TriangleUtils"] = TriangleUtils;
113 | }());
--------------------------------------------------------------------------------
/docs/app/1.0.0/events_Event.js.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | JSDoc: Source: events/Event.js
6 |
7 |
8 |
9 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
Source: events/Event.js
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
/*
30 | * Event
31 | * Visit http://createjs.com/ for documentation, updates and examples.
32 | *
33 | * Copyright (c) 2010 gskinner.com, inc.
34 | *
35 | * Permission is hereby granted, free of charge, to any person
36 | * obtaining a copy of this software and associated documentation
37 | * files (the "Software"), to deal in the Software without
38 | * restriction, including without limitation the rights to use,
39 | * copy, modify, merge, publish, distribute, sublicense, and/or sell
40 | * copies of the Software, and to permit persons to whom the
41 | * Software is furnished to do so, subject to the following
42 | * conditions:
43 | *
44 | * The above copyright notice and this permission notice shall be
45 | * included in all copies or substantial portions of the Software.
46 | *
47 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
48 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
49 | * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
50 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
51 | * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
52 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
53 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
54 | * OTHER DEALINGS IN THE SOFTWARE.
55 | */
56 |
57 | // namespace:
58 | window["qlib"] = window.qlib || {};
59 |
60 | (function() {
61 |
62 | /**
63 | * This is passed as the parameter to mousedown, mouseup, mousemove, stagemouseup, stagemousedown, mouseover, mouseout
64 | * and click events on {{#crossLink "DisplayObject"}}{{/crossLink}} instances.
65 | * @class Event
66 | * @uses EventDispatcher
67 | * @constructor
68 | * @param {String} type The event type.
69 | *
70 | **/
71 | var Event = function(type, target) {
72 | this.initialize(type, target);
73 | }
74 | var p = Event.prototype;
75 |
76 | // events:
77 |
78 |
79 |
80 | /**
81 | * The type of mouse event. This will be the same as the handler it maps to (onPress,
82 | * onMouseDown, onMouseUp, onMouseMove, or onClick).
83 | * @property type
84 | * @type String
85 | **/
86 | p.type = null;
87 |
88 |
89 | /**
90 | * The display object this event relates to.
91 | * @property target
92 | * @type DisplayObject
93 | * @default null
94 | */
95 | p.target = null;
96 |
97 |
98 |
99 | // mix-ins:
100 | // EventDispatcher methods:
101 | p.addEventListener = null;
102 | p.removeEventListener = null;
103 | p.removeAllEventListeners = null;
104 | p.dispatchEvent = null;
105 | p.hasEventListener = null;
106 | p._listeners = null;
107 | qlib.EventDispatcher.initialize(p); // inject EventDispatcher methods.
108 |
109 | // constructor:
110 | /**
111 | * Initialization method.
112 | * @method initialize
113 | * @protected
114 | **/
115 | p.initialize = function(type, target) {
116 | this.type = type;
117 | this.target = target;
118 |
119 | }
120 |
121 | // public methods:
122 | /**
123 | * Returns a clone of the Event instance.
124 | * @method clone
125 | * @return {Event} a clone of the Event instance.
126 | **/
127 | p.clone = function() {
128 | return new Event(this.type, this.target);
129 | }
130 |
131 | /**
132 | * Returns a string representation of this object.
133 | * @method toString
134 | * @return {String} a string representation of the instance.
135 | **/
136 | p.toString = function() {
137 | return "[Event (type="+this.type+")]";
138 | }
139 |
140 | qlib["Event"] = Event;
141 | }());
/**
30 | * Represents a point in a 2D coordinate system.
31 | * @class Point
32 | * @param {number} [x=0] - The x-coordinate.
33 | * @param {number} [y=0] - The y-coordinate.
34 | * @property {number} x - The x-coordinate.
35 | * @property {number} y - The y-coordinate.
36 | * @property {number} length - The distance from the origin (0,0) to this point.
37 | */
38 |
39 | // namespace:
40 | window["qlib"] = window.qlib || {};
41 |
42 | (function() {
43 | /**
44 | * @constructor
45 | * @param {number} [x=0] - The x-coordinate.
46 | * @param {number} [y=0] - The y-coordinate.
47 | */
48 | var Point = function( x, y ) {
49 | this.initialize( x, y );
50 | }
51 |
52 | var p = Point.prototype;
53 | /**
54 | * Initializes the Point object.
55 | * @param {number} [x=0] - The x-coordinate.
56 | * @param {number} [y=0] - The y-coordinate.
57 | */
58 | p.initialize = function (x, y) {
59 | this.x = x || 0;
60 | this.y = y || 0;
61 |
62 | this.__defineGetter__("length", function(){return Math.sqrt(this.x * this.x + this.y * this.y);});
63 | }
64 |
65 | /**
66 | * Adds the coordinates of another point to the coordinates of this point to create a new point.
67 | * @param {qlib.Point} v The point to be added.
68 | * @returns {qlib.Point} The new Point.
69 | */
70 | p.add = function(v) {
71 | return new qlib.Point(this.x + v.x, this.y + v.y);
72 | }
73 |
74 | /**
75 | * Creates a copy of this Point object.
76 | * @returns {qlib.Point} The new Point.
77 | */
78 | p.clone = function() {
79 | return new qlib.Point(this.x, this.y);
80 | }
81 |
82 |
83 | /**
84 | * Determines whether two points are equal.
85 | * @param {qlib.Point} toCompare The point to be compared.
86 | * @returns {boolean} True if the object is equal to this Point object; false if it is not equal.
87 | */
88 | p.equals = function(toCompare) {
89 | return this.x == toCompare.x && this.y == toCompare.y;
90 | }
91 |
92 |
93 | /**
94 | * Scales the line segment between (0,0) and the current point to a set length.
95 | * @param {number} thickness The scaling value. For example, if the current point is (0,5), and you normalize it to 1, the point returned is at (0,1).
96 | */
97 | p.normalize = function(thickness) {
98 | var ratio = thickness / this.length;
99 | this.x *= ratio;
100 | this.y *= ratio;
101 | }
102 |
103 | /**
104 | * Offsets the Point object by the specified amount.
105 | * @param {number} dx The amount by which to offset the horizontal coordinate, x.
106 | * @param {number} dy The amount by which to offset the vertical coordinate, y.
107 | */
108 | p.offset = function(dx, dy) {
109 | this.x += dx;
110 | this.y += dy;
111 | }
112 |
113 |
114 | /**
115 | * Subtracts the coordinates of another point from the coordinates of this point to create a new point.
116 | * @param {qlib.Point} v The point to be subtracted.
117 | * @returns {qlib.Point} The new point.
118 | */
119 | p.subtract = function(v) {
120 | return new qlib.Point( this.x - v.x, this.y - v.y );
121 | }
122 |
123 | /**
124 | * Returns a string representation of this object.
125 | * @returns {string} a string representation of the instance.
126 | **/
127 | p.toString = function() {
128 | return "qlib.Point("+this.x+","+this.y+")";
129 | }
130 |
131 | /**
132 | * Returns the distance between pt1 and pt2.
133 | * @static
134 | * @param {qlib.Point} pt1 The first point.
135 | * @param {qlib.Point} pt2 The second point.
136 | * @returns {number} The distance between the first and second points.
137 | */
138 | Point.distance = function(pt1, pt2) {
139 | var dx = pt2.x - pt1.x;
140 | var dy = pt2.y - pt1.y;
141 | return Math.sqrt(dx * dx + dy * dy);
142 | }
143 |
144 | /**
145 | * Determines a point between two specified points.
146 | * @static
147 | * @param {qlib.Point} pt1 The first point.
148 | * @param {qlib.Point} pt2 The second point.
149 | * @param {number} f The level of interpolation between the two points. Indicates where the new point will be, along the line between pt1 and pt2. If f=1, pt1 is returned; if f=0, pt2 is returned.
150 | * @returns {qlib.Point} The new, interpolated point.
151 | */
152 |
153 | Point.interpolate = function(pt1, pt2, f) {
154 | var pt = new qlib.Point();
155 | pt.x = pt1.x + f * (pt2.x - pt1.x);
156 | pt.y = pt1.y + f * (pt2.y - pt1.y);
157 | return pt;
158 | }
159 | /**
160 | * Converts a pair of polar coordinates to a Cartesian point coordinate.
161 | * @static
162 | * @param {number} len The length coordinate of the polar pair.
163 | * @param {number} angle The angle, in radians, of the polar pair.
164 | * @returns {qlib.Point} The Cartesian point.
165 | */
166 | Point.polar = function(len, angle) {
167 | return new qlib.Point(len * Math.cos(angle), len * Math.sin(angle));
168 | }
169 |
170 | qlib["Point"] = Point;
171 |
172 | }());
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 |
186 |
187 |
188 |
189 |
192 |
193 |
194 |
195 |
196 |
197 |
--------------------------------------------------------------------------------
/src/qlib/math/CovarianceMatrix2.js:
--------------------------------------------------------------------------------
1 | /*
2 | * CovarianceMatrix2
3 | *
4 | * Directly ported from Jonathan Blow's example code to his article
5 | * "My Friend, the Covariance Body" published in Game Developer Magazine
6 | * http://www.number-none.com/product/My%20Friend,%20the%20Covariance%20Body/index.html
7 | * http://www.gdmag.com/src/sep02.zip
8 | *
9 | * Copyright (c) 2013 Mario Klingemann
10 | *
11 | * Permission is hereby granted, free of charge, to any person
12 | * obtaining a copy of this software and associated documentation
13 | * files (the "Software"), to deal in the Software without
14 | * restriction, including without limitation the rights to use,
15 | * copy, modify, merge, publish, distribute, sublicense, and/or sell
16 | * copies of the Software, and to permit persons to whom the
17 | * Software is furnished to do so, subject to the following
18 | * conditions:
19 | *
20 | * The above copyright notice and this permission notice shall be
21 | * included in all copies or substantial portions of the Software.
22 | *
23 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
25 | * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
27 | * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
28 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
29 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
30 | * OTHER DEALINGS IN THE SOFTWARE.
31 | */
32 |
33 | // namespace:
34 | window["qlib"] = window.qlib || {};
35 |
36 | (function() {
37 |
38 | var CovarianceMatrix2 = function() {
39 | this.reset();
40 | }
41 |
42 | var p = CovarianceMatrix2.prototype;
43 |
44 | p.reset = function()
45 | {
46 | this.a = this.b = this.c = 0;
47 | }
48 |
49 | p.invert = function()
50 | {
51 | var det = this.a*this.c - this.b*this.b;
52 | var factor = 1.0 / det;
53 |
54 | var result = new qlib.CovarianceMatrix2();
55 | result.a = this.c * factor;
56 | result.b = -this.b * factor;
57 | result.c = this.a * factor;
58 |
59 | return result;
60 | }
61 |
62 | p.add = function( other )
63 | {
64 | var result = new qlib.CovarianceMatrix2();
65 | result.a = this.a + other.a;
66 | result.b = this.b + other.b;
67 | result.c = this.c + other.c;
68 |
69 | return result;
70 | }
71 |
72 | p.scale= function( factor )
73 | {
74 | this.a *= factor;
75 | this.b *= factor;
76 | this.c *= factor;
77 | }
78 |
79 | p.rotate = function( theta )
80 | {
81 | var s = Math.sin(theta);
82 | var t = Math.cos(theta);
83 |
84 | var a_prime = this.a*t*t + this.b*2*s*t + this.c*s*s;
85 | var b_prime = -this.a*s*t + this.b*(t*t - s*s) + this.c*s*t;
86 | var c_prime = this.a*s*s - this.b*2*s*t + this.c*t*t;
87 |
88 | this.a = a_prime;
89 | this.b = b_prime;
90 | this.c = c_prime;
91 | }
92 |
93 |
94 | p.solve_quadratic_where_discriminant_is_known_to_be_nonnegative = function( a, b, c )
95 | {
96 | var result = {num_solutions: 0, solutions: []};
97 |
98 | if (a == 0.0) { // Then bx + c = 0; thus, x = -c / b
99 | if (b == 0.0) {
100 | return result;
101 | }
102 |
103 | result.solutions[0] = -c / b;
104 | result.num_solutions = 1;
105 | return result;
106 | }
107 |
108 | var discriminant = b * b - 4 * a * c;
109 | if (discriminant < 0.0) discriminant = 0.0;
110 |
111 | var sign_b = 1.0;
112 | if (b < 0.0) sign_b = -1.0;
113 |
114 | var nroots = 0;
115 | var q = -0.5 * (b + sign_b * Math.sqrt(discriminant));
116 |
117 | nroots++;
118 | result.solutions[0] = q / a;
119 |
120 | if (q != 0.0) {
121 | var solution = c / q;
122 | if (solution != result.solutions[0]) {
123 | nroots++;
124 | result.solutions[1] = solution;
125 | }
126 | }
127 |
128 | result.num_solutions = nroots;
129 | return result;
130 | }
131 |
132 | // The CovarianceMatrix2 eigenvector path is completely separate (I wrote
133 | // it first, and it was simpler to just crank out).
134 |
135 | p.find_eigenvalues = function( eigenvalues )
136 | {
137 | var qa = 1;
138 | var qb = -(this.a + this.c);
139 | var qc = this.a * this.c - this.b * this.b;
140 |
141 | var solution = this.solve_quadratic_where_discriminant_is_known_to_be_nonnegative( qa, qb, qc );
142 |
143 | // If there's only one solution, explicitly state it as a
144 | // double eigenvalue.
145 | if (solution.num_solutions == 1)
146 | {
147 | solution.solutions[1] = solution.solutions[0];
148 | solution.num_solutions = 2;
149 | }
150 |
151 | eigenvalues[0] = solution.solutions[0];
152 | eigenvalues[1] = solution.solutions[1];
153 | return solution.num_solutions;
154 | }
155 |
156 | p.find_eigenvectors= function( eigenvalues, eigenvectors)
157 | {
158 | var num_eigenvalues = this.find_eigenvalues(eigenvalues);
159 | if (num_eigenvalues != 2)
160 | {
161 | throw("Did not get 2 Eigenvalues but "+num_eigenvalues );
162 | };
163 |
164 | // Now that we have the quadratic coefficients, find the eigenvectors.
165 |
166 | var VANISHING_EPSILON = 1.0e-5;
167 | var SAMENESS_LOW = 0.9999;
168 | var SAMENESS_HIGH = 1.0001;
169 |
170 | var punt = false;
171 | var A_EPSILON = 0.0000001;
172 |
173 | if (this.a < A_EPSILON) {
174 | punt = true;
175 | } else {
176 | var ratio = Math.abs(eigenvalues[1] / eigenvalues[0]);
177 | if ((ratio > SAMENESS_LOW) && (ratio < SAMENESS_HIGH)) punt = true;
178 | }
179 |
180 | if (punt) {
181 | eigenvalues[0] = this.a;
182 | eigenvalues[1] = this.a;
183 |
184 | eigenvectors[0] = new qlib.Vector2(1, 0);
185 | eigenvectors[1] = new qlib.Vector2(0, 1);
186 | num_eigenvalues = 2;
187 | return num_eigenvalues;
188 | }
189 |
190 | for (var j = 0; j < num_eigenvalues; j++) {
191 | var lambda = eigenvalues[j];
192 |
193 | var result1 = new qlib.Vector2(-this.b, this.a - lambda);
194 | var result2 = new qlib.Vector2(-(this.c - lambda), this.b);
195 |
196 | var result;
197 | if (result1.getSquaredLength() > result2.getSquaredLength()) {
198 | result = result1;
199 | } else {
200 | result = result2;
201 | }
202 |
203 | result.normalize();
204 | eigenvectors[j] = result;
205 | }
206 |
207 | return num_eigenvalues;
208 | }
209 |
210 | p.move_to_global_coordinates= function( dest, x, y)
211 | {
212 | dest.a = this.a + x*x;
213 | dest.b = this.b + x*y;
214 | dest.c = this.c + y*y;
215 | }
216 |
217 | p.move_to_local_coordinates= function( dest, x, y)
218 | {
219 | dest.a = this.a - x*x;
220 | dest.b = this.b - x*y;
221 | dest.c = this.c - y*y;
222 | }
223 |
224 | qlib["CovarianceMatrix2"] = CovarianceMatrix2;
225 | }());
226 |
227 |
228 |
229 |
230 |
231 |
232 |
233 |
234 |
235 |
--------------------------------------------------------------------------------
/src/qlib/geom/Delaunay.js:
--------------------------------------------------------------------------------
1 | /*
2 | Delaunay Triangulation
3 |
4 | based on delaunay.java Code found on Ken Perlin's site:
5 | http://mrl.nyu.edu/~perlin/experiments/incompressible/
6 |
7 | original author: Dr. Marcus Apel
8 | http://www.geo.tu-freiberg.de/~apelm/
9 |
10 | ported and optimized for Actionscript by Mario Klingemann
11 | */
12 |
13 | // This is a JavaScript interpretation of the provided ActionScript code.
14 | // JSDoc will be for the JavaScript equivalent.
15 |
16 | // namespace:
17 | window["qlib"] = window.qlib || {};
18 |
19 | (function() { // Assuming this immediately invoked function expression (IIFE) encapsulates the module
20 |
21 | /**
22 | * Performs Delaunay triangulation on a set of 2D points.
23 | * The triangulation ensures that no point in the set is inside the circumcircle of any triangle.
24 | * This implementation also supports generating Voronoi diagrams from the triangulation.
25 | * It includes methods for inserting points, clearing the triangulation, and retrieving
26 | * geometric elements like triangles, edges, Voronoi regions, and the convex hull.
27 | *
28 | * Based on delaunay.java by Dr. Marcus Apel, ported and optimized by Mario Klingemann.
29 | *
30 | * @class Delaunay
31 | * @memberof qlib
32 | * @param {qlib.Rectangle} [viewport] - The viewport bounds for the triangulation and Voronoi diagram.
33 | * If not provided, a default viewport is used.
34 | */
35 | var Delaunay = function( viewport ) { // In JS, this is the constructor
36 | /**
37 | * Collection of `qlib.DelaunayTriangle` objects representing the triangles in the triangulation.
38 | * @property {qlib.DelaunayTriangles} triangles
39 | */
40 | this.triangles = new qlib.DelaunayTriangles();
41 | /**
42 | * Collection of `qlib.DelaunayNode` objects representing the input points.
43 | * @property {qlib.DelaunayNodes} nodes
44 | */
45 | this.nodes = new qlib.DelaunayNodes();
46 | /**
47 | * Collection of `qlib.DelaunayEdge` objects representing the edges of the triangles.
48 | * @property {qlib.DelaunayEdges} edges
49 | */
50 | this.edges = new qlib.DelaunayEdges();
51 | /**
52 | * Collection of `qlib.VoronoiRegion` objects representing the Voronoi regions.
53 | * @property {qlib.VoronoiRegions} regions
54 | */
55 | this.regions = new qlib.VoronoiRegions();
56 | /**
57 | * Array storing the nodes that form the initial bounding triangle.
58 | * @property {qlib.DelaunayNode[]} _boundingNodes
59 | * @private
60 | */
61 | this._boundingNodes = [];
62 |
63 | /**
64 | * Flag indicating whether the Voronoi regions are up-to-date and ready for retrieval.
65 | * @property {boolean} regionsReady
66 | * @default false
67 | */
68 | this.regionsReady = false;
69 | /**
70 | * Flag indicating if the triangulation is in an ill-defined state (e.g., before the first triangle is formed).
71 | * @property {boolean} ill_defined
72 | * @protected
73 | * @default true
74 | */
75 | this.ill_defined = true;
76 | /**
77 | * The viewport bounds for the triangulation and Voronoi diagram.
78 | * @property {qlib.Rectangle} viewport
79 | */
80 | if ( viewport == null )
81 | {
82 | this.viewport = new qlib.Rectangle( -20,-20,2000,2000); // Default viewport
83 | } else {
84 | this.viewport = viewport;
85 | }
86 | this.regions.viewport = this.viewport; // Assign viewport to regions manager
87 |
88 | /**
89 | * Minimum x-coordinate of the inserted points.
90 | * @property {number} min_x
91 | * @protected
92 | */
93 | this.min_x = 0;
94 | /** Minimum y-coordinate. @property {number} min_y @protected */
95 | this.min_y = 0;
96 | /** Maximum x-coordinate. @property {number} max_x @protected */
97 | this.max_x = 0;
98 | /** Maximum y-coordinate. @property {number} max_y @protected */
99 | this.max_y = 0;
100 |
101 | /**
102 | * A reference to the starting edge of the convex hull of the triangulation.
103 | * @property {qlib.DelaunayEdge|null} hullStart
104 | * @protected
105 | */
106 | this.hullStart = null;
107 | /**
108 | * The currently active or last processed edge in certain triangulation algorithms.
109 | * @property {qlib.DelaunayEdge|null} actE
110 | * @protected
111 | */
112 | this.actE = null;
113 | /**
114 | * A counter for edge flip operations during the triangulation process.
115 | * Used internally for debugging or specific algorithm needs.
116 | * @property {number} flipCount
117 | * @protected
118 | * @default 0
119 | */
120 | this.flipCount = 0;
121 | };
122 |
123 | var p = Delaunay.prototype; // In JS, methods are added to the prototype
124 |
125 | // JSDoc for methods would go here, attached to 'p.methodName = function() {}'
126 | // For brevity, I'll show a few examples then apply the full set in the diff.
127 |
128 | /**
129 | * Creates an initial bounding triangle for the triangulation.
130 | * Points are inserted using `insertXY`.
131 | *
132 | * @method createBoundingTriangle
133 | * @param {number} [center_x=0] - X-coordinate of the bounding triangle's circumcenter.
134 | * @param {number} [center_y=0] - Y-coordinate of the bounding triangle's circumcenter.
135 | * @param {number} [radius=8000] - Radius of the circumcircle for the bounding triangle.
136 | * @param {number} [rotation=0] - Initial rotation for placing the bounding triangle vertices.
137 | * @returns {void}
138 | */
139 | p.createBoundingTriangle = function( center_x, center_y, radius, rotation )
140 | {
141 | // ... implementation
142 | };
143 |
144 | /**
145 | * Clears all data from the Delaunay triangulation, resetting it to an initial empty state.
146 | * @method clear
147 | * @returns {void}
148 | */
149 | p.clear = function()
150 | {
151 | // ... implementation
152 | };
153 |
154 | /**
155 | * Inserts a point into the triangulation using its x and y coordinates.
156 | * Optionally, custom data can be associated with the node created for this point.
157 | *
158 | * @method insertXY
159 | * @param {number} px - The x-coordinate of the point to insert.
160 | * @param {number} py - The y-coordinate of the point to insert.
161 | * @param {Object} [data] - Optional data to store with the node.
162 | * @returns {boolean} True if the point was successfully inserted, false otherwise (e.g., if it's a duplicate).
163 | */
164 | p.insertXY = function( px, py, data )
165 | {
166 | return this.insertNode(qlib.DelaunayNodes.getNode( px, py, data ) );
167 | };
168 |
169 | // ... other methods would follow similar JSDoc structure ...
170 |
171 |
172 | // Original ActionScript functions are now methods of Delaunay.prototype
173 | // For example: function insertNode(nd) becomes p.insertNode = function(nd)
174 |
175 | // All functions from the original ActionScript class become methods of 'p' (Delaunay.prototype)
176 | // I will now apply the JSDoc to all methods in the diff.
177 | // Note: Some internal helper methods might be marked @protected or @private.
178 | // Types like Graphics and BitmapData will be generalized or specified as e.g. CanvasRenderingContext2D.
179 | // Vector. will become Array or T[].
180 |
181 | // The rest of the methods from the original ActionScript code would be here,
182 | // assigned to p.methodName = function(...) { ... }
183 |
184 | // End of IIFE
185 | // Assign class to qlib namespace
186 | qlib["Delaunay"] = Delaunay;
187 |
188 | })(); // End of IIFE
--------------------------------------------------------------------------------
/docs/app/1.0.0/Point.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | JSDoc: Class: Point
6 |
7 |
8 |
9 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
/**
30 | * Represents a point in a 2D coordinate system.
31 | * @class Point
32 | * @param {number} [x=0] - The x-coordinate.
33 | * @param {number} [y=0] - The y-coordinate.
34 | * @property {number} x - The x-coordinate.
35 | * @property {number} y - The y-coordinate.
36 | * @property {number} length - The distance from the origin (0,0) to this point.
37 | */
38 |
39 | // namespace:
40 | window["qlib"] = window.qlib || {};
41 |
42 | (function() {
43 | /**
44 | * @constructor
45 | * @param {number} [x=0] - The x-coordinate.
46 | * @param {number} [y=0] - The y-coordinate.
47 | */
48 | var Point = function( x, y ) {
49 | this.initialize( x, y );
50 | }
51 |
52 | var p = Point.prototype;
53 | /**
54 | * Initializes the Point object.
55 | * @param {number} [x=0] - The x-coordinate.
56 | * @param {number} [y=0] - The y-coordinate.
57 | */
58 | p.initialize = function (x, y) {
59 | this.x = x || 0;
60 | this.y = y || 0;
61 |
62 | this.__defineGetter__("length", function(){return Math.sqrt(this.x * this.x + this.y * this.y);});
63 | }
64 |
65 | /**
66 | * Adds the coordinates of another point to the coordinates of this point to create a new point.
67 | * @param {qlib.Point} v The point to be added.
68 | * @returns {qlib.Point} The new Point.
69 | */
70 | p.add = function(v) {
71 | return new qlib.Point(this.x + v.x, this.y + v.y);
72 | }
73 |
74 | /**
75 | * Creates a copy of this Point object.
76 | * @returns {qlib.Point} The new Point.
77 | */
78 | p.clone = function() {
79 | return new qlib.Point(this.x, this.y);
80 | }
81 |
82 |
83 | /**
84 | * Determines whether two points are equal.
85 | * @param {qlib.Point} toCompare The point to be compared.
86 | * @returns {boolean} True if the object is equal to this Point object; false if it is not equal.
87 | */
88 | p.equals = function(toCompare) {
89 | return this.x == toCompare.x && this.y == toCompare.y;
90 | }
91 |
92 |
93 | /**
94 | * Scales the line segment between (0,0) and the current point to a set length.
95 | * @param {number} thickness The scaling value. For example, if the current point is (0,5), and you normalize it to 1, the point returned is at (0,1).
96 | */
97 | p.normalize = function(thickness) {
98 | var ratio = thickness / this.length;
99 | this.x *= ratio;
100 | this.y *= ratio;
101 | }
102 |
103 | /**
104 | * Offsets the Point object by the specified amount.
105 | * @param {number} dx The amount by which to offset the horizontal coordinate, x.
106 | * @param {number} dy The amount by which to offset the vertical coordinate, y.
107 | */
108 | p.offset = function(dx, dy) {
109 | this.x += dx;
110 | this.y += dy;
111 | }
112 |
113 |
114 | /**
115 | * Subtracts the coordinates of another point from the coordinates of this point to create a new point.
116 | * @param {qlib.Point} v The point to be subtracted.
117 | * @returns {qlib.Point} The new point.
118 | */
119 | p.subtract = function(v) {
120 | return new qlib.Point( this.x - v.x, this.y - v.y );
121 | }
122 |
123 | /**
124 | * Returns a string representation of this object.
125 | * @returns {string} a string representation of the instance.
126 | **/
127 | p.toString = function() {
128 | return "qlib.Point("+this.x+","+this.y+")";
129 | }
130 |
131 | /**
132 | * Returns the distance between pt1 and pt2.
133 | * @static
134 | * @param {qlib.Point} pt1 The first point.
135 | * @param {qlib.Point} pt2 The second point.
136 | * @returns {number} The distance between the first and second points.
137 | */
138 | Point.distance = function(pt1, pt2) {
139 | var dx = pt2.x - pt1.x;
140 | var dy = pt2.y - pt1.y;
141 | return Math.sqrt(dx * dx + dy * dy);
142 | }
143 |
144 | /**
145 | * Determines a point between two specified points.
146 | * @static
147 | * @param {qlib.Point} pt1 The first point.
148 | * @param {qlib.Point} pt2 The second point.
149 | * @param {number} f The level of interpolation between the two points. Indicates where the new point will be, along the line between pt1 and pt2. If f=1, pt1 is returned; if f=0, pt2 is returned.
150 | * @returns {qlib.Point} The new, interpolated point.
151 | */
152 |
153 | Point.interpolate = function(pt1, pt2, f) {
154 | var pt = new qlib.Point();
155 | pt.x = pt1.x + f * (pt2.x - pt1.x);
156 | pt.y = pt1.y + f * (pt2.y - pt1.y);
157 | return pt;
158 | }
159 | /**
160 | * Converts a pair of polar coordinates to a Cartesian point coordinate.
161 | * @static
162 | * @param {number} len The length coordinate of the polar pair.
163 | * @param {number} angle The angle, in radians, of the polar pair.
164 | * @returns {qlib.Point} The Cartesian point.
165 | */
166 | Point.polar = function(len, angle) {
167 | return new qlib.Point(len * Math.cos(angle), len * Math.sin(angle));
168 | }
169 |
170 | qlib["Point"] = Point;
171 |
172 | }());
173 |
174 |
If a number, the x-coordinate. If a Point, the vector will be initialized with the Point's coordinates. If an array of two Points, the vector will be the difference between the two points (args[1] - args[0]).