aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xjs/lib/geom/brush-stroke.js177
1 files changed, 172 insertions, 5 deletions
diff --git a/js/lib/geom/brush-stroke.js b/js/lib/geom/brush-stroke.js
index 9a934928..39af5c5c 100755
--- a/js/lib/geom/brush-stroke.js
+++ b/js/lib/geom/brush-stroke.js
@@ -32,6 +32,8 @@ var BrushStroke = function GLBrushStroke() {
32 //stroke information 32 //stroke information
33 this._strokeWidth = 0.0; 33 this._strokeWidth = 0.0;
34 this._strokeColor = [0.4, 0.4, 0.4, 1.0]; 34 this._strokeColor = [0.4, 0.4, 0.4, 1.0];
35 this._secondStrokeColor = this._strokeColor;
36 this._strokeHardness = 100;
35 this._strokeMaterial = null; 37 this._strokeMaterial = null;
36 this._strokeStyle = "Solid"; 38 this._strokeStyle = "Solid";
37 39
@@ -114,7 +116,7 @@ var BrushStroke = function GLBrushStroke() {
114 //add the point only if it is some epsilon away from the previous point 116 //add the point only if it is some epsilon away from the previous point
115 var numPoints = this._Points.length; 117 var numPoints = this._Points.length;
116 if (numPoints>0) { 118 if (numPoints>0) {
117 var threshold = this._WETNESS_FACTOR*this._strokeWidth; 119 var threshold = 1;//this._WETNESS_FACTOR*this._strokeWidth;
118 var prevPt = this._Points[numPoints-1]; 120 var prevPt = this._Points[numPoints-1];
119 var diffPt = [prevPt[0]-pt[0], prevPt[1]-pt[1]]; 121 var diffPt = [prevPt[0]-pt[0], prevPt[1]-pt[1]];
120 var diffPtMag = Math.sqrt(diffPt[0]*diffPt[0] + diffPt[1]*diffPt[1]); 122 var diffPtMag = Math.sqrt(diffPt[0]*diffPt[0] + diffPt[1]*diffPt[1]);
@@ -173,6 +175,14 @@ var BrushStroke = function GLBrushStroke() {
173 this._strokeColor = c; 175 this._strokeColor = c;
174 }; 176 };
175 177
178 this.setSecondStrokeColor = function(c){
179 this._secondStrokeColor=c;
180 }
181
182 this.setStrokeHardness = function(h){
183 this._strokeHardness=h;
184 }
185
176 this.getStrokeStyle = function () { 186 this.getStrokeStyle = function () {
177 return this._strokeStyle; 187 return this._strokeStyle;
178 }; 188 };
@@ -219,7 +229,8 @@ var BrushStroke = function GLBrushStroke() {
219 var numPoints = this._Points.length; 229 var numPoints = this._Points.length;
220 230
221 //**** add samples to the path if needed...linear interpolation for now 231 //**** add samples to the path if needed...linear interpolation for now
222 if (numPoints>1) { 232 //if (numPoints>1) {
233 if (0){
223 var threshold = this._WETNESS_FACTOR*this._strokeWidth; 234 var threshold = this._WETNESS_FACTOR*this._strokeWidth;
224 var prevPt = this._Points[0]; 235 var prevPt = this._Points[0];
225 var prevIndex = 0; 236 var prevIndex = 0;
@@ -250,6 +261,44 @@ var BrushStroke = function GLBrushStroke() {
250 } 261 }
251 } 262 }
252 } 263 }
264 //**** add samples to the long sections of the path --- Catmull-Rom spline interpolation
265 if (numPoints>1) {
266 var numInsertedPoints = 0;
267 var threshold = 5;//0.25*this._strokeWidth; //this determines whether a segment between two sample is too long
268 var prevPt = this._Points[0];
269 for (var i=1;i<numPoints;i++){
270 var pt = this._Points[i];
271 var diff = [pt[0]-prevPt[0], pt[1]-prevPt[1]];
272 var distance = Math.sqrt(diff[0]*diff[0]+diff[1]*diff[1]);
273 if (distance>threshold){
274 //build the control polygon for the Catmull-Rom spline (prev. 2 points and next 2 points)
275 var prev = (i===1) ? i-1 : i-2;
276 var next = (i===numPoints-1) ? i : i+1;
277 var ctrlPts = [this._Points[prev], this._Points[i-1], this._Points[i], this._Points[next]];
278 //insert points along the prev. to current point
279 var numNewPoints = Math.floor(distance/threshold);
280 for (var j=0;j<numNewPoints;j++){
281 var param = (j+1)/(numNewPoints+1);
282 var newpt = this._CatmullRomSplineInterpolate(ctrlPts, param);
283 //insert new point before point i
284 this._Points.splice(i, 0, newpt);
285 i++;
286 numInsertedPoints++;
287 }
288 this._dirty=true;
289 }
290 prevPt=pt;
291 //update numPoints to match the new length
292 numPoints = this._Points.length;
293
294 //end this function if the numPoints has gone above the max. size specified
295 if (numPoints> this._MAX_ALLOWED_SAMPLES){
296 console.log("leaving the resampling because numPoints is greater than limit:"+this._MAX_ALLOWED_SAMPLES);
297 break;
298 }
299 }
300 console.log("Inserted "+numInsertedPoints+" additional CatmullRom points");
301 }
253 302
254 // *** compute the bounding box ********* 303 // *** compute the bounding box *********
255 this._BBoxMin = [Infinity, Infinity, Infinity]; 304 this._BBoxMin = [Infinity, Infinity, Infinity];
@@ -412,7 +461,7 @@ var BrushStroke = function GLBrushStroke() {
412 } 461 }
413 */ 462 */
414 463
415 464 /*
416 var R2 = this._strokeWidth; 465 var R2 = this._strokeWidth;
417 var R = R2*0.5; 466 var R = R2*0.5;
418 var hardness = 0; //for a pencil, this is always 1 //TODO get hardness parameter from user interface 467 var hardness = 0; //for a pencil, this is always 1 //TODO get hardness parameter from user interface
@@ -440,6 +489,109 @@ var BrushStroke = function GLBrushStroke() {
440 //ctx.globalCompositeOperation = 'source-in'; 489 //ctx.globalCompositeOperation = 'source-in';
441 //ctx.rect(x-R, y-R, R2, R2); 490 //ctx.rect(x-R, y-R, R2, R2);
442 } 491 }
492 */
493
494 /*
495 //build the stamp for the brush stroke
496 //todo get this directly from the UI
497 var t=0;
498 var numTraces = this._strokeWidth;
499 var halfNumTraces = numTraces/2;
500 var startPos = [-this._strokeWidth/2,0];
501 var brushStamp = [];
502
503 //build an angled (calligraphic) brush stamp
504 var deltaDisplacement = [1,1];//[this._strokeWidth/numTraces, 0]; //a horizontal line brush
505 for (t=0;t<numTraces;t++){
506 var brushPt = [startPos[0]+t*deltaDisplacement[0], startPos[1]+t*deltaDisplacement[1]];
507 brushStamp.push(brushPt);
508 }
509
510
511 //make a circular brush stamp
512 brushStamp=[];
513 numTraces = this._strokeWidth*Math.PI; //figure out how to
514 var radius = this._strokeWidth/2;
515 for (t=0;t<numTraces;t++)
516 {
517 var angle = Math.PI*(360*t/numTraces)/180;
518 var brushPt = [radius*Math.cos(angle), radius*Math.sin(angle)];
519 brushStamp.push(brushPt);
520 }
521
522// //make a square brush stamp
523// STOPPED HERE
524// brushStamp = [];
525// numTraces = 4*strokeWidth;
526// for (t=0;t<numTraces;t++){
527// if (t<numTraces*0.25){
528// var brushPt = [startPos[0]+t*deltaDisplacement[0], startPos[1]+t*deltaDisplacement[1]];
529// } else if (t<numTraces*0.5){
530//
531// } else if (t<numTraces*0.75){
532//
533// } else {
534//
535// }
536// brushStamp.push(brushPt);
537// }
538
539 for (t=0;t<numTraces;t++){
540 var disp = [brushStamp[t][0], brushStamp[t][1]];
541 //ctx.globalCompositeOperation = 'source-over';
542 var distFromMiddle = Math.abs(halfNumTraces-t);
543 var alphaVal = 1.0 - (100-this._strokeHardness)*(distFromMiddle/halfNumTraces)/100;
544 alphaVal = 0.2;
545 ctx.save();
546 ctx.lineWidth=this._strokeWidth/10;//todo figure out the correct formula for the line width
547 if (ctx.lineWidth<2)
548 ctx.lineWidth=2;
549 if (t===numTraces-1){
550 ctx.lineWidth = 1;
551 }
552 ctx.lineJoin="bevel";
553 ctx.lineCap="butt";
554 //if (t<numTraces/2)
555 ctx.strokeStyle="rgba("+parseInt(255*this._strokeColor[0])+","+parseInt(255*this._strokeColor[1])+","+parseInt(255*this._strokeColor[2])+","+alphaVal+")";
556 //else
557 // ctx.strokeStyle="rgba("+parseInt(255*this._secondStrokeColor[0])+","+parseInt(255*this._secondStrokeColor[1])+","+parseInt(255*this._secondStrokeColor[2])+","+alphaVal+")";
558 ctx.translate(disp[0],disp[1]);
559 ctx.beginPath();
560 ctx.moveTo(this._Points[0][0]-bboxMin[0], this._Points[0][1]-bboxMin[1]);
561 for (var i=0;i<numPoints;i++){
562 ctx.lineTo(this._Points[i][0]-bboxMin[0], this._Points[i][1]-bboxMin[1]);
563 }
564 ctx.stroke();
565 ctx.restore();
566 }
567 */
568
569 /*
570 //debugging path
571 ctx.beginPath();
572 ctx.moveTo(this._Points[0][0]-bboxMin[0], this._Points[0][1]-bboxMin[1]);
573 for (var i=1;i<numPoints;i++){
574 ctx.lineTo(this._Points[i][0]-bboxMin[0], this._Points[i][1]-bboxMin[1]);
575 }
576 ctx.lineWidth=1.0;
577 ctx.strokeStyle = "black";
578 ctx.stroke();
579 */
580
581 var numlayers = this._strokeWidth/2;
582 var alphaVal = 1.0/(numlayers-1);
583 for (var l=0;l<numlayers;l++){
584 ctx.beginPath();
585 ctx.moveTo(this._Points[0][0]-bboxMin[0], this._Points[0][1]-bboxMin[1]);
586 for (var i=1;i<numPoints;i++){
587 ctx.lineTo(this._Points[i][0]-bboxMin[0], this._Points[i][1]-bboxMin[1]);
588 }
589 ctx.lineCap = "round";
590 ctx.lineJoin="round";
591 ctx.lineWidth=l+1;
592 ctx.strokeStyle="rgba("+parseInt(255*this._strokeColor[0])+","+parseInt(255*this._strokeColor[1])+","+parseInt(255*this._strokeColor[2])+","+alphaVal+")";
593 ctx.stroke();
594 }
443 595
444 ctx.restore(); 596 ctx.restore();
445 }; //render() 597 }; //render()
@@ -473,10 +625,25 @@ var BrushStroke = function GLBrushStroke() {
473 return true; 625 return true;
474 }; 626 };
475 627
476}; //function GLSubpath ...class definition 628}; //function BrushStroke ...class definition
477 629
478BrushStroke.prototype = new GeomObj(); 630BrushStroke.prototype = new GeomObj();
479 631
632BrushStroke.prototype._CatmullRomSplineInterpolate = function(ctrlPts, t)
633{
634 //perform CatmullRom interpolation on the spline...assume t is in [0,1]
635 var t2 = t*t;