diff options
Diffstat (limited to 'js/lib')
-rwxr-xr-x | js/lib/geom/sub-path.js | 940 |
1 files changed, 130 insertions, 810 deletions
diff --git a/js/lib/geom/sub-path.js b/js/lib/geom/sub-path.js index 765316b1..761391b7 100755 --- a/js/lib/geom/sub-path.js +++ b/js/lib/geom/sub-path.js | |||
@@ -11,30 +11,6 @@ var GeomObj = require("js/lib/geom/geom-obj").GeomObj; | |||
11 | var AnchorPoint = require("js/lib/geom/anchor-point").AnchorPoint; | 11 | var AnchorPoint = require("js/lib/geom/anchor-point").AnchorPoint; |
12 | var MaterialsModel = require("js/models/materials-model").MaterialsModel; | 12 | var MaterialsModel = require("js/models/materials-model").MaterialsModel; |
13 | 13 | ||
14 | // TODO Those function do not seems to be used. We should remove them | ||
15 | /* | ||
16 | function SubpathOffsetPoint(pos, mapPos) { | ||
17 | this.Pos = [pos[0],pos[1],pos[2]]; | ||
18 | this.CurveMapPos = [mapPos[0], mapPos[1], mapPos[2]]; | ||
19 | } | ||
20 | |||
21 | function SubpathOffsetTriangle(v0, v1, v2) { | ||
22 | this.v0 = v0; | ||
23 | this.v1 = v1; | ||
24 | this.v2 = v2; | ||
25 | this.n = [0,0,1]; //replace with the actual cross product later | ||
26 | } | ||
27 | |||
28 | function sortNumberAscending(a,b){ | ||
29 | return a-b; | ||
30 | } | ||
31 | function sortNumberDescending(a,b){ | ||
32 | return b-a; | ||
33 | } | ||
34 | function SegmentIntersections(){ | ||
35 | this.paramArray = []; | ||
36 | } | ||
37 | */ | ||
38 | /////////////////////////////////////////////////////////////////////// | 14 | /////////////////////////////////////////////////////////////////////// |
39 | // Class GLSubpath | 15 | // Class GLSubpath |
40 | // representation a sequence of cubic bezier curves. | 16 | // representation a sequence of cubic bezier curves. |
@@ -45,60 +21,44 @@ var GLSubpath = function GLSubpath() { | |||
45 | /////////////////////////////////////////////////// | 21 | /////////////////////////////////////////////////// |
46 | // Instance variables | 22 | // Instance variables |
47 | /////////////////////////////////////////////////// | 23 | /////////////////////////////////////////////////// |
24 | |||
25 | // NOTE: | ||
26 | // This class contains functionality to store piecewise cubic bezier paths. | ||
27 | // The coordinates of the paths are always in local, canvas space. | ||
28 | // That is, the Z coordinate can be ignored (for now), and the paths are essentially in 2D. | ||
29 | // All coordinates of the '_Samples' should lie within [0,0] and [width, height], | ||
30 | // where width and height refer to the dimensions of the canvas for this path. | ||
31 | // Whenever the the canvas dimensions change, the coordinates of the anchor points | ||
32 | // and _Samples must be re-computed. | ||
33 | |||
48 | this._Anchors = []; | 34 | this._Anchors = []; |
49 | this._BBoxMin = [0, 0, 0]; | 35 | this._BBoxMin = [0, 0, 0]; |
50 | this._BBoxMax = [0, 0, 0]; | 36 | this._BBoxMax = [0, 0, 0]; |
51 | this._isClosed = false; | 37 | this._isClosed = false; |
52 | 38 | ||
53 | this._samples = []; //polyline representation of this curve in stage world space | 39 | this._Samples = []; //polyline representation of this curve in canvas space |
54 | this._sampleParam = []; //parametric distance of samples, within [0, N], where N is # of Bezier curves (=# of anchor points if closed, =#anchor pts -1 if open) | 40 | this._sampleParam = []; //parametric distance of samples, within [0, N], where N is # of Bezier curves (=# of anchor points if closed, =#anchor pts -1 if open) |
55 | this._anchorSampleIndex = []; //index within _samples corresponding to anchor points | 41 | this._anchorSampleIndex = []; //index within _Samples corresponding to anchor points |
56 | 42 | ||
57 | this._LocalPoints = []; //polyline representation of this curve in canvas space | 43 | //initially set the _dirty bit so we will re-construct _Anchors and _Samples |
58 | this._LocalBBoxMin = [0,0,0]; //bbox min point of _LocalPoints | ||
59 | this._LocalBBoxMax = [0,0,0]; //bbox max point of _LocalPoints | ||
60 | this._AnchorLocalCoords = []; //local coords for all the anchor points , stored as a triplet of 3D vectors (prev, curr, next, in order) | ||
61 | this._UnprojectedAnchors = []; | ||
62 | |||
63 | //initially set the _dirty bit so we will construct samples | ||
64 | this._dirty = true; | 44 | this._dirty = true; |
65 | 45 | ||
66 | //initially set the local dirty bit so we will construct local coordinates | 46 | //the top left location of this subpath's canvas in screen space (used to identify cases when location changes) |
67 | this._isLocalDirty = true; | ||
68 | |||
69 | //initially set the local dirty bit for the anchors so we will construct local coordinates | ||
70 | this._isAnchorLocalDirty = true; | ||
71 | |||
72 | //whether or not to use the canvas drawing to stroke/fill | ||
73 | this._useCanvasDrawing = true; | ||
74 | |||
75 | //the canvas that will draw this subpath | ||
76 | this._canvas = null; | ||
77 | |||
78 | //the top left location of this subpath's canvas in screen space | ||
79 | this._canvasLeft = 0; | 47 | this._canvasLeft = 0; |
80 | this._canvasTop = 0; | 48 | this._canvasTop = 0; |
81 | 49 | ||
82 | //stroke information | 50 | //stroke information |
83 | this._strokeWidth = 1.0; | 51 | this._strokeWidth = 1.0; |
84 | this._strokeColor = [0.4, 0.4, 0.4, 1.0]; | 52 | this._strokeColor = [0.4, 0.4, 0.4, 1.0]; |
85 | this._strokeMaterial = null | ||
86 | this._strokeStyle = "Solid"; | ||
87 | this._materialAmbient = [0.2, 0.2, 0.2, 1.0]; | ||
88 | this._materialDiffuse = [0.4, 0.4, 0.4, 1.0]; | ||
89 | this._materialSpecular = [0.4, 0.4, 0.4, 1.0]; | ||
90 | this._fillColor = [1.0, 1.0, 1.0, 0.0]; | 53 | this._fillColor = [1.0, 1.0, 1.0, 0.0]; |
91 | this._fillMaterial = null; | ||
92 | this._DISPLAY_ANCHOR_RADIUS = 5; | 54 | this._DISPLAY_ANCHOR_RADIUS = 5; |
55 | |||
93 | //drawing context | 56 | //drawing context |
94 | this._world = null; | 57 | this._world = null; |
58 | this._canvas = null; //todo this might be unnecessary (but faster) since we can get it from the world | ||
95 | 59 | ||
96 | //tool that owns this subpath | 60 | //tool that owns this subpath |
97 | this._drawingTool = null; | 61 | this._drawingTool = null; |
98 | this._planeMat = Matrix.I(4); | ||
99 | this._planeMatInv = Matrix.I(4); | ||
100 | this._planeCenter = null; | ||
101 | this._dragPlane = null; | ||
102 | 62 | ||
103 | //used to query what the user selected, OR-able for future extensions | 63 | //used to query what the user selected, OR-able for future extensions |
104 | this.SEL_NONE = 0; //nothing was selected | 64 | this.SEL_NONE = 0; //nothing was selected |
@@ -110,8 +70,6 @@ var GLSubpath = function GLSubpath() { | |||
110 | this._selectedAnchorIndex = -1; | 70 | this._selectedAnchorIndex = -1; |
111 | 71 | ||
112 | this._SAMPLING_EPSILON = 0.5; //epsilon used for sampling the curve | 72 | this._SAMPLING_EPSILON = 0.5; //epsilon used for sampling the curve |
113 | this._DEFAULT_STROKE_WIDTH = 20; //use only if stroke width not specified | ||
114 | this._MAX_OFFSET_ANGLE = 10; //max angle (in degrees) between consecutive vectors from curve to offset path | ||
115 | 73 | ||
116 | // (current GeomObj complains if buildBuffers/render is added to GLSubpath prototype) | 74 | // (current GeomObj complains if buildBuffers/render is added to GLSubpath prototype) |
117 | //buildBuffers | 75 | //buildBuffers |
@@ -121,13 +79,6 @@ var GLSubpath = function GLSubpath() { | |||
121 | // return; //no need to do anything for now | 79 | // return; //no need to do anything for now |
122 | }; | 80 | }; |
123 | 81 | ||
124 | this._offsetLocalCoord = function(deltaW, deltaH){ | ||
125 | var numPoints = this._LocalPoints.length; | ||
126 | for (var i=0;i<numPoints;i++) { | ||
127 | this._LocalPoints[i][0]+= deltaW; | ||
128 | this._LocalPoints[i][1]+= deltaH; | ||
129 | } | ||
130 | }; | ||
131 | //render | 82 | //render |
132 | // specify how to render the subpath in Canvas2D | 83 | // specify how to render the subpath in Canvas2D |
133 | this.render = function () { | 84 | this.render = function () { |
@@ -146,24 +97,12 @@ var GLSubpath = function GLSubpath() { | |||
146 | if (numAnchors === 0) { | 97 | if (numAnchors === 0) { |
147 | return; //nothing to do for empty paths | 98 | return; //nothing to do for empty paths |
148 | } | 99 | } |
149 | var useLocalCoord = true; | ||
150 | this.createSamples(); //dirty bit checked in this function...will generate a polyline representation | 100 | this.createSamples(); //dirty bit checked in this function...will generate a polyline representation |
151 | 101 | ||
152 | //build the coordinates of the samples in 2D (canvas) space (localDirty bit checked in buildLocalCoord | ||
153 | this.buildLocalCoord(); | ||
154 | |||
155 | //figure the size of the area we will draw into | 102 | //figure the size of the area we will draw into |
156 | var bboxWidth=0, bboxHeight=0; | 103 | var bboxWidth=0, bboxHeight=0; |
157 | if (useLocalCoord){ | 104 | bboxWidth = this._BBoxMax[0] - this._BBoxMin[0]; |
158 | bboxWidth = this._LocalBBoxMax[0] - this._LocalBBoxMin[0]; | 105 | bboxHeight = this._BBoxMax[1] - this._BBoxMin[1]; |
159 | bboxHeight = this._LocalBBoxMax[1] - this._LocalBBoxMin[1]; | ||
160 | } | ||
161 | else { | ||
162 | var bboxMin = this.getBBoxMin(); | ||
163 | var bboxMax = this.getBBoxMax(); | ||
164 | bboxWidth = bboxMax[0] - bboxMin[0]; | ||
165 | bboxHeight = bboxMax[1] - bboxMin[1]; | ||
166 | } | ||
167 | 106 | ||
168 | ctx.save(); | 107 | ctx.save(); |
169 | ctx.clearRect(0, 0, bboxWidth, bboxHeight); | 108 | ctx.clearRect(0, 0, bboxWidth, bboxHeight); |
@@ -204,33 +143,17 @@ var GLSubpath = function GLSubpath() { | |||
204 | */ | 143 | */ |
205 | 144 | ||
206 | 145 | ||
207 | var numPoints=0, i=0; | ||
208 | ctx.beginPath(); | 146 | ctx.beginPath(); |
209 | if (!useLocalCoord){ | 147 | var numPoints = this._Samples.length; |
210 | numPoints = this._samples.length/3; | 148 | ctx.moveTo(this._Samples[0][0],this._Samples[0][1]); |
211 | ctx.moveTo(this._samples[0]-bboxMin[0],this._samples[1]-bboxMin[1]); | 149 | for (var i=0;i<numPoints;i++){ |
212 | for (i=0;i<numPoints;i++){ | 150 | ctx.lineTo(this._Samples[i][0],this._Samples[i][1]); |
213 | ctx.lineTo(this._samples[3*i]-bboxMin[0],this._samples[3*i + 1]-bboxMin[1]); | ||
214 | } | ||
215 | if (this._isClosed === true) { | ||
216 | ctx.lineTo(this._samples[0]-bboxMin[0],this._samples[1]-bboxMin[1]); | ||
217 | } | ||
218 | ctx.fill(); | ||
219 | ctx.stroke(); | ||
220 | } | 151 | } |
221 | else { | 152 | if (this._isClosed === true) { |
222 | //render using the local coords | 153 | ctx.lineTo(this._Samples[0][0],this._Samples[0][1]); |
223 | numPoints = this._LocalPoints.length; | ||
224 | ctx.moveTo(this._LocalPoints[0][0],this._LocalPoints[0][1]); | ||
225 | for (i=0;i<numPoints;i++){ | ||
226 | ctx.lineTo(this._LocalPoints[i][0],this._LocalPoints[i][1]); | ||
227 | } | ||
228 | if (this._isClosed === true) { | ||
229 | ctx.lineTo(this._LocalPoints[0][0],this._LocalPoints[0][1]); | ||
230 | } | ||
231 | ctx.fill(); | ||
232 | ctx.stroke(); | ||
233 | } | 154 | } |
155 | ctx.fill(); | ||
156 | ctx.stroke(); | ||
234 | ctx.restore(); | 157 | ctx.restore(); |
235 | }; //render() | 158 | }; //render() |
236 | 159 | ||
@@ -310,21 +233,21 @@ GLSubpath.prototype = new GeomObj(); | |||
310 | ///////////////////////////////////////////////////////// | 233 | ///////////////////////////////////////////////////////// |
311 | // Property Accessors/Setters | 234 | // Property Accessors/Setters |
312 | ///////////////////////////////////////////////////////// | 235 | ///////////////////////////////////////////////////////// |
313 | GLSubpath.prototype.setCanvas = function (c) { | ||
314 | this._canvas = c; | ||
315 | }; | ||
316 | GLSubpath.prototype.getCanvas = function() { | ||
317 | return this._canvas; | ||
318 | }; | ||
319 | |||
320 | GLSubpath.prototype.setWorld = function (world) { | 236 | GLSubpath.prototype.setWorld = function (world) { |
321 | this._world = world; | 237 | this._world = world; |
322 | }; |