Последняя версия (ru.flashpress.geom.FPAbout.VERSION = 0.1) лежит здесь
http://flashpress.ru/blog/libs/ .
Если точка регистрации будет лежать не в центре, то мой пример работать не будет, надо поэкспериментировать, как будет время - допишу
Добавлено через 21 час 53 минуты
Дописал код так, что бы можно было вертеть объекты с точкой регистрации в левом верхнем углу:

Код AS3:
package
{
import flash.display.Sprite;
import flash.display.StageAlign;
import flash.display.StageScaleMode;
import flash.events.MouseEvent;
import ru.flashpress.geom.line.FPGLine2d;
import ru.flashpress.geom.line.math.FPGLineToPoint2dMath;
import ru.flashpress.geom.point.FPGPoint2d;
import ru.flashpress.geom.polygon.FPGEdge2d;
import ru.flashpress.geom.polygon.FPGPolygon2d;
import ru.flashpress.geom.polygon.FPGVertex2d;
[SWF(width="600", height="600")]
public class testRect2 extends Sprite
{
private static const CENTER_X:Number = 300;
private static const CENTER_Y:Number = 300;
//
private var redRect:Sprite;
private var purpleRect:Sprite;
private var grayRect:Sprite;
private var polygonRed:FPGPolygon2d;
private var polygonPurp:FPGPolygon2d;
public function testRect2()
{
stage.scaleMode = StageScaleMode.NO_SCALE;
stage.align = StageAlign.TOP_LEFT;
//
var wRed:Number = 100;
var hRed:Number = 200;
var wPur:Number = 100;
var hPur:Number = 150;
//
redRect = new Sprite();
redRect.graphics.lineStyle(1, 0xff0000, 1);
redRect.graphics.drawRect(0, 0, wRed, hRed);
redRect.graphics.endFill();
this.addChild(redRect);
redRect.x = CENTER_X-wRed/2;
redRect.y = CENTER_Y-hRed/2;
//
purpleRect = new Sprite();
purpleRect.graphics.lineStyle(1, 0xff00ff, 1);
purpleRect.graphics.drawRect(0, 0, wPur, hPur);
purpleRect.graphics.endFill();
this.addChild(purpleRect);
purpleRect.x = redRect.x + (redRect.width-purpleRect.width)/2;
purpleRect.y = redRect.y + (redRect.height-purpleRect.height)/2;
//
grayRect = new Sprite();
grayRect.graphics.lineStyle(1, 0x999999, 1);
grayRect.graphics.drawRect(0, 0, wPur, hPur);
grayRect.graphics.endFill();
this.addChild(grayRect);
//
// создаем полигон красного прямоугольника
var redPoints:Vector.<FPGPoint2d> = new Vector.<FPGPoint2d>();
redPoints.push(new FPGPoint2d(CENTER_X-wRed/2, CENTER_Y-hRed/2));
redPoints.push(new FPGPoint2d(CENTER_X+wRed/2, CENTER_Y-hRed/2));
redPoints.push(new FPGPoint2d(CENTER_X+wRed/2, CENTER_Y+hRed/2));
redPoints.push(new FPGPoint2d(CENTER_X-wRed/2, CENTER_Y+hRed/2));
polygonRed = new FPGPolygon2d(redPoints);
//
// создаем полигон фиолетового прямоугольника
var purpPoints:Vector.<FPGPoint2d> = new Vector.<FPGPoint2d>();
purpPoints.push(new FPGPoint2d(CENTER_X-wPur/2, CENTER_Y-hPur/2));
purpPoints.push(new FPGPoint2d(CENTER_X+wPur/2, CENTER_Y-hPur/2));
purpPoints.push(new FPGPoint2d(CENTER_X+wPur/2, CENTER_Y+hPur/2));
purpPoints.push(new FPGPoint2d(CENTER_X-wPur/2, CENTER_Y+hPur/2));
polygonPurp = new FPGPolygon2d(purpPoints);
//
this.stage.addEventListener(MouseEvent.MOUSE_MOVE, moveHandler);
rotate(0);
calculate();
}
private function moveHandler(event:MouseEvent):void
{
event.updateAfterEvent();
var dx:Number = this.mouseX-purpleRect.x;
var dy:Number = this.mouseY-purpleRect.y;
var radians:Number = Math.atan2(dy, dx);
rotate(radians);
calculate();
}
private var oldRotate:Number = 0;
private function rotate(radians:Number):void
{
// поворачиваем филотетовый полигон относительно центральной точки CENTER_X-CENTER_Y
// на угол равный разнице между текущим значением и предыдущим
polygonPurp.rotation(radians-oldRotate, new FPGPoint2d(CENTER_X, CENTER_Y));
oldRotate = radians;
//
//
// поворачиваем Displayobject-ы
grayRect.rotation = purpleRect.rotation = radians*180/Math.PI;
// задаем фиолетовому спрайту координаты смещения
purpleRect.x = polygonPurp.vertexes[0].x;
purpleRect.y = polygonPurp.vertexes[0].y;
}
private function calculate():void
{
var i:int;
var j:int;
var vertex:FPGVertex2d;
var edge:FPGEdge2d;
var heightLine:FPGLine2d;
//
var leftPoint:FPGVertex2d;
var leftEdge:FPGEdge2d;
var maxScale:Number = 1;
for (i=0; i<polygonRed.vertexes.length; i++) {
// текущая вершина красного полигона
vertex = polygonRed.vertexes[i];
for (j=0; j<polygonPurp.edges.length; j++) {
// текущее ребро фиолетового полигона
edge = polygonPurp.edges[j];
// если вершина лежит "слева" от ребра, то пропускаем проверку
// в случае прямоугольников если вершина лежит "слева" -
// это значит что данное ребро не является наиближайщим к данной вершине
if (edge.valueFromPoint(vertex) <= 0) continue;
// получаем отрезок прямой опущенной из вершины на ребро
heightLine = FPGLineToPoint2dMath.lineHeight(edge, vertex);
//
// определяем левую вершину ребра
leftPoint = edge.p1 as FPGVertex2d;
// определяем левое ребро
// в итоге leftEdge будет ссылаться на ребро соседнее с edge
leftEdge = leftPoint.leftEdge;
// определяем максимальный scale
// длина перпендикуляра heightLine умноженная на 2 - это то значение,
// на которое надо увеличить соседнее ребро,
// что бы фиолетовый прямоугольник прошел через текущую вершину
maxScale = Math.max(maxScale, (leftEdge.length+heightLine.length*2)/leftEdge.length);
}
}
//
grayRect.scaleX = grayRect.scaleY = maxScale;
// создаем копию фиолетового полигона
var polygonClone:FPGPolygon2d = polygonPurp.clone();
// применяем к этому полигону scale относительно центральной точки
polygonClone.scale(maxScale, maxScale, new FPGPoint2d(CENTER_X, CENTER_Y));
// и задаем увеличенному спрайту координаты смещения
grayRect.x = polygonClone.vertexes[0].x;
grayRect.y = polygonClone.vertexes[0].y;
}
}
}
Дописал библиотеку FPGeometry2d - обновил метод scale(sx, sy) так, что бы можно было передать в него точку, относительно которой происходит растяжение (Текущая версия ru.flashpress.geom.FPAbout.VERSION = 0.1.1)