diff options
Diffstat (limited to 'js/lib/geom/sub-path.js')
-rwxr-xr-x | js/lib/geom/sub-path.js | 504 |
1 files changed, 362 insertions, 142 deletions
diff --git a/js/lib/geom/sub-path.js b/js/lib/geom/sub-path.js index 7046673e..35070915 100755 --- a/js/lib/geom/sub-path.js +++ b/js/lib/geom/sub-path.js | |||
@@ -12,6 +12,7 @@ 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 | 14 | // TODO Those function do not seems to be used. We should remove them |
15 | /* | ||
15 | function SubpathOffsetPoint(pos, mapPos) { | 16 | function SubpathOffsetPoint(pos, mapPos) { |
16 | this.Pos = [pos[0],pos[1],pos[2]]; | 17 | this.Pos = [pos[0],pos[1],pos[2]]; |
17 | this.CurveMapPos = [mapPos[0], mapPos[1], mapPos[2]]; | 18 | this.CurveMapPos = [mapPos[0], mapPos[1], mapPos[2]]; |
@@ -33,7 +34,7 @@ function sortNumberDescending(a,b){ | |||
33 | function SegmentIntersections(){ | 34 | function SegmentIntersections(){ |
34 | this.paramArray = []; | 35 | this.paramArray = []; |
35 | } | 36 | } |
36 | 37 | */ | |
37 | /////////////////////////////////////////////////////////////////////// | 38 | /////////////////////////////////////////////////////////////////////// |
38 | // Class GLSubpath | 39 | // Class GLSubpath |
39 | // representation a sequence of cubic bezier curves. | 40 | // representation a sequence of cubic bezier curves. |
@@ -49,27 +50,34 @@ var GLSubpath = function GLSubpath() { | |||
49 | this._BBoxMax = [0, 0, 0]; | 50 | this._BBoxMax = [0, 0, 0]; |
50 | this._isClosed = false; | 51 | this._isClosed = false; |
51 | 52 | ||
52 | this._samples = []; //polyline representation of this curve | 53 | this._samples = []; //polyline representation of this curve in stage world space |
53 | 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) | 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) |
54 | this._anchorSampleIndex = []; //index within _samples corresponding to anchor points | 55 | this._anchorSampleIndex = []; //index within _samples corresponding to anchor points |
55 | 56 | ||
57 | this._LocalPoints = []; //polyline representation of this curve in canvas space | ||
58 | this._LocalBBoxMin = [0,0,0]; //bbox min point of _LocalPoints | ||
59 | this._LocalBBoxMax = [0,0,0]; //bbox max point of _LocalPoints | ||
60 | |||
56 | this._UnprojectedAnchors = []; | 61 | this._UnprojectedAnchors = []; |
57 | 62 | ||
58 | //initially set the _dirty bit so we will construct samples | 63 | //initially set the _dirty bit so we will construct samples |
59 | this._dirty = true; | 64 | this._dirty = true; |
60 | 65 | ||
66 | //initially set the local dirty bit so we will construct local coordinates | ||
67 | this._isLocalDirty = true; | ||
68 | |||
61 | //whether or not to use the canvas drawing to stroke/fill | 69 | //whether or not to use the canvas drawing to stroke/fill |
62 | this._useCanvasDrawing = true; | 70 | this._useCanvasDrawing = true; |
63 | 71 | ||
64 | //the canvas that will draw this subpath | 72 | //the canvas that will draw this subpath |
65 | this._canvas = null; | 73 | this._canvas = null; |
66 | 74 | ||
67 | //the X and Y location of this subpath's canvas in stage world space of Ninja | 75 | //the top left location of this subpath's canvas in screen space |
68 | this._canvasX = 0; | 76 | this._canvasLeft = 0; |
69 | this._canvasY = 0; | 77 | this._canvasTop = 0; |
70 | 78 | ||
71 | //stroke information | 79 | //stroke information |
72 | this._strokeWidth = 0.0; | 80 | this._strokeWidth = 1.0; |
73 | this._strokeColor = [0.4, 0.4, 0.4, 1.0]; | 81 | this._strokeColor = [0.4, 0.4, 0.4, 1.0]; |
74 | this._strokeMaterial = null | 82 | this._strokeMaterial = null |
75 | this._strokeStyle = "Solid"; | 83 | this._strokeStyle = "Solid"; |
@@ -87,6 +95,7 @@ var GLSubpath = function GLSubpath() { | |||
87 | this._planeMat = null; | 95 | this._planeMat = null; |
88 | this._planeMatInv = null; | 96 | this._planeMatInv = null; |
89 | this._planeCenter = null; | 97 | this._planeCenter = null; |
98 | this._dragPlane = null; | ||
90 | 99 | ||
91 | //used to query what the user selected, OR-able for future extensions | 100 | //used to query what the user selected, OR-able for future extensions |
92 | this.SEL_NONE = 0; //nothing was selected | 101 | this.SEL_NONE = 0; //nothing was selected |
@@ -109,42 +118,59 @@ var GLSubpath = function GLSubpath() { | |||
109 | // return; //no need to do anything for now | 118 | // return; //no need to do anything for now |
110 | }; | 119 | }; |
111 | 120 | ||
121 | this._offsetLocalCoord = function(deltaW, deltaH){ | ||
122 | var numPoints = this._LocalPoints.length; | ||
123 | for (var i=0;i<numPoints;i++) { | ||
124 | this._LocalPoints[i][0]+= deltaW; | ||
125 | this._LocalPoints[i][1]+= deltaH; | ||
126 | } | ||
127 | }; | ||
112 | //render | 128 | //render |
113 | // specify how to render the subpath in Canvas2D | 129 | // specify how to render the subpath in Canvas2D |
114 | this.render = function () { | 130 | this.render = function () { |
115 | // get the world | 131 | // get the world |
116 | var world = this.getWorld(); | 132 | var world = this.getWorld(); |
117 | if (!world) throw( "null world in subpath render" ); | 133 | if (!world) throw( "null world in subpath render" ); |
118 | 134 | if (!this._canvas){ | |
119 | // get the context | 135 | //set the canvas by querying the world |
136 | this._canvas = this.getWorld().getCanvas(); | ||
137 | } | ||
138 | // get the context | ||
120 | var ctx = world.get2DContext(); | 139 | var ctx = world.get2DContext(); |
121 | if (!ctx) throw ("null context in subpath render") | 140 | if (!ctx) throw ("null context in subpath render"); |
122 | 141 | ||
123 | var numAnchors = this.getNumAnchors(); | 142 | var numAnchors = this.getNumAnchors(); |
124 | if (numAnchors === 0) { | 143 | if (numAnchors === 0) { |
125 | return; //nothing to do for empty paths | 144 | return; //nothing to do for empty paths |
126 | } | 145 | } |
146 | var useLocalCoord = true; | ||
147 | this.createSamples(); //dirty bit checked in this function...will generate a polyline representation | ||
127 | 148 | ||
128 | ctx.save(); | 149 | //build the coordinates of the samples in 2D (canvas) space (localDirty bit checked in buildLocalCoord |
150 | this.buildLocalCoord(); | ||
129 | 151 | ||
130 | this.createSamples(); //dirty bit checked in this function...will generate a polyline representation | 152 | //figure the size of the area we will draw into |
131 | var bboxMin = this.getBBoxMin(); | 153 | var bboxWidth=0, bboxHeight=0; |
132 | var bboxMax = this.getBBoxMax(); | 154 | if (useLocalCoord){ |
133 | var bboxWidth = bboxMax[0] - bboxMin[0]; | 155 | bboxWidth = this._LocalBBoxMax[0] - this._LocalBBoxMin[0]; |
134 | var bboxHeight = bboxMax[1] - bboxMin[1]; | 156 | bboxHeight = this._LocalBBoxMax[1] - this._LocalBBoxMin[1]; |
135 | var bboxMid = [0.5 * (bboxMax[0] + bboxMin[0]), 0.5 * (bboxMax[1] + bboxMin[1]), 0.5 * (bboxMax[2] + bboxMin[2])]; | ||
136 | |||
137 | if (this._canvas) { | ||
138 | CanvasController.setProperty(this._canvas, "width", bboxWidth+"px"); | ||
139 | CanvasController.setProperty(this._canvas, "height", bboxHeight+"px"); | ||
140 | this._canvas.elementModel.shapeModel.GLWorld.setViewportFromCanvas(this._canvas); | ||
141 | } | 157 | } |
158 | else { | ||
159 | var bboxMin = this.getBBoxMin(); | ||
160 | var bboxMax = this.getBBoxMax(); | ||
161 | bboxWidth = bboxMax[0] - bboxMin[0]; | ||
162 | bboxHeight = bboxMax[1] - bboxMin[1]; | ||
163 | } | ||
164 | |||
165 | ctx.save(); | ||
142 | ctx.clearRect(0, 0, bboxWidth, bboxHeight); | 166 | ctx.clearRect(0, 0, bboxWidth, bboxHeight); |
143 | 167 | ||
144 | ctx.lineWidth = this._strokeWidth; | 168 | ctx.lineWidth = this._strokeWidth; |
145 | ctx.strokeStyle = "black"; | 169 | ctx.strokeStyle = "black"; |
146 | if (this._strokeColor) { | 170 | if (this._strokeColor) { |
147 | ctx.strokeStyle = MathUtils.colorToHex( this._strokeColor ); | 171 | //ctx.strokeStyle = MathUtils.colorToHex( this._strokeColor ); |
172 | var strokeColorStr = "rgba("+parseInt(255*this._strokeColor[0])+","+parseInt(255*this._strokeColor[1])+","+parseInt(255*this._strokeColor[2])+","+this._strokeColor[3]+")"; | ||
173 | ctx.strokeStyle = strokeColorStr; | ||
148 | } | 174 | } |
149 | 175 | ||
150 | ctx.fillStyle = "white"; | 176 | ctx.fillStyle = "white"; |
@@ -152,14 +178,13 @@ var GLSubpath = function GLSubpath() { | |||
152 | //ctx.fillStyle = MathUtils.colorToHex( this._fillColor ); | 178 | //ctx.fillStyle = MathUtils.colorToHex( this._fillColor ); |
153 | var fillColorStr = "rgba("+parseInt(255*this._fillColor[0])+","+parseInt(255*this._fillColor[1])+","+parseInt(255*this._fillColor[2])+","+this._fillColor[3]+")"; | 179 | var fillColorStr = "rgba("+parseInt(255*this._fillColor[0])+","+parseInt(255*this._fillColor[1])+","+parseInt(255*this._fillColor[2])+","+this._fillColor[3]+")"; |
154 | ctx.fillStyle = fillColorStr; | 180 | ctx.fillStyle = fillColorStr; |
155 | console.log("Fill color:" + fillColorStr); | ||
156 | } | 181 | } |
157 | var lineCap = ['butt','round','square']; | 182 | var lineCap = ['butt','round','square']; |
158 | ctx.lineCap = lineCap[1]; | 183 | ctx.lineCap = lineCap[1]; |
159 | ctx.beginPath(); | ||
160 | 184 | ||
161 | /* | 185 | /* |
162 | commenting this out for now because of Chrome bug where coincident endpoints of bezier curve cause the curve to not be rendered | 186 | commenting this out for now because of Chrome bug where coincident endpoints of bezier curve cause the curve to not be rendered |
187 | ctx.beginPath(); | ||
163 | var prevAnchor = this.getAnchor(0); | 188 | var prevAnchor = this.getAnchor(0); |
164 | ctx.moveTo(prevAnchor.getPosX()-bboxMin[0],prevAnchor.getPosY()-bboxMin[1]); | 189 | ctx.moveTo(prevAnchor.getPosX()-bboxMin[0],prevAnchor.getPosY()-bboxMin[1]); |
165 | for (var i = 1; i < numAnchors; i++) { | 190 | for (var i = 1; i < numAnchors; i++) { |
@@ -176,16 +201,33 @@ var GLSubpath = function GLSubpath() { | |||
176 | */ | 201 | */ |
177 | 202 | ||
178 | 203 | ||
179 | var numPoints = this._samples.length/3; | 204 | var numPoints=0, i=0; |
180 | ctx.moveTo(this._samples[0]-bboxMin[0],this._samples[1]-bboxMin[1]); | 205 | ctx.beginPath(); |
181 | for (var i=0;i<numPoints;i++){ | 206 | if (!useLocalCoord){ |
182 | ctx.lineTo(this._samples[3*i]-bboxMin[0],this._samples[3*i + 1]-bboxMin[1]); | 207 | numPoints = this._samples.length/3; |
208 | ctx.moveTo(this._samples[0]-bboxMin[0],this._samples[1]-bboxMin[1]); | ||
209 | for (i=0;i<numPoints;i++){ | ||
210 | ctx.lineTo(this._samples[3*i]-bboxMin[0],this._samples[3*i + 1]-bboxMin[1]); | ||
211 | } | ||
212 | if (this._isClosed === true) { | ||
213 | ctx.lineTo(this._samples[0]-bboxMin[0],this._samples[1]-bboxMin[1]); | ||
214 | } | ||
215 | ctx.fill(); | ||
216 | ctx.stroke(); | ||
183 | } | 217 | } |
184 | if (this._isClosed === true) { | 218 | else { |
185 | ctx.lineTo(this._samples[0]-bboxMin[0],this._samples[1]-bboxMin[1]); | 219 | //render using the local coords |
220 | numPoints = this._LocalPoints.length; | ||
221 | ctx.moveTo(this._LocalPoints[0][0],this._LocalPoints[0][1]); | ||
222 | for (i=0;i<numPoints;i++){ | ||
223 | ctx.lineTo(this._LocalPoints[i][0],this._LocalPoints[i][1]); | ||
224 | } | ||
225 | if (this._isClosed === true) { | ||
226 | ctx.lineTo(this._LocalPoints[0][0],this._LocalPoints[0][1]); | ||
227 | } | ||
228 | ctx.fill(); | ||
229 | ctx.stroke(); | ||
186 | } | 230 | } |
187 | ctx.fill(); | ||
188 | ctx.stroke(); | ||
189 | ctx.restore(); | 231 | ctx.restore(); |
190 | }; //render() | 232 | }; //render() |
191 | 233 | ||
@@ -293,6 +335,10 @@ GLSubpath.prototype.setPlaneMatrix = function(planeMat){ | |||
293 | this._planeMat = planeMat; | 335 | this._planeMat = planeMat; |
294 | }; | 336 | }; |
295 | 337 | ||