示例#1
0
        public static ILocationF MoveTowards(this ILocationF a, float angle, float distance)
        {
            while (angle < 0)
            {
                angle += 360;
            }

            while (angle > 360)
            {
                angle -= 360;
            }

            distance = Geometry.NormalizeQuantity(distance, angle);
            var forward = angle > 270 || angle < 90;
            var up      = angle > 180;

            // convert to radians
            angle = (float)(angle * Math.PI / 180);
            float dy = (float)Math.Abs(distance * Math.Sin(angle));
            float dx = (float)Math.Sqrt((distance * distance) - (dy * dy));

            float x2 = forward ? a.Left + dx : a.Left - dx;
            float y2 = up ? a.Top - dy : a.Top + dy;

            var ret = LocationF.Create(x2, y2);

            return(ret);
        }
示例#2
0
        public static IRectangularF ToRect(this ILocationF loc, float w, float h)
        {
            var left = loc.Left - w / 2;
            var top  = loc.Top - h / 2;

            return(RectangularF.Create(left, top, w, h));
        }
示例#3
0
        public static ILocationF MoveTowards(this ILocationF a, ILocationF b, float distance)
        {
            float slope   = (a.Top - b.Top) / (a.Left - b.Left);
            bool  forward = a.Left <= b.Left;
            bool  up      = a.Top <= b.Top;

            float  abDistance = Geometry.CalculateNormalizedDistanceTo(a, b);
            double angle      = Math.Asin(Math.Abs(b.Top - a.Top) / abDistance);
            float  dy         = (float)Math.Abs(distance * Math.Sin(angle));
            float  dx         = (float)Math.Sqrt((distance * distance) - (dy * dy));

            float x2 = forward ? a.Left + dx : a.Left - dx;
            float y2 = up ? a.Top + dy : a.Top - dy;

            var ret = LocationF.Create(x2, y2);

            return(ret);
        }
示例#4
0
        public static float CalculateAngleTo(this ILocationF start, ILocationF end)
        {
            float dx = end.Left - start.Left;
            float dy = end.Top - start.Top;
            float d  = CalculateDistanceTo(start, end);

            if (dy == 0 && dx > 0)
            {
                return(0);
            }
            else if (dy == 0)
            {
                return(180);
            }
            else if (dx == 0 && dy > 0)
            {
                return(90);
            }
            else if (dx == 0)
            {
                return(270);
            }

            double radians, increment;

            if (dx >= 0 && dy >= 0)
            {
                // Sin(a) = dy / d
                radians   = Math.Asin(dy / d);
                increment = 0;
            }
            else if (dx < 0 && dy > 0)
            {
                // Sin(a) = dx / d
                radians   = Math.Asin(-dx / d);
                increment = 90;
            }
            else if (dy < 0 && dx < 0)
            {
                radians   = Math.Asin(-dy / d);
                increment = 180;
            }
            else if (dx > 0 && dy < 0)
            {
                radians   = Math.Asin(dx / d);
                increment = 270;
            }
            else
            {
                throw new Exception($"Failed to calculate angle from {start?.Left},{start?.Top} to {end?.Left},{end?.Top}");
            }

            var ret = (float)(increment + radians * 180 / Math.PI);

            if (ret == 360)
            {
                ret = 0;
            }

            return(ret);
        }
示例#5
0
 public static float CalculateDistanceTo(this ILocationF start, ILocationF end) => CalculateDistanceTo(start.Left, start.Top, end.Left, end.Top);
示例#6
0
 public static float CalculateNormalizedDistanceTo(ILocationF a, ILocationF b) => NormalizeQuantity(a.CalculateDistanceTo(b), a.CalculateAngleTo(b), true);
示例#7
0
 public static IRectangularF Create(ILocationF location, ISizeF size) => new RectangularF(location.Left, location.Top, size.Width, size.Height);
示例#8
0
 public static ILocationF GetOffsetByPixels(this ILocationF r, float dx, float dy)
 {
     return(LocationF.Create(r.Left + dx, r.Top + dy));
 }
示例#9
0
        public static HitPrediction PredictHit(HitDetectionOptions options)
        {
            HitPrediction prediction = new HitPrediction();

            prediction.MovingObjectPosition = options.MovingObject.CopyBounds();
            prediction.Visibility           = options.Visibility;
            if (options.Visibility == 0)
            {
                prediction.Direction = Direction.None;
                prediction.Type      = HitType.None;
                return(prediction);
            }


            var effectiveObstacles = options.Obstacles.Where(o => o.CalculateDistanceTo(options.MovingObject) <= options.Visibility + options.Precision).ToList();

            var        endPoint = options.MovingObject.MoveTowards(options.Angle, options.Visibility);
            ILocationF lkg      = null;

            for (var dPrime = options.Precision; dPrime < options.Visibility; dPrime += options.Precision)
            {
                var testArea = options.MovingObject.MoveTowards(options.Angle, dPrime);
                prediction.Path.Add(testArea);
                var obstacleHit = effectiveObstacles.Where(o =>
                {
                    var simpleTest = o.Touches(testArea) == true;
                    if (simpleTest == false)
                    {
                        return(false);
                    }

                    if (o.Touches(options.MovingObject))
                    {
                        var overlapBefore = options.MovingObject.NumberOfPixelsThatOverlap(o);
                        var overlapAfter  = testArea.NumberOfPixelsThatOverlap(o);

                        if (overlapAfter < overlapBefore)
                        {
                            return(false);
                        }
                        else
                        {
                            return(true);
                        }
                    }
                    else
                    {
                        return(true);
                    }
                }).FirstOrDefault();

                if (obstacleHit != null)
                {
                    prediction.Type        = HitType.Obstacle;
                    prediction.ObstacleHit = obstacleHit;
                    prediction.LKG         = lkg;
                    return(prediction);
                }
                else
                {
                    lkg = testArea.TopLeft();
                }
            }

            var obstacleHitFinal = effectiveObstacles.Where(o => o.Touches(endPoint) == true).FirstOrDefault();

            if (obstacleHitFinal != null)
            {
                prediction.Type        = HitType.Obstacle;
                prediction.ObstacleHit = obstacleHitFinal;
                prediction.LKG         = lkg;
                return(prediction);
            }

            prediction.Type = HitType.None;
            return(prediction);
        }
示例#10
0
 public static float CalculateDistanceTo(this ILocationF start, ILocationF end) => (float)Math.Sqrt(((start.Left - end.Left) * (start.Left - end.Left)) + ((start.Top - end.Top) * (start.Top - end.Top)));