Skip to main content
Inspiring
December 2, 2016
Answered

Position sprite on edge of polygon

  • December 2, 2016
  • 2 replies
  • 745 views

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

This topic has been closed for replies.
Correct answer Jakob Wagner 2048

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;

            }

        }

    }

}

2 replies

Jakob Wagner 2048AuthorCorrect answer
Inspiring
December 5, 2016

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;

            }

        }

    }

}

kglad
Community Expert
December 2, 2016

we need to see DrawingShapes.drawPolygon

Inspiring
December 2, 2016

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);

                }

            }

        }

kglad
Community Expert
December 2, 2016

what's wrong with your marker?