Skip to main content
Inspiring
December 2, 2016
Answered

Position sprite on edge of polygon

  • December 2, 2016
  • 6 replies
  • 764 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 is closed to new replies. Start a new post to keep the conversation going.
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;

            }

        }

    }

}

6 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
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
Community Expert
December 2, 2016

what's wrong with your marker?