
Код AS3:
package
{
import flash.display.Graphics;
import flash.display.Sprite;
import flash.display.StageAlign;
import flash.display.StageScaleMode;
import flash.events.Event;
import flash.geom.Point;
public class Main extends Sprite
{
private var markers:Vector.<Marker>;
public function Main():void
{
stage.scaleMode = StageScaleMode.NO_SCALE;
stage.align = StageAlign.TOP_LEFT;
markers = Vector.<Marker>([
new Marker(100, 100, this),
new Marker(200, 100, this),
new Marker(300, 100, this),
new Marker(400, 100, this),
new Marker(500, 100, this)
]);
addEventListener(Event.ENTER_FRAME, this_enterFrame);
}
private function this_enterFrame(e:Event):void
{
graphics.clear();
var points:Vector.<Point> = new Vector.<Point>();
for (var i:int = 0; i < markers.length; i++)
{
//var j:int = markers.length - 1 - i;
points.push(markers[i].location);
}
graphics.beginFill(0x0, 0.25);
graphics.lineStyle(0, 0xFF0000);
filledLine(graphics, points, 40 );
}
public static function filledLine(g:Graphics, points:Vector.<Point>, thickness:Number, miterLimit:Number = 3):void
{
var s2:Point;
var s1:Point;
var n2:Point;
var n1:Point;
var p:Point;
var a1:Number;
var a2:Number;
var d1:Point;
var d2:Point;
var dP:Point;
var dir:Number;
var arm:Number;
var i:int;
var arr1:Array = [];
var arr2:Array = [];
var arr:Array = [];
var l:int = points.length;
var maxDist:Number = miterLimit ? miterLimit * thickness : Number.MAX_VALUE;
// winding
var angle1:Number = 0;
var angle2:Number = 0;
for (i = 0; i < l; i++)
{
var dp1:Point = points[(i + 1) % points.length].subtract(points[(i + 0) % points.length]);
var dp2:Point = points[(i + 1) % points.length].subtract(points[(i + 2) % points.length]);
var aa1:Number = Math.atan2(dp1.y, dp1.x);
var aa2:Number = Math.atan2(dp2.y, dp2.x);
var da1:Number = aa1 - aa2;
var da2:Number = aa2 - aa1;
if (da1 < 0)
da1 += Math.PI * 2;
if (da2 < 0)
da2 += Math.PI * 2;
angle1 += da1;
angle2 += da2;
}
if (angle2 < angle1)
{
var tmp:Vector.<Point> = new Vector.<Point>();
for (i = 0; i < points.length; i++)
{
tmp[i] = points[l - i - 1];
}
points = tmp;
}
// крайняя
dP = points[1].subtract(points[0]);
arm = 0.5 * thickness;
dir = Math.atan2(dP.y, dP.x) - Math.PI * 0.5;
dP = Point.polar(arm, dir);
arr.push(points[0].subtract(dP), points[0].add(dP));
// промежуточные
for (i = 1; i < l - 1; i++)
{
d1 = points[i].subtract(points[i - 1]);
d2 = points[i].subtract(points[i + 1]);
a1 = Math.atan2(d1.y, d1.x);
a2 = Math.atan2(d2.y, d2.x);
arm = 0.5 * thickness / Math.sin(0.5 * (a1 - a2));
dir = 0.5 * (a1 + a2);
//dir += Math.PI;
dP = Point.polar(arm, dir);
if (Math.abs(arm) > maxDist)
{
n1 = Point.polar(0.5 * thickness, a1 + 1.5 * Math.PI);
n2 = Point.polar(0.5 * thickness, a2 + 0.5 * Math.PI);
s1 = Point.polar(maxDist, a1);
s2 = Point.polar(maxDist, a2);
arr.push(points[i].add(n1.add(s1)));
arr.push(points[i].add(n2.add(s2)));
}
else
{
arr.push(points[i].add(dP));
}
arr2.push(points[i].subtract(dP)); // внутренняя
}
// крайняя
dP = points[l - 2].subtract(points[l - 1]);
arm = 0.5 * thickness;
dir = Math.atan2(dP.y, dP.x) - Math.PI * 0.5;
dP = Point.polar(arm, dir);
arr.push(points[l - 1].subtract(dP), points[l - 1].add(dP));
// внутренний контур
while (arr2.length)
{
arr.push(arr2.pop());
}
g.moveTo(arr[arr.length - 1].x, arr[arr.length - 1].y);
for (i = 0; i < arr.length; i++)
{
g.lineTo(arr[i].x, arr[i].y);
}
}
}
}
/////////////////
import flash.display.DisplayObjectContainer;
import flash.display.Sprite;
import flash.events.MouseEvent;
import flash.geom.Point;
class Marker extends Sprite
{
private var mX:Number;
private var mY:Number;
public function Marker(x:Number = 0, y:Number = 0, parent:DisplayObjectContainer = null)
{
this.x = x;
this.y = y;
graphics.beginFill(0x000000, 0.5);
graphics.drawCircle(0, 0, 10);
if (parent)
{
parent.addChild(this);
}
addEventListener(MouseEvent.MOUSE_DOWN, mouseDown);
buttonMode = true;
}
public function get location():Point
{
return new Point(x, y);
}
private function mouseDown(e:MouseEvent):void
{
stage.addEventListener(MouseEvent.MOUSE_MOVE, stage_mouseMove);
stage.addEventListener(MouseEvent.MOUSE_UP, stage_mouseUp);
mX = stage.mouseX;
mY = stage.mouseY;
}
private function stage_mouseUp(e:MouseEvent):void
{
stage.removeEventListener(MouseEvent.MOUSE_UP, stage_mouseUp);
stage.removeEventListener(MouseEvent.MOUSE_MOVE, stage_mouseMove);
}
private function stage_mouseMove(e:MouseEvent):void
{
x += stage.mouseX - mX;
y += stage.mouseY - mY;
mX = stage.mouseX;
mY = stage.mouseY;
}
}