Copy link to clipboard
Copied
Hi all
So, mathematics. This one is to tuff for me. I use this Class: http://snipplr.com/view/67582/as3-drawing-shapes-arc-burst-dashedline-gear-polygon-star-wedge-line/
To draw a polygon. I then want to position a sprite on the edge of that polygon. I would like to define the place on the polygon as a degree, so that 0 and 360 would give me the same result.
I have this script.
package
{
import flash.display.MovieClip;
import flash.display.Graphics;
import flash.display.Sprite;
public class Polygon extends MovieClip
{
private var marker:Sprite;
public function Polygon()
{
marker = new Sprite();
addChild(marker);
marker.graphics.beginFill(0xFF0000, .8);
marker.graphics.drawCircle(0, 0, 10);
graphics.lineStyle(3, 0x0074B9);
positionInPolygon(marker, 400, 300, 5, 200, 0, 20);
DrawingShapes.drawPolygon(graphics, 400, 300, 5, 200, 0);
}
public static function positionInPolygon(target:Sprite, x:Number, y:Number, sides:uint, radius:Number, angle:Number, atAngle:Number):void
{
if (sides <= 2)
{
throw ArgumentError("DrawingShapes.drawPolygon() - parameter 'sides' needs to be atleast 3");
return;
}
if (sides > 2)
{
var step:Number, start:Number, n:Number, dx:Number, dy:Number;
step = (Math.PI * 2) / sides;
start = (angle / 180) * Math.PI;
// Here I can set an integer instead of zero to jump between corners, not what I want though
target.x = x+Math.cos(start + (step * 0)) * radius;
target.y = y+Math.sin(start + (step * 0)) * radius;
}
}
}
}
I need to set target x and y differently. But how?
Let me know if it didn't make sense. I would be graceful for any help.
Thanks,
Jakob Wagner
Thank you for taking the time. Unfortunately, they need to be distributed evenly. I have been trying different things over the weekend and ended up with this, taking a radical different approach. It works. Have the feeling a maths expert could do it in a simpler way, though. And it would be cool if I could bevel the corners, which is going to be impossible with this approach.
Not to worry, this will do for now.
Thanks,
Jakob
package
{
import flash.display.MovieClip;
import flash.display.Graphic
...Copy link to clipboard
Copied
we need to see DrawingShapes.drawPolygon
Copy link to clipboard
Copied
It's on the link, but I put it below here also.
public static function drawPolygon(target:Graphics, x:Number, y:Number, sides:uint, radius:Number, angle:Number=0):void
{
// check that sides is sufficient to build
if (sides <= 2)
{
throw ArgumentError("DrawingShapes.drawPolygon() - parameter 'sides' needs to be atleast 3");
return;
}
if (sides > 2)
{
// init vars
var step:Number, start:Number, n:Number, dx:Number, dy:Number;
// calculate span of sides
step = (Math.PI * 2) / sides;
// calculate starting angle in radians
start = (angle / 180) * Math.PI;
target.moveTo(x + (Math.cos(start) * radius), y - (Math.sin(start) * radius));
// draw the polygon
for (n = 1; n <= sides; ++n)
{
dx = x + Math.cos(start + (step * n)) * radius;
dy = y - Math.sin(start + (step * n)) * radius;
target.lineTo(dx, dy);
}
}
}
Copy link to clipboard
Copied
what's wrong with your marker?
Copy link to clipboard
Copied
Right now I can position it on each of the corners. I want a way to position it anywhere on the edge.
What I'm really trying to do is to distribute a given number of markers evenly on the edge.
Copy link to clipboard
Copied
// this will distribute your points equally by angle, not by distance, along the perimeter
function positionInPolygon(target: Sprite, x: Number, y: Number, sides: uint, radius: Number, angle: Number, atAngle: Number): void {
if (sides <= 2) {
//throw ArgumentError("DrawingShapes.drawPolygon() - parameter 'sides' needs to be atleast 3");
return;
}
if (sides > 2) {
var step: Number, start: Number, n: Number, dx: Number, dy: Number;
step = (Math.PI * 2) / sides;
start = (angle / 180) * Math.PI;
var stepN:Number = findStepF(atAngle,sides)
var x1:Number = x + Math.cos(start + (step *stepN)) * radius;
var y1:Number = y - Math.sin(start + (step * stepN)) * radius;
var x2:Number = x + Math.cos(start + (step * (1+stepN))) * radius;
var y2:Number = y - Math.sin(start + (step * (1+stepN))) * radius;
var x3:Number = x;
var y3:Number = y;
var x4:Number = x+50*Math.cos(atAngle*Math.PI/180);
var y4:Number = y-50*Math.sin(atAngle*Math.PI/180);
var d:Number = (x1-x2)*(y3-y4)-(y1-y2)*(x3-x4);
target.x = ((x1*y2-y1*x2)*(x3-x4)-(x1-x2)*(x3*y4-y3*x4))/d;
target.y = ((x1*y2-y1*x2)*(y3-y4)-(y1-y2)*(x3*y4-y3*x4))/d;
}
}
function findStepF(angle:Number,sides:int):int{
return Math.floor(sides*angle/360);
}
Copy link to clipboard
Copied
Thank you for taking the time. Unfortunately, they need to be distributed evenly. I have been trying different things over the weekend and ended up with this, taking a radical different approach. It works. Have the feeling a maths expert could do it in a simpler way, though. And it would be cool if I could bevel the corners, which is going to be impossible with this approach.
Not to worry, this will do for now.
Thanks,
Jakob
package
{
import flash.display.MovieClip;
import flash.display.Graphics;
import flash.display.Sprite;
import flash.geom.Point;
import flash.events.Event;
public class Polygon extends MovieClip
{
private var numberOfMarkers;
private var markers:Sprite;
private var offset:Number;
private var numberOfSides:int;
private var polygonAngle:Number;
public function Polygon()
{
numberOfMarkers = 50;
offset = 0;
numberOfSides = 3;
polygonAngle = 0;
markers = new Sprite();
addChild(markers);
for(var i:int=0;i<numberOfMarkers;i++)
{
var marker:Sprite = new Sprite();
markers.addChild(marker);
marker.graphics.beginFill(0xFF0000, .8);
marker.graphics.drawCircle(0, 0, 7);
positionInPolygon(marker, 400, 300, numberOfSides, 200, polygonAngle, 360/numberOfMarkers*i);
}
addEventListener(Event.ENTER_FRAME, thisEnterFrame);
}
private function thisEnterFrame(e:Event)
{
offset++;
polygonAngle--;
for(var i:int=0;i<numberOfMarkers;i++)
{
var marker:Sprite = markers.getChildAt(i) as Sprite;
positionInPolygon(marker, 400, 300, numberOfSides, 200, polygonAngle, 360/numberOfMarkers*i+offset);
}
}
public function positionInPolygon(target:Sprite, x:Number, y:Number, sides:uint, radius:Number, angle:Number, atAngle:Number):void
{
if (sides <= 2)
{
throw ArgumentError("DrawingShapes.drawPolygon() - parameter 'sides' needs to be atleast 3");
return;
}
if (sides > 2)
{
var points:Array = [];
var step:Number, start:Number, dx:Number, dy:Number;
step = (Math.PI * 2) / sides;
start = (angle / 180) * Math.PI;
points[0] = new Point(x + (Math.cos(start) * radius), y - (Math.sin(start) * radius));
for (var i:int=1;i<=sides;++i)
{
dx = x + Math.cos(start + (step * i)) * radius;
dy = y - Math.sin(start + (step * i)) * radius;
points = new Point(dx, dy);
}
atAngle = atAngle%360;
// the length of each side
var sideLength:Number = 2*radius*Math.sin(Math.PI/sides);
// the length of all sides combined
var totalLength:Number = sideLength*sides;
// distance from point 0 if all sides where put in one long line
var distanceFromStart:Number = totalLength*atAngle/360;
// index of the start point
var startPoint:int = Math.floor(distanceFromStart/sideLength);
// index of the end point
var endPoint:int = startPoint==sides-1?0:startPoint+1;
// distance from the start point
var distanceFromStartPoint:Number = distanceFromStart-(sideLength*startPoint);
// difference between the to points on x, creating the side a in a right angled triangle
var a:Number = points[startPoint].x-points[endPoint].x;
// difference between the to points on y, creating the side b in a right angled triangle
var b:Number = points[startPoint].y-points[endPoint].y;
// the angle A, opposite of side a
var A:Number = Math.atan(a/b);
// the new side a based on angle A and distanceFromStartPoint
var na:Number = Math.sin(A)*distanceFromStartPoint*(b<0?1:-1);
// the new side b based on angle A and distanceFromStartPoint
var nb:Number = Math.cos(A)*distanceFromStartPoint*(b<0?1:-1);
target.x = points[startPoint].x+na;
target.y = points[startPoint].y+nb;
}
}
}
}