/* The function transferPoint() is used to transfer points of original four-sided figure to destination figure, which is distorted to perpective. The output is similar to Photoshop Edit-Transform-Distort. The calculation is made by the way that is "perspectivelly" valid (please see the idea on page http://www.royalcomics.org/puhekupla/four_corner_distort.pdf and live example on http://www.royalcomics.org/puhekupla/drag13.swf). The other (newer than this) example that make valid perspective calculations is on http://zehfernando.com/category/flash/, where is link to valid perspective distortion (http://zehfernando.com/f/TriangleTest.swf) and also links to many distortion codes that produces perspectivelly invalid output (for example http://www.rubenswieringa.com/code/as3/flex/DistortImage/). TriangleTest.swf makes use of triangles and flash.display.BitmapData, so the figure is always raster image and the performance with raster images is good. Our transferPoint() can perform raster images as well as vector images, but because of calculating every single point or pixel, the performance with raster images is slower than with vector images. Parameters: xI = x coordinate of point in original figure yI = y coordinate of point in original figure bounds = array of corner coordinates of original four-sided figure Example of bounds-array: var bounds:Array = new Array(); bounds[0] = new Point(0, 0); //bounds[1] = new Point(200, 0); // Not needed, because rectangle bounds[2] = new Point(200,100); //bounds[3] = new Point(0,100); // Not needed, because rectangle coords = corner coordinates of destination (perspective distorted) figure Example of coords-array: var coords:Array = new Array(); coords[0] = new Point(0, 0); coords[1] = new Point(200, 0); coords[2] = new Point(350,200); coords[3] = new Point(0,100); Returns: Array (xI transferred to perspective, yI transferred to perspective) Example: Array(10,20) This function has no check for "illegal" points, so the destination figure can be really distorted :) The function can be used to transfer points of raster image as well as vector image, which means that points of vector font glyphs can be transferred. Vector points can be control points ("offline") and anchor points ("online"), so also curves run smoothly. Idea behind the calculation (http://www.royalcomics.org/puhekupla/four_corner_distort.pdf) and example of four-corner-drag (http://www.royalcomics.org/puhekupla/drag13.swf) are constructed and designed by Timo Kähkönen (04/2009) and the calculation mathematics are made by Mika Kähkönen (04/2009). */ function transferPoint (xI:Number, yI:Number, bounds:Array, coords:Array) { var ADDING:Number = 0.001; var xA:Number = bounds[0].x; var yA:Number = bounds[0].y; var xC:Number = bounds[2].x; var yC:Number = bounds[2].y; var xAu:Number = coords[0].x; var yAu:Number = coords[0].y; var xBu:Number = coords[1].x; var yBu:Number = coords[1].y; var xCu:Number = coords[2].x; var yCu:Number = coords[2].y; var xDu:Number = coords[3].x; var yDu:Number = coords[3].y; // Calcultations // if points are the same, have to add a ADDING to avoid dividing by zero if (xBu==xCu) xCu+=ADDING; if (xAu==xDu) xDu+=ADDING; if (xAu==xBu) xBu+=ADDING; if (xDu==xCu) xCu+=ADDING; var kBC:Number = (yBu-yCu)/(xBu-xCu); var kAD:Number = (yAu-yDu)/(xAu-xDu); var kAB:Number = (yAu-yBu)/(xAu-xBu); var kDC:Number = (yDu-yCu)/(xDu-xCu); if (kBC==kAD) kAD+=ADDING; var xE:Number = (kBC*xBu - kAD*xAu + yAu - yBu) / (kBC-kAD); var yE:Number = kBC*(xE - xBu) + yBu; if (kAB==kDC) kDC+=ADDING; var xF:Number = (kAB*xBu - kDC*xCu + yCu - yBu) / (kAB-kDC); var yF:Number = kAB*(xF - xBu) + yBu; if (xE==xF) xF+=ADDING; var kEF:Number = (yE-yF) / (xE-xF); if (kEF==kAB) kAB+=ADDING; var xG:Number = (kEF*xDu - kAB*xAu + yAu - yDu) / (kEF-kAB); var yG:Number = kEF*(xG - xDu) + yDu; if (kEF==kBC) kBC+=ADDING; var xH:Number = (kEF*xDu - kBC*xBu + yBu - yDu) / (kEF-kBC); var yH:Number = kEF*(xH - xDu) + yDu; var rG:Number = (yC-yI)/(yC-yA); var rH:Number = (xI-xA)/(xC-xA); var xJ:Number = (xG-xDu)*rG + xDu; var yJ:Number = (yG-yDu)*rG + yDu; var xK:Number = (xH-xDu)*rH + xDu; var yK:Number = (yH-yDu)*rH + yDu; if (xF==xJ) xJ+=ADDING; if (xE==xK) xK+=ADDING; var kJF:Number = (yF-yJ) / (xF-xJ); //23 var kKE:Number = (yE-yK) / (xE-xK); //12 var xKE:Number; if (kJF==kKE) kKE+=ADDING; var xIu:Number = (kJF*xF - kKE*xE + yE - yF) / (kJF-kKE); var yIu:Number = kJF * (xIu - xJ) + yJ; var b:Array = new Array(); b[0]=xIu; // Original point xI transferred to xIu b[1]=yIu; // Original point yI transferred to yIu return b; }