/* <copyright>
This file contains proprietary software owned by Motorola Mobility, Inc.<br/>
No rights, expressed or implied, whatsoever to this software are provided by Motorola Mobility, Inc. hereunder.<br/>
(c) Copyright 2011 Motorola Mobility, Inc.  All Rights Reserved.
</copyright> */

var Montage = require("montage/core/core").Montage;
var Component = require("montage/ui/component").Component;

var snapManager = require("js/helper-classes/3D/snap-manager").SnapManager;
var viewUtils = require("js/helper-classes/3D/view-utils").ViewUtils;
var vecUtils = require("js/helper-classes/3D/vec-utils").VecUtils;
var drawUtils = require("js/helper-classes/3D/draw-utils").DrawUtils;

exports.DrawingToolBase = Montage.create(Component, {

    dragPlane: {
        value: null
    },
    /**
     * Used on the initial MouseDown for Drawing Tools
     * 
     * Returns: An array containing:
     *          0 - HitRec point
     *          1 - X value converted to screen point
     *          2 - Y value converted to screen point
     */
    getInitialSnapPoint: {
        value: function(x, y, shapeCanvas)
		{
            // update the snap settings
			snapManager.enableSnapAlign( snapManager.snapAlignEnabledAppLevel() );
			snapManager.enableElementSnap( snapManager.elementSnapEnabledAppLevel() );
			snapManager.enableGridSnap( snapManager.gridSnapEnabledAppLevel() );

			// do the snap
			this.dragPlane = null;
            var hitRec = snapManager.snap(x, y,  true);
			if (hitRec) {
				if (shapeCanvas)
				{
					this.dragPlane = viewUtils.getUnprojectedElementPlane( shapeCanvas );
					snapManager.setupDragPlaneFromPlane( this.dragPlane );
				}
				else
				{
					this.dragPlane = snapManager.setupDragPlanes( hitRec, true );
				}
//				console.log( "drag plane: " + this.dragPlane );

				var wpHitRec = hitRec.convertToWorkingPlane( this.dragPlane );
				var pt = hitRec.getScreenPoint();

                return( [wpHitRec, pt[0], pt[1]] );
			}
        }
    },

    /**
     * Used on the Mouse Move to calculate new snap point.
     */
    getUpdatedSnapPoint: {
        value: function(x,y, snap3d, downHitRec) {
            // update the snap settings
			snapManager.enableSnapAlign( snapManager.snapAlignEnabledAppLevel() );
			snapManager.enableElementSnap( snapManager.elementSnapEnabledAppLevel() );
			snapManager.enableGridSnap( snapManager.gridSnapEnabledAppLevel() );

			var hitRec = snapManager.snap(x, y, snap3d );
			if (hitRec) {
//				if ((hitRec.getType() !== hitRec.SNAP_TYPE_STAGE) && !hitRec.isSomeGridTypeSnap()) {
//					hitRec = hitRec.convertToWorkingPlane( snapManager.getDragPlane() );
//				}
//
//				if(downHitRec !== null) {
//					// if we are working off-plane, do a snap to the projected locations of the geometry
//					var thePlane = workingPlane;
//					if (snapManager.hasDragPlane())
//					{
//						thePlane = snapManager.getDragPlane();
//					}
//
//                    // Return the up HitRec
//                    return hitRec;
//				} else {
//                    return null;
//                }
                if(downHitRec) {
                    hitRec = hitRec.convertToWorkingPlane(this.dragPlane);
                } else if ((hitRec.getType() !== hitRec.SNAP_TYPE_STAGE) && !hitRec.isSomeGridTypeSnap()) {
                    hitRec = hitRec.convertToWorkingPlane( snapManager.getDragPlane() );
                }
            }
            return hitRec;
        }
    },

    getUpdatedSnapPointNoAppLevelEnabling: {
        value: function(x,y, snap3d, downHitRec) {


			// do the first snap
			var hitRec = snapManager.snap(x, y, snap3d );
			if (hitRec) {
				if ((hitRec.getType() !== hitRec.SNAP_TYPE_STAGE) && !hitRec.isSomeGridTypeSnap()) {
					hitRec = hitRec.convertToWorkingPlane( snapManager.getDragPlane() );
				}

				if(downHitRec !== null) {
					// if we are working off-plane, do a snap to the projected locations of the geometry
					var thePlane = workingPlane;
					if (snapManager.hasDragPlane())
					{
						thePlane = snapManager.getDragPlane();
					}

                    // Return the up HitRec
                    return hitRec;
				} else {
                    return null;
                }
            }
        }
    },


    setDownHitRec: {
		value: function (x, y, do3DSnap) {
			var hitRec = snapManager.snap(x, y, do3DSnap );
			if (hitRec) {
				if ((hitRec.getType() != hitRec.SNAP_TYPE_STAGE) && !hitRec.isSomeGridTypeSnap()) {
					//hitRec = hitRec.convertToWorkingPlane( workingPlane );
					snapManager.setupDragPlanes(hitRec);
					hitRec = hitRec.convertToWorkingPlane( snapManager.getDragPlane() );
				}

		    return hitRec;

			}
		}
	},

    drawSnapLastHit: {
        value: function() {
            snapManager.drawLastHit();
        }
    },

    getHitRecPos: {
        value: function (hitRec) {
            if (!hitRec)
                return null;

            // get the hit rec. points in plane space
            var psPos = hitRec.getLocalPoint();

            var stageOffset = viewUtils.getElementOffset(this.application.ninja.currentDocument.model.documentRoot);
            viewUtils.setViewportObj(this.application.ninja.currentDocument.model.documentRoot);

            // get the matrix taking the local hit point in plane space
            // to world space of whatever element it is in.
            var planeMat = hitRec.getPlaneMatrix();

            // get the center of the circle in stage world space
            var swPos = viewUtils.postViewToStageWorld(MathUtils.transformPoint(psPos, hitRec.getPlaneMatrix()), hitRec.getElt());

            //var swPos = hitRec.calculateStageWorldPoint(); todo figure out why we cannot just use this function instead of the above

            // the stage world space point is now relative to the center of the 3D space.  To
            // calculate the left and top offsets, this must be offset by the stage dimensions
            swPos[0] += snapManager.getStageWidth() / 2.0;
            swPos[1] += snapManager.getStageHeight() / 2.0;

            return swPos;
        }
    },

    getCompletePoints: {
        value: function(hitRec0, hitRec1) {
			if (hitRec0 && hitRec1) {

				// get the 2 snap points in plane space
				var p0 = hitRec0.getLocalPoint(),
					p1 = hitRec1.getLocalPoint();

				var stageOffset = viewUtils.getElementOffset(this.application.ninja.currentDocument.model.documentRoot);
				viewUtils.setViewportObj(this.application.ninja.currentDocument.model.documentRoot);

				// get the matrix taking the local hit point in plane space
				// to world space of whatever element it is in.
				var planeMat = hitRec0.getPlaneMatrix();

				// get the center of the circle in stage world space
				var s0 = viewUtils.postViewToStageWorld( MathUtils.transformPoint(p0,hitRec0.getPlaneMatrix()), hitRec0.getElt() ),
					s1 = viewUtils.postViewToStageWorld( MathUtils.transformPoint(p1,hitRec1.getPlaneMatrix()), hitRec1.getElt() );

				// apply the projected snap points
				var s0Proj = false,  s1Proj = false;

				// find a "reasonable" plane
				var thePlane = workingPlane.slice(0);
				if (snapManager.hasDragPlane())  {
					thePlane = snapManager.getDragPlane();
				}

				var d0 = vecUtils.vecDot( 3, thePlane, s0 ) + thePlane[3],
					d1 = vecUtils.vecDot( 3, thePlane, s1 ) + thePlane[3];
				var sign0 = MathUtils.fpSign( d0 ),  sign1 = MathUtils.fpSign( d1 );
				if ((sign0 !== 0) || (sign1 !== 0)) {
					// we need to pick a different plane
					if ( MathUtils.fpCmp(d0,d1) === 0 ) {
						thePlane[3] = -vecUtils.vecDot(3, thePlane, s0);
					} else {
						var vec = vecUtils.vecSubtract(3,  s1, s0 );
						var yAxis = [0,1,0];
						var tmp = vecUtils.vecCross( 3,  vec, yAxis  );
						var mag = vecUtils.vecMag(3, tmp);
						if (MathUtils.fpSign(mag) === 0) {
							thePlane = [0,0,1];
							thePlane[3] = -vecUtils.vecDot(3, thePlane, s0);
						} else {
							var xAxis = vecUtils.vecCross( 3,  yAxis, tmp );
							thePlane  = vecUtils.vecCross( 3,  xAxis, yAxis );
							vecUtils.vecNormalize(3, thePlane, 1.0 );
							thePlane[3] = -vecUtils.vecDot(3, thePlane, s0);
						}
					}

					// recompute the plane matrix
					planeMat = drawUtils.getPlaneToWorldMatrix(thePlane, MathUtils.getPointOnPlane(thePlane));
				}

				// unproject the bounds
				//var planeMatInv = planeMat.inverse();
				var planeMatInv = glmat4.inverse( planeMat, [] );
				//var midPt = this.unprojectPoints( s0, s1, planeMat, planeMatInv, s1Proj );
//				var midPt = this.unprojectPoints( s0, s1, planeMat, planeMatInv, true );

				// get the 4 points of the bounding box in 2D space
				p0 = MathUtils.transformPoint( s0, planeMatInv );
				p1 = MathUtils.transformPoint( s1, planeMatInv );

				// determine the midpoint of the oval
				//midPt = s0.add(s1);
				//midPt = midPt.multiply(0.5);
				//midPt = MathUtils.makeDimension3(midPt);
				var midPt = vec3.add(s0, s1, []);
				midPt = vecUtils.vecScale( 3, midPt, 0.5 );

				// the mid point is now relative to the center of the 3D space.  To
				// calculate the left and top offsets, this must be offset by the stage dimensions
				midPt[0] += snapManager.getStageWidth() / 2.0;
				midPt[1] += snapManager.getStageHeight() / 2.0;

				// calculate the width and height.
				var	left  = p0[0];  var top    = p0[1];
				var	right = p1[0];  var bottom = p1[1];
				var w = Math.abs(right - left),
					h = Math.abs(bottom - top);

//                return ({"width":w, "height":h, "planeMat":planeMat, "midPt":midPt});
                var s0Offset = s0.slice(0);
                var s1Offset = s1.slice(0);
 
                s0Offset[0] += snapManager.getStageWidth() / 2.0;
                s0Offset[1] += snapManager.getStageHeight() / 2.0;
                s1Offset[0] += snapManager.getStageWidth() / 2.0;
                s1Offset[1] += snapManager.getStageHeight() / 2.0;
               return ({ "width": w, "height": h, "planeMat": planeMat, "midPt": midPt, "mouseDownPos": s0Offset, "mouseUpPos": s1Offset });
			} else {
                return null
            }
        }
    },

    cleanupSnap: {
        value: function() {
            // set the drag plane to the working plane
            snapManager.clear2DCache();
            snapManager.setupDragPlaneFromPlane( workingPlane );

            // update the snap settings
            snapManager.enableSnapAlign( snapManager.snapAlignEnabledAppLevel() );
            snapManager.enableElementSnap( snapManager.elementSnapEnabledAppLevel() );
            snapManager.enableGridSnap( snapManager.gridSnapEnabledAppLevel() );

        }
    },

    draw2DRectangle: {
        value: function(x0, y0, x1, y1) {
            var drawingContext = this.application.ninja.stage.drawingContext,
                drawingPrefs = this.application.ninja.stage.drawingContextPreferences;

            this.application.ninja.stage.clearDrawingCanvas();
            //TODO Save and restore state
            drawingContext.strokeStyle = drawingPrefs.color;
            drawingContext.lineWidth = drawingPrefs.thickness;
            drawingContext.strokeRect(x0 - 0.5 ,y0 - 0.5 ,x1 ,y1);
        }
    },

    /**
     * Feedback drawing functions
     */
    drawRectangle: {
        value: function(hitRec0, hitRec1) {
            var p0 = hitRec0.getLocalPoint(),
				p1 = hitRec1.getLocalPoint();

			var stageMat = viewUtils.getMatrixFromElement(this.application.ninja.currentDocument.model.documentRoot);
			var elt = hitRec0.getElt();
			if (!elt) {  elt = hitRec1.getElt();  }
			if (!elt) {  elt = this.application.ninja.currentDocument.model.documentRoot;  }
			if (elt)
			{
				viewUtils.pushViewportObj(elt);
				var offset = viewUtils.getElementOffset(elt);
				offset[2] = 0;

				// check the plane to draw the rectangle on
				var s0 = viewUtils.postViewToStageWorld( MathUtils.transformPoint(p0,hitRec0.getPlaneMatrix()), hitRec0.getElt() ),
					s1 = viewUtils.postViewToStageWorld( MathUtils.transformPoint(p1,hitRec1.getPlaneMatrix()), hitRec1.getElt() );

				// find a "reasonable" plane
				var planeMat = hitRec0.getPlaneMatrix();
				var planeMatInv;
				var thePlane = workingPlane.slice(0);
				if (snapManager.hasDragPlane())
				{
					thePlane = snapManager.getDragPlane();
				}
				var d0 = vecUtils.vecDot( 3, thePlane, s0 ) + thePlane[3],
					d1 = vecUtils.vecDot( 3, thePlane, s1 ) + thePlane[3];
				var sign0 = MathUtils.fpSign( d0 ),  sign1 = MathUtils.fpSign( d1 );
				if ((sign0 !== 0) || (sign1 !== 0))
				{
					// we need to pick a different plane
					if ( MathUtils.fpCmp(d0,d1) === 0 ){
						thePlane[3] = -vecUtils.vecDot(3, thePlane, s0);
					}
					else
					{
						var vec = vecUtils.vecSubtract(3,  s1, s0 );
						var yAxis = [0,1,0];
						var tmp = vecUtils.vecCross( 3,  vec, yAxis  );
						var mag = vecUtils.vecMag(3, tmp);
						if (MathUtils.fpSign(mag) === 0)
						{
							thePlane = [0,0,1];
							thePlane[3] = -vecUtils.vecDot(3, thePlane, s0);
						}
						else
						{
							var xAxis = vecUtils.vecCross( 3,  yAxis, tmp );
							thePlane  = vecUtils.vecCross( 3,  xAxis, yAxis );
							vecUtils.vecNormalize(3, thePlane, 1.0 );
							thePlane[3] = -vecUtils.vecDot(3, thePlane, s0);
						}
					}

					// recompute the plane matrix
					planeMat = drawUtils.getPlaneToWorldMatrix(thePlane, MathUtils.getPointOnPlane(thePlane));
					//planeMatInv = planeMat.inverse();
					planeMatInv = glmat4.inverse( planeMat, [] );

					p0 = MathUtils.transformPoint(p0,hitRec0.getPlaneMatrix());
					p0 = MathUtils.transformPoint(p0, planeMatInv);
					p1 = MathUtils.transformPoint(p1,hitRec1.getPlaneMatrix());
					p1 = MathUtils.transformPoint(p1, planeMatInv);
				}
				else {
					//planeMatInv = planeMat.inverse();
					planeMatInv = glmat4.inverse( planeMat, [] );
				}

				// determine if the geometry is going to be projected.  If so a second projected rectangle is drawn
				var isProjected = ((MathUtils.fpCmp(thePlane[2],1.0) !== 0) || (MathUtils.fpSign(thePlane[3]) !== 0));

                // TODO - We no longer need to project drawing after perspective fix. Need to clean up this code.
                // For now, just setting isProjected to false so rest of the drawing still works.
                isProjected = false;
				// get and draw the unprojected object points
				var projPtArr = [];
				if (isProjected)
				{
					this.getProjectedObjectPoints( s0, s1, planeMat, planeMatInv, elt, stageMat, offset, projPtArr );

				}

				var localPt = [p0[0], p0[1], 0.0, 1.0];
				s0 = viewUtils.postViewToStageWorld( MathUtils.transformPoint(localPt,planeMat),  elt );
				s0 = vecUtils.vecAdd(3, viewUtils.viewToScreen( MathUtils.transformPoint(s0, stageMat) ), offset );

				localPt[1] = p1[1];
				s1 = viewUtils.postViewToStageWorld( MathUtils.transformPoint(localPt,planeMat),  elt );
				s1 = vecUtils.vecAdd(3, viewUtils.viewToScreen( MathUtils.transformPoint(s1, stageMat) ), offset );

				localPt[0] = p1[0];
				var s2 = viewUtils.postViewToStageWorld( MathUtils.transformPoint(localPt,planeMat),  elt );
				s2 = vecUtils.vecAdd(3, viewUtils.viewToScreen( MathUtils.transformPoint(s2, stageMat) ), offset );

				localPt[1] = p0[1];
				var s3 = viewUtils.postViewToStageWorld( MathUtils.transformPoint(localPt,planeMat),  elt );
				s3 = vecUtils.vecAdd(3, viewUtils.viewToScreen( MathUtils.transformPoint(s3, stageMat) ), offset );

				if ( isProjected)
				{
					var unprojPtArr = [s0, s1, s2, s3];
					this.application.ninja.stage.draw3DProjectedAndUnprojectedRectangles( unprojPtArr,  projPtArr );
				}
				else
                {
					this.application.ninja.stage.draw3DSelectionRectangle(s0[0], s0[1],
																		s1[0], s1[1],
																		s2[0], s2[1],
																		s3[0], s3[1],
																		s0[0], s0[1]);
				}

				viewUtils.popViewportObj();
			}
        }
    },

    drawLine: {
        value: function (hitRec0, hitRec1, strokeSize, strokeColor) {
            var p0 = hitRec0.getScreenPoint(),
                p1 = hitRec1.getScreenPoint();
            this.application.ninja.stage.drawLine(p0[0], p0[1], p1[0], p1[1], strokeSize, strokeColor);
        }
    },

    /**
     *  Draw Helper Functions
     */

    /**
     * Returns a perfect square using the top/left/bottom/right values.
     */
    toSquare: {
        value: function(x0,x1,y0,y1) {
            var dw = 1;
            var dh = 1;

            var w = x1 - x0,
                h = y1 - y0;

            if(w < 0) dw = -1;
            if(h < 0) dh = -1;

            if(Math.abs(w) >= Math.abs(h)) {
                h = (Math.abs(w) * dh);
            } else {
                w = (Math.abs(h) * dw);
            }

            return [x0,y0,w,h];
        }
    },

    toCenterRectangle: {
        value: function(x0,x1,y0,y1) {
            var x,y,w,h = 0;

            x = x0 - (x1 - x0);
            y = y0 - (y1 - y0);
            w = x1 - x;
            h = y1 - y;

            return [x,y,w,h];
        }
    },




    /**
     * Helper Functions
     */

	unprojectPoints:
	{
		value: function( s0In, s1In, planeMat, planeMatInv,  fixedS1 ) {
			var s0 = s0In.slice(0);
			var s2 = s1In.slice(0);
		

			// calculate the mid point of the rectangle
			var midPt = vecUtils.vecAdd(3, s0, s2);
			vecUtils.vecScale(3, midPt, 0.5);
			s0[0] -= midPt[0];  s0[1] -= midPt[1];
			s2[0] -= midPt[0];  s2[1] -= midPt[1];

			// convert the 2 world space points to plane space
			var p0 = MathUtils.transformPoint( s0, planeMatInv ),
				p2 = MathUtils.transformPoint( s2, planeMatInv );
			var z = p0[2];

			// fill in the other 2 points on the plane to complete the 4 points
			var p1 = [p0[0], p2[1], z],
				p3 = [p2[0], p0[1], z];

			// convert back to 3D space
			s0 = MathUtils.transformPoint( p0, planeMat );
			var s1 = MathUtils.transformPoint( p1, planeMat );
			s2 = MathUtils.transformPoint( p2, planeMat );
			var s3 = MathUtils.transformPoint( p3, planeMat );

			// unproject the 4 points
			var i;
			var p = 1400;
			var ptArr = [ s0, s1, s2, s3 ];
			for (i=0;  i<4;  i++)
			{
				pt = ptArr[i];
				if (MathUtils.fpCmp(p,-pt[2]) !== 0){
					z = pt[2]*p/(p + pt[2]);
					var x = pt[0]*(p - z)/p,
						y = pt[1]*(p - z)/p;
					

					pt[0] = x;  pt[1] = y;  pt[2] = z;
				}
			}

			// back to 2D space...
			for (i=0;  i<4;  i++)
				ptArr[i] = MathUtils.transformPoint( ptArr[i], planeMatInv );

			// find the 2 diagonal points to use
			if (fixedS1)
			{
				p0 = ptArr[0];  p1 = ptArr[1];  p2 = ptArr[2];  p3 = ptArr[3];
				pt0 = p0.slice(0);  pt1 = p2.slice(0);
				z = pt0[2];
			}
			else
			{
				p0 = ptArr[0];  p1 = ptArr[1];  p2 = ptArr[2];  p3 = ptArr[3];
				z = p0[2];
				var pt0 = p0.slice(0), pt1 = p2.slice(0);
				if (p0[0] < p2[0]){
					pt0[0] = Math.max(p0[0],p1[0]);
					pt1[0] = Math.min(p2[0],p3[0]);
				}
				else {
					pt0[0] = Math.min(p0[0],p1[0]);
					pt1[0] = Math.max(p2[0],p3[0]);
				}
				if (p0[1] < p2[1]){
					pt0[1] = Math.max(p0[1],p3[1]);
					pt1[1] = Math.min(p1[1],p2[1]);
				}
				else {
					pt0[1] = Math.min(p0[1],p3[1]);
					pt1[1] = Math.max(p1[1],p2[1]);
				}
			}
			pt0[2] = z;  pt1[2] = z;

			var ctr = vecUtils.vecAdd(3, pt0, pt1);
			vecUtils.vecScale( 3, ctr, 0.5 );

			// put the diagonal points back in 3D space
			s0  = MathUtils.transformPoint( pt0, planeMat );
			s1  = MathUtils.transformPoint( pt1, planeMat );
			ctr = MathUtils.transformPoint( ctr, planeMat );

			// add the translation back in
			 s0[0] += midPt[0];   s0[1] += midPt[1];
			 s1[0] += midPt[0];   s1[1] += midPt[1];
			ctr[0] += midPt[0];  ctr[1] += midPt[1];

			// set the returned values
			s0In[0] = s0[0];  s0In[1] = s0[1];  s0In[2] = s0[2];
			s1In[0] = s1[0];  s1In[1] = s1[1];  s1In[2] = s1[2];

			return ctr;
		}
	},

    getProjectedObjectPoints:
	{
		value: function( u0, u1, planeMat, planeMatInv, elt, stageMat, offset, rtnScrPts ){
			var s0 = u0.slice(0);
			var s2 = u1.slice(0);

	        var i, z;

			// calculate the mid point of the rectangle
			var midPt = vecUtils.vecAdd(3, s0, s2);
			vecUtils.vecScale(3, midPt, 0.5);
			s0[0] -= midPt[0];  s0[1] -= midPt[1];
			s2[0] -= midPt[0];  s2[1] -= midPt[1];

			// unproject the 2 points
			var p = 1400;
			var ptArr = [ s0, s2 ];
			for (i=0;  i<2;  i++)
			{
				pt = ptArr[i];
				if (MathUtils.fpCmp(p,-pt[2]) !== 0) {
					z = pt[2]*p/(p + pt[2]);
					var x = pt[0]*(p - z)/p,
						y = pt[1]*(p - z)/p;
						y = pt[1]*(p - z)/p;

					pt[0] = x;  pt[1] = y;  pt[2] = z;
				}
			}

			// back to 2D space...
			for (i=0;  i<2;  i++)
				ptArr[i] = MathUtils.transformPoint( ptArr[i], planeMatInv );

			// fill in the other 2 points on the plane to complete the 4 points
			var pt0 = ptArr[0],  pt2 = ptArr[1];
			z = pt0[2];
			pt0[2] = z;  pt2[2] = z;
			var pt1 = [pt0[0], pt2[1], z],
				pt3 = [pt2[0], pt0[1], z];

			//
			ptArr = [pt0, pt1, pt2, pt3];
			var pt;
			var dist, scale, pDist = 1400;	// elt.webkitTransform is not always defined.
			for (i=0;  i<4;  i++)
			{
				// put the point back in 3D space
				pt = MathUtils.transformPoint( ptArr[i], planeMat );

				// apply the perspective
				dist = pDist - pt[2];
				if (MathUtils.fpSign(dist) !== 0)
				{
					scale = pDist / dist;
					pt[0] *= scale;
					pt[1] *= scale;
					pt[2] *= scale;
				}

				// add the translation back in
				pt[0] += midPt[0];  pt[1] += midPt[1];

				// to screen coordinates
				pt = viewUtils.postViewToStageWorld( pt,  elt );
				pt = vecUtils.vecAdd(3, viewUtils.viewToScreen( MathUtils.transformPoint(pt, stageMat) ), offset );

				// save the final result
				rtnScrPts[i] = pt;
			}
		}
	}
    
});