aboutsummaryrefslogtreecommitdiff
path: root/js/lib
diff options
context:
space:
mode:
Diffstat (limited to 'js/lib')
-rwxr-xr-xjs/lib/geom/brush-stroke.js205
1 files changed, 94 insertions, 111 deletions
diff --git a/js/lib/geom/brush-stroke.js b/js/lib/geom/brush-stroke.js
index 4c42539a..0278e49c 100755
--- a/js/lib/geom/brush-stroke.js
+++ b/js/lib/geom/brush-stroke.js
@@ -18,9 +18,12 @@ var BrushStroke = function GLBrushStroke() {
18 // Instance variables 18 // Instance variables
19 /////////////////////////////////////////////////// 19 ///////////////////////////////////////////////////
20 this._Points = []; 20 this._Points = [];
21 this._OrigPoints = [];
21 this._BBoxMin = [0, 0, 0]; 22 this._BBoxMin = [0, 0, 0];
22 this._BBoxMax = [0, 0, 0]; 23 this._BBoxMax = [0, 0, 0];
23 this._dirty = true; 24 this._dirty = true;
25 this._addedSamples = false;
26 this._storedOrigPoints = false;
24 27
25 //whether or not to use the canvas drawing to stroke/fill 28 //whether or not to use the canvas drawing to stroke/fill
26 this._useCanvasDrawing = true; 29 this._useCanvasDrawing = true;
@@ -39,10 +42,7 @@ var BrushStroke = function GLBrushStroke() {
39 this._strokeDoSmoothing = false; 42 this._strokeDoSmoothing = false;
40 this._strokeUseCalligraphic = false; 43 this._strokeUseCalligraphic = false;
41 this._strokeAngle = 0; 44 this._strokeAngle = 0;
42 45 this._strokeAmountSmoothing = 0;
43 //the wetness of the brush (currently this is multiplied to the square of the stroke width, but todo should be changed to not depend on stroke width entirely
44 //smaller value means more samples for the path
45 this._WETNESS_FACTOR = 0.25;
46 46
47 //threshold that tells us whether two samples are too far apart 47 //threshold that tells us whether two samples are too far apart
48 this._MAX_SAMPLE_DISTANCE_THRESHOLD = 5; 48 this._MAX_SAMPLE_DISTANCE_THRESHOLD = 5;
@@ -125,7 +125,7 @@ var BrushStroke = function GLBrushStroke() {
125 //add the point only if it is some epsilon away from the previous point 125 //add the point only if it is some epsilon away from the previous point
126 var numPoints = this._Points.length; 126 var numPoints = this._Points.length;
127 if (numPoints>0) { 127 if (numPoints>0) {
128 var threshold = this._MIN_SAMPLE_DISTANCE_THRESHOLD;//this._WETNESS_FACTOR*this._strokeWidth; 128 var threshold = this._MIN_SAMPLE_DISTANCE_THRESHOLD;
129 var prevPt = this._Points[numPoints-1]; 129 var prevPt = this._Points[numPoints-1];
130 var diffPt = [prevPt[0]-pt[0], prevPt[1]-pt[1]]; 130 var diffPt = [prevPt[0]-pt[0], prevPt[1]-pt[1]];
131 var diffPtMag = Math.sqrt(diffPt[0]*diffPt[0] + diffPt[1]*diffPt[1]); 131 var diffPtMag = Math.sqrt(diffPt[0]*diffPt[0] + diffPt[1]*diffPt[1]);
@@ -140,7 +140,8 @@ var BrushStroke = function GLBrushStroke() {
140 }; 140 };
141 141
142 this.insertPoint = function(pt, index){ 142 this.insertPoint = function(pt, index){
143 this._Points.splice(index, 0, pt); this._dirty=true; 143 this._Points.splice(index, 0, pt);
144 this._dirty=true;
144 }; 145 };
145 146
146 this.isDirty = function(){ 147 this.isDirty = function(){
@@ -173,7 +174,7 @@ var BrushStroke = function GLBrushStroke() {
173 }; 174 };
174 175
175 this.setStrokeMaterial = function (m) { 176 this.setStrokeMaterial = function (m) {
176 this._strokeMaterial = m; 177 this._strokeMaterial = m; this._dirty = true;
177 }; 178 };
178 179
179 this.getStrokeColor = function () { 180 this.getStrokeColor = function () {
@@ -181,27 +182,47 @@ var BrushStroke = function GLBrushStroke() {
181 }; 182 };
182 183
183 this.setStrokeColor = function (c) { 184 this.setStrokeColor = function (c) {
184 this._strokeColor = c; 185 this._strokeColor = c; this._dirty = true;
185 }; 186 };
186 187
187 this.setSecondStrokeColor = function(c){ 188 this.setSecondStrokeColor = function(c){
188 this._secondStrokeColor=c; 189 this._secondStrokeColor=c; this._dirty = true;
189 } 190 }
190 191
191 this.setStrokeHardness = function(h){ 192 this.setStrokeHardness = function(h){
192 this._strokeHardness=h; 193 if (this._strokeHardness!==h){
194 this._strokeHardness=h;
195 this._dirty = true;
196 }
193 } 197 }
194 198
195 this.setDoSmoothing = function(s){ 199 this.setDoSmoothing = function(s){
196 this._strokeDoSmoothing = s; 200 if (this._strokeDoSmoothing!==s) {
201 this._strokeDoSmoothing = s;
202 this._dirty = true;
203 }
204 }
205
206 this.setSmoothingAmount = function(a){
207 if (this._strokeAmountSmoothing!==a) {
208 this._strokeAmountSmoothing = a;
209 this._dirty = true;
210 }
211
197 } 212 }
198 213
199 this.setStrokeUseCalligraphic = function(c){ 214 this.setStrokeUseCalligraphic = function(c){
200 this._strokeUseCalligraphic = c; 215 if (this._strokeUseCalligraphic!==c){
216 this._strokeUseCalligraphic = c;
217 this._dirty = true;
218 }
201 } 219 }
202 220
203 this.setStrokeAngle = function(a){ 221 this.setStrokeAngle = function(a){
204 this._strokeAngle = a; 222 if (this._strokeAngle!==a){
223 this._strokeAngle = a;
224 this._dirty = true;
225 };
205 } 226 }
206 227
207 this.getStrokeStyle = function () { 228 this.getStrokeStyle = function () {
@@ -220,133 +241,95 @@ var BrushStroke = function GLBrushStroke() {
220 241
221 };//NO-OP for now 242 };//NO-OP for now
222 243
223
224 //remove and return anchor at specified index, return null on error
225 this.removePoint = function (index) {
226 var retAnchor = null;
227 if (index < this._Points.length) {
228 retPt = this._Points.splice(index, 1);
229 this._dirty=true;
230 }
231 return retPoint;
232 };
233
234 //remove all the points 244 //remove all the points
235 this.clear = function () { 245 this.clear = function () {
236 this._Points = []; 246 this._Points = [];
247 this._OrigPoints = [];
237 this._dirty=true; 248 this._dirty=true;
238 } 249 }
239 250
240 this.translate = function (tx, ty, tz) { 251 /*this.translate = function (tx, ty, tz) {
241 for (var i=0;i<this._Points.length;i++){ 252 for (var i=0;i<this._Points.length;i++){
242 this._Points[i][0]+=tx; 253 this._Points[i][0]+=tx;
243 this._Points[i][1]+=ty; 254 this._Points[i][1]+=ty;
244 this._Points[i][2]+=tz; 255 this._Points[i][2]+=tz;
245 } 256 }
246 }; 257 this._dirty = true;
258 };*/
247 259
248 this.computeMetaGeometry = function() { 260 this.computeMetaGeometry = function() {
249 if (this._dirty) { 261 var numPoints = this._Points.length;
250 var numPoints = this._Points.length; 262 if (this._addedSamples === false){
251 263 //**** add samples to the long sections of the path --- Catmull-Rom spline interpolation *****
252 //**** add samples to the path if needed...linear interpolation for now 264 // instead of the following, may use 4-point subdivision iterations over continuous regions of 'long' segments
253 //if (numPoints>1) { 265 // look at http://www.gvu.gatech.edu/~jarek/Split&Tweak/ for formula
254 if (0){ 266
255 var threshold = this._WETNESS_FACTOR*this._strokeWidth; 267 var numInsertedPoints = 0;
256 var prevPt = this._Points[0]; 268 var newSampledPoints = [];
257 var prevIndex = 0; 269 var threshold = this._MAX_SAMPLE_DISTANCE_THRESHOLD;//this determines whether a segment between two sample is long enough to warrant checking for angle
258 for (var i=1;i<numPoints;i++){ 270 var prevPt = this._Points[0];
259 var pt = this._Points[i]; 271 newSampledPoints.push(this._Points[0]);
260 var diff = [pt[0]-prevPt[0], pt[1]-prevPt[1]]; 272 for (var i=1;i<numPoints;i++) {
261 var distance = Math.sqrt(diff[0]*diff[0]+diff[1]*diff[1]); 273 var pt = this._Points[i];
262 if (distance>threshold){ 274 var diff = [pt[0]-prevPt[0], pt[1]-prevPt[1]];
263 //insert points along the prev. to current point 275 var distance = Math.sqrt(diff[0]*diff[0]+diff[1]*diff[1]);
264 var numNewPoints = Math.floor(distance/threshold); 276 if (distance>threshold){
265 for (var j=0;j<numNewPoints;j++){ 277 //build the control polygon for the Catmull-Rom spline (prev. 2 points and next 2 points)
266 var param = (j+1)/(numNewPoints+1); 278 var prev = (i===1) ? i-1 : i-2;
267 var newpt = [prevPt[0]+ diff[0]*param, prevPt[1]+ diff[1]*param]; 279 var next = (i===numPoints-1) ? i : i+1;
268 //insert new point before point i 280 var ctrlPts = [this._Points[prev], this._Points[i-1], this._Points[i], this._Points[next]];
269 this._Points.splice(i, 0, [newpt[0], newpt[1], 0]); 281 //insert points along the prev. to current point
270 i++; 282 var numNewPoints = Math.floor(distance/threshold);
271 } 283 for (var j=0;j<numNewPoints;j++){
272 this._dirty=true; 284 var param = (j+1)/(numNewPoints+1);
273 } 285 var newpt = this._CatmullRomSplineInterpolate(ctrlPts, param);
274 prevPt=pt; 286 newSampledPoints.push(newpt);
275 //update numPoints to match the new length 287 numInsertedPoints++;
276 numPoints = this._Points.length;
277
278 //end this function if the numPoints has gone above the max. size specified
279 if (numPoints> this._MAX_ALLOWED_SAMPLES){
280 console.log("leaving the resampling because numPoints is greater than limit:"+this._MAX_ALLOWED_SAMPLES);
281 break;
282 } 288 }
283 } 289 }
290 newSampledPoints.push(pt);
291 prevPt=pt;
292
293 //end this function if the numPoints has gone above the max. size specified
294 //if (numPoints> this._MAX_ALLOWED_SAMPLES){
295 // console.log("leaving the resampling because numPoints is greater than limit:"+this._MAX_ALLOWED_SAMPLES);
296 // break;
297 //}
284 } 298 }
299 this._Points = newSampledPoints.slice(0);
300 newSampledPoints = [];
301 console.log("Inserted "+numInsertedPoints+" additional CatmullRom points");
302 this._addedSamples = true;
303 this._dirty=true;
304 }
305 //build a copy of the original points...this should be done only once
306 if (this._storedOrigPoints === false) {
307 this._OrigPoints = this._Points.slice(0);