Ejemplo n.º 1
0
        protected static string lastSegmentToCurve(int[][] stroke, float lineCurveThreshold)
        {
		    // Here we tidy up things left unfinished
    		
		    // What's left unfinished there is the curve between the last points
		    // in the stroke
		    // We can also be called when there is only one point in the stroke (meaning, the 
		    // stroke was just a dot), in which case there is nothing for us to do.

		    // So for "this curve" to be calc'ed we need 3 points 
		    // 	A, B, C
		    // and 2 lines:
		    //  pre-line (from points A to B), 
		    //  this line (from points B to C) 
		    // Well, actually, we don't need to *know* the point A, just the vector A->B
		    // so, we really need points B, C and AB vector.
		    var positionInStroke = stroke.Length - 1;
    		
		    // there must be at least 2 points in the stroke.for us to work. Hope calling code checks for that.
            var BCvector = new Vector(stroke[positionInStroke][0], stroke[positionInStroke][1]);
		    var rounding = 2;

            string curvetemplate = "c {0} {1} {2} {3} {4} {5}";
            string linetemplate = "l {0} {1}";

		    if (positionInStroke > 1 && BCvector.Length > lineCurveThreshold){
			    // we have at least 3 elems in stroke
                var ABvector = new Vector(stroke[positionInStroke - 1][0], stroke[positionInStroke - 1][1]);
			    var ABCangle = BCvector.AngleTo(ABvector.Reversed);
			    var minlenfraction = 0.05;
			    var maxlen = BCvector.Length * 0.35;
			    var BtoCP1vector = new Vector(
                    ABvector.x + BCvector.x
                    , ABvector.y + BCvector.y
                ).GetResizedTo(
				    (float)(Math.Max(minlenfraction, ABCangle) * maxlen)
			    );
    			
			    return String.Format(
                    curvetemplate
				    , Math.Round( BtoCP1vector.x, rounding )
				    , Math.Round( BtoCP1vector.y, rounding )
				    , Math.Round( BCvector.x, rounding ) // CP2 is same as Cpoint
				    , Math.Round( BCvector.y, rounding ) // CP2 is same as Cpoint
				    , Math.Round( BCvector.x, rounding )
				    , Math.Round( BCvector.y, rounding )
			    );
		    } else {
			    // Since there is no AB leg, there is no curve to draw. This is just line
			    return String.Format(
                    linetemplate
				    , Math.Round( BCvector.x, rounding )
				    , Math.Round( BCvector.y, rounding )
			    );
		    }
	    }
Ejemplo n.º 2
0
		/**
		 * Calculates the angle between 'this' vector and another.
		 * @public
		 * @function
		 * @returns {Number} The angle between the two vectors as measured in PI. 
		 */
		public float AngleTo(Vector vectorB) {
			var divisor = this.Length * vectorB.Length;
			if (divisor == 0) {
				return 0;
			} else {
				// JavaScript floating point math is screwed up.
				// because of it, the core of the formula can, on occasion, have values
				// over 1.0 and below -1.0.
				return (float)( Math.Acos(
					Math.Min( 
						Math.Max( 
							( this.x * vectorB.x + this.y * vectorB.y ) / divisor
							, -1.0
						)
						, 1.0
					)
				) / Math.PI );
			}
		}
Ejemplo n.º 3
0
        protected static string segmentToCurve(int[][] stroke, int positionInStroke, float lineCurveThreshold)
        {
		    // long lines (ones with many pixels between them) do not look good when they are part of a large curvy stroke.
		    // You know, the jaggedy crocodile spine instead of a pretty, smooth curve. Yuck!
		    // We want to approximate pretty curves in-place of those ugly lines.
		    // To approximate a very nice curve we need to know the direction of line before and after.
		    // Hence, on long lines we actually wait for another point beyond it to come back from
		    // mousemoved before we draw this curve.
    		
		    // So for "prior curve" to be calc'ed we need 4 points 
		    // 	A, B, C, D (we are on D now, A is 3 points in the past.)
		    // and 3 lines:
		    //  pre-line (from points A to B), 
		    //  this line (from points B to C), (we call it "this" because if it was not yet, it's the only one we can draw for sure.) 
		    //  post-line (from points C to D) (even through D point is 'current' we don't know how we can draw it yet)
		    //
		    // Well, actually, we don't need to *know* the point A, just the vector A->B

		    // Again, we can only derive curve between points positionInStroke-1 and positionInStroke
		    // Thus, since we can only draw a line if we know one point ahead of it, we need to shift our focus one point ahead.
		    positionInStroke += 1;
		    // Let's hope the code that calls us knows we do that and does not call us with positionInStroke = index of last point.

            var CDvector = new Vector(stroke[positionInStroke][0], stroke[positionInStroke][1]);
		    // Again, we have a chance here to draw only PREVIOUS line segment - BC
    		
		    // So, let's start with BC curve.
		    // if there is only 2 points in stroke array (C, D), we don't have "history" long enough to have point B, let alone point A.
		    // so positionInStroke should start with 2, ie
		    // we are here when there are at least 3 points in stroke array.
            var BCvector = new Vector(stroke[positionInStroke - 1][0], stroke[positionInStroke - 1][1]);
		    Vector ABvector;
		    var rounding = 2;

            string curvetemplate = "c {0} {1} {2} {3} {4} {5}";
            string linetemplate = "l {0} {1}";


		    if ( BCvector.Length > lineCurveThreshold ){
			    // Yey! Pretty curves, here we come!
			    if(positionInStroke > 2) {
                    ABvector = new Vector(stroke[positionInStroke - 2][0], stroke[positionInStroke - 2][1]);
			    } else {
				    ABvector = new Vector(0,0);
			    }
			    var minlenfraction = 0.05f;
			    var maxlen = BCvector.Length * 0.35;

			    var ABCangle = BCvector.AngleTo(ABvector.Reversed);
			    var BCDangle = CDvector.AngleTo(BCvector.Reversed);
			    var BtoCP1vector = new Vector(
                        ABvector.x + BCvector.x
                        , ABvector.y + BCvector.y
                    ).GetResizedTo(
				        (float)(Math.Max(minlenfraction, ABCangle) * maxlen)
			        );
			    var CtoCP2vector = new Vector(
                        BCvector.x + CDvector.x
                        , BCvector.y + CDvector.y
                    ).Reversed.GetResizedTo(
				        (float)(Math.Max(minlenfraction, BCDangle) * maxlen)
			        );
			    var BtoCP2vector = new Vector(BCvector.x + CtoCP2vector.x, BCvector.y + CtoCP2vector.y);
    			
			    // returing curve for BC segment
			    // all coords are vectors against Bpoint
			    return String.Format(
                    curvetemplate
				    , Math.Round( BtoCP1vector.x, rounding )
				    , Math.Round( BtoCP1vector.y, rounding )
				    , Math.Round( BtoCP2vector.x, rounding )
				    , Math.Round( BtoCP2vector.y, rounding )
				    , Math.Round( BCvector.x, rounding )
				    , Math.Round( BCvector.y, rounding )
			    );
		    } else {
			    return String.Format(
                    linetemplate
				    , Math.Round( BCvector.x, rounding )
				    , Math.Round( BCvector.y, rounding )
			    );
		    }
	    }