Пример #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 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);
        }
Пример #3
0
        public static float CalculateDistanceTo(this IRectangularF a, IRectangularF b)
        {
            var left   = b.Right() < a.Left;
            var right  = a.Right() < b.Left;
            var bottom = b.Bottom() < a.Top;
            var top    = a.Bottom() < b.Top;

            if (top && left)
            {
                return(LocationF.Create(a.Left, a.Bottom()).CalculateDistanceTo(LocationF.Create(b.Right(), b.Top)));
            }
            else if (left && bottom)
            {
                return(LocationF.Create(a.Left, a.Top).CalculateDistanceTo(LocationF.Create(b.Right(), b.Bottom())));
            }
            else if (bottom && right)
            {
                return(LocationF.Create(a.Right(), a.Top).CalculateDistanceTo(LocationF.Create(b.Left, b.Bottom())));
            }
            else if (right && top)
            {
                return(LocationF.Create(a.Right(), a.Bottom()).CalculateDistanceTo(LocationF.Create(b.Left, b.Top)));
            }
            else if (left)
            {
                return(a.Left - b.Right());
            }
            else if (right)
            {
                return(b.Left - a.Right());
            }
            else if (bottom)
            {
                return(a.Top - b.Bottom());
            }
            else if (top)
            {
                return(b.Top - a.Bottom());
            }
            else
            {
                return(0);
            }
        }
Пример #4
0
        private static ILocationF FindIntersectionPoint(Edge a, Edge b)
        {
            var x1 = a.From.Left;
            var y1 = a.From.Top;
            var x2 = a.To.Left;
            var y2 = a.To.Top;

            var x3 = b.From.Left;
            var y3 = b.From.Top;
            var x4 = b.To.Left;
            var y4 = b.To.Top;

            var den = (x1 - x2) * (y3 - y4) - (y1 - y2) * (x3 - x4);

            if (den == 0)
            {
                return(null);
            }

            var t = ((x1 - x3) * (y3 - y4) - (y1 - y3) * (x3 - x4)) / den;

            if (t <= 0 || t >= 1)
            {
                return(null);
            }

            var u = -((x1 - x2) * (y1 - y3) - (y1 - y2) * (x1 - x3)) / den;

            if (u > 0 && u < 1)
            {
                return(LocationF.Create(x1 + t * (x2 - x1), y1 + t * (y2 - y1)));
            }
            else
            {
                return(null);
            }
        }
Пример #5
0
 public static ILocationF BottomRight(this IRectangularF rectangular) => LocationF.Create(rectangular.Right(), rectangular.Bottom());
Пример #6
0
 public static ILocationF BottomLeft(this IRectangularF rectangular) => LocationF.Create(rectangular.Left, rectangular.Bottom());
Пример #7
0
 public static ILocationF TopRight(this IRectangularF rectangular) => LocationF.Create(rectangular.Right(), rectangular.Top);
Пример #8
0
 public static ILocationF TopLeft(this IRectangularF rectangular) => LocationF.Create(rectangular.Left, rectangular.Top);
Пример #9
0
 public static ILocationF Center(this IRectangularF rectangular) => LocationF.Create(rectangular.CenterX(), rectangular.CenterY());
Пример #10
0
 public static ILocationF GetOffsetByPixels(this ILocationF r, float dx, float dy)
 {
     return(LocationF.Create(r.Left + dx, r.Top + dy));
 }
Пример #11
0
        public static HitPrediction PredictHit(HitDetectionOptions options)
        {
            HitPrediction prediction = new HitPrediction();

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


            var mov = options.MovingObject;

            List <Edge> rays;

            if (options.Mode == CastingMode.Precise)
            {
                rays = new List <Edge>()
                {
                    new Edge()
                    {
                        From = mov.TopLeft(), To = mov.TopLeft().MoveTowards(options.Angle, options.Visibility, normalized: false)
                    },
                    new Edge()
                    {
                        From = mov.TopRight(), To = mov.TopRight().MoveTowards(options.Angle, options.Visibility, normalized: false)
                    },
                    new Edge()
                    {
                        From = mov.BottomLeft(), To = mov.BottomLeft().MoveTowards(options.Angle, options.Visibility, normalized: false)
                    },
                    new Edge()
                    {
                        From = mov.BottomRight(), To = mov.BottomRight().MoveTowards(options.Angle, options.Visibility, normalized: false)
                    },
                };

                var granularity = .5f;

                for (var x = mov.Left + granularity; x < mov.Left + mov.Width; x += granularity)
                {
                    var top = LocationF.Create(x, mov.Top);
                    var bot = LocationF.Create(x, mov.Bottom());

                    rays.Add(new Edge()
                    {
                        From = top, To = top.MoveTowards(options.Angle, options.Visibility, normalized: false)
                    });
                    rays.Add(new Edge()
                    {
                        From = bot, To = bot.MoveTowards(options.Angle, options.Visibility, normalized: false)
                    });
                }

                for (var y = mov.Top + granularity; y < mov.Top + mov.Height; y += granularity)
                {
                    var left  = LocationF.Create(mov.Left, y);
                    var right = LocationF.Create(mov.Right(), y);

                    rays.Add(new Edge()
                    {
                        From = left, To = left.MoveTowards(options.Angle, options.Visibility, normalized: false)
                    });
                    rays.Add(new Edge()
                    {
                        From = right, To = right.MoveTowards(options.Angle, options.Visibility, normalized: false)
                    });
                }
            }
            else if (options.Mode == CastingMode.Rough)
            {
                var center = options.MovingObject.Center();
                rays = new List <Edge>()
                {
                    new Edge()
                    {
                        From = mov.TopLeft(), To = mov.TopLeft().MoveTowards(options.Angle, options.Visibility, normalized: false)
                    },
                    new Edge()
                    {
                        From = mov.TopRight(), To = mov.TopRight().MoveTowards(options.Angle, options.Visibility, normalized: false)
                    },
                    new Edge()
                    {
                        From = mov.BottomLeft(), To = mov.BottomLeft().MoveTowards(options.Angle, options.Visibility, normalized: false)
                    },
                    new Edge()
                    {
                        From = mov.BottomRight(), To = mov.BottomRight().MoveTowards(options.Angle, options.Visibility, normalized: false)
                    },
                    new Edge()
                    {
                        From = center, To = center.MoveTowards(options.Angle, options.Visibility, normalized: false)
                    }
                };
            }
            else if (options.Mode == CastingMode.SingleRay)
            {
                var center = options.MovingObject.Center();
                rays = new List <Edge>()
                {
                    new Edge()
                    {
                        From = center, To = center.MoveTowards(options.Angle, options.Visibility, normalized: false)
                    }
                };
            }
            else
            {
                throw new NotSupportedException("Unknown mide: " + options.Mode);
            }

            var           closestIntersectionDistance = float.MaxValue;
            IRectangularF closestIntersectingElement  = null;
            var           closestEdgeIndex            = -1;
            var           effectiveObstacles          = options.Obstacles.ToArray();

            for (var i = 0; i < effectiveObstacles.Length; i++)
            {
                var obstacle = effectiveObstacles[i];
                for (var j = 0; j < obstacle.Edges.Length; j++)
                {
                    var edge = obstacle.Edges[j];
                    for (var k = 0; k < rays.Count; k++)
                    {
                        var ray          = rays[k];
                        var intersection = FindIntersectionPoint(ray, edge);
                        if (intersection != null)
                        {
                            var d = ray.From.CalculateDistanceTo(intersection);
                            if (d < closestIntersectionDistance && d <= options.Visibility)
                            {
                                closestIntersectionDistance = d;
                                closestIntersectingElement  = obstacle;
                                closestEdgeIndex            = j;
                            }
                        }
                    }
                }
            }

            if (closestIntersectingElement != null)
            {
                prediction.ObstacleHit = closestIntersectingElement;
                prediction.LKGD        = closestIntersectionDistance - .1f;
                prediction.LKG         = options.MovingObject.MoveTowards(options.Angle, prediction.LKGD, normalized: false).TopLeft();
                prediction.Type        = HitType.Obstacle;
                prediction.EdgeIndex   = closestEdgeIndex;
            }

            return(prediction);
        }