Exemplo n.º 1
0
        public Fuzzy MoveAlong(Direction direction, double step, out Position newPosition)
        {
            // simple case #1 : dx == 0
            if ( direction.Dx == 0 )
            {
                newPosition = new Position(x, y + step * Fuzzy.Sign(direction.Dy));
                return step;
            }

            // simple case #2 : dy == 0
            if ( direction.Dy == 0)
            {
                newPosition = new Position(x + step * Fuzzy.Sign(direction.Dx), y);
                return step;
            }

            var newXOnGrid = GetNextPositionOnGrid(x, direction.Dx, step);
            var newYOnGrid = GetNextPositionOnGrid(y, direction.Dy, step);

            var xMotion = newXOnGrid - x;
            var yMotion = newYOnGrid - y;

            Debug.Assert(Fuzzy.Abs(xMotion) > 0);
            Debug.Assert(Fuzzy.Abs(xMotion) <= 0.5);
            Debug.Assert(Fuzzy.Abs(yMotion) > 0);
            Debug.Assert(Fuzzy.Abs(yMotion) <= 0.5);

            // shorter motion on X axis
            if (xMotion / direction.Dx < yMotion / direction.Dy)
            {
                yMotion = xMotion * direction.Dy / direction.Dx;
                Debug.Assert(Fuzzy.Abs(yMotion) > 0);
                Debug.Assert(Fuzzy.Abs(yMotion) <= 0.5);
            }
            // shorter motion on Y axis
            else if (xMotion / direction.Dx > yMotion / direction.Dy)
            {
                xMotion = yMotion * direction.Dx / direction.Dy;
                Debug.Assert(Fuzzy.Abs(xMotion) > 0);
                Debug.Assert(Fuzzy.Abs(xMotion) <= 0.5);
            }

            Debug.Assert(yMotion / xMotion == direction.Dy / direction.Dx);

            newPosition = new Position(x + xMotion, y + yMotion);

            return Fuzzy.Sqrt(xMotion * xMotion + yMotion * yMotion);
        }
Exemplo n.º 2
0
        public bool SolveDirection(Direction direction)
        {
            var distance = new Fuzzy(0.0);
            var position = startPosition;

            Log("----");

            while (true)
            {
                Log("(X ; Y) = ({0} ; {1})", position.X, position.Y);
                Log("(dX ; dY) = ({0} ; {1})", direction.Dx, direction.Dy);

                distance += position.MoveAlong(direction, step, out position);

                if (distance > maxDistance)
                {
                    Log("Max distance reached");
                    return false;
                }

                if (position.Equals(startPosition))
                {
                    Log("Start position reached !!!");
                    return true;
                }

                bool reflectionOnX, reflectionOnY;
                var xOnGrid = Fuzzy.Floor(position.X);
                var yOnGrid = Fuzzy.Floor(position.Y);

                Log("(X ; Y) = ({0} ; {1})", position.X, position.Y);

                var isOnHorizontalGrid = position.Y == yOnGrid;
                var isOnVerticalGrid = position.X == xOnGrid;

                Log("isOnHorizontalGrid = {0}", isOnHorizontalGrid);
                Log("isOnVerticalGrid = {0}", isOnVerticalGrid);

                if (isOnHorizontalGrid && isOnVerticalGrid)
                {
                    var mirrorOnUpperLeft = IsMirrorAt(position.X - step, position.Y - step);
                    var mirrorOnUpperRight = IsMirrorAt(position.X + step, position.Y - step);
                    var mirrorOnLowerLeft = IsMirrorAt(position.X - step, position.Y + step);
                    var mirrorOnLowerRight = IsMirrorAt(position.X + step, position.Y + step);

                    // we can't possibly be in the middle of 4 mirrors
                    Debug.Assert(!(mirrorOnUpperLeft&&mirrorOnUpperRight&&mirrorOnLowerLeft&&mirrorOnLowerRight));

                    reflectionOnX =
                        mirrorOnUpperLeft && mirrorOnLowerLeft ||
                        mirrorOnUpperRight && mirrorOnLowerRight;

                    reflectionOnY =
                        mirrorOnUpperLeft && mirrorOnUpperRight ||
                        mirrorOnLowerLeft && mirrorOnLowerRight;
                }
                else if (isOnHorizontalGrid)
                {
                    var mirrorAbove = IsMirrorAt(position.X, position.Y - step);
                    var mirrorBelow = IsMirrorAt(position.X, position.Y + step);

                    reflectionOnY = mirrorAbove || mirrorBelow;
                    reflectionOnX = false;
                }
                else if (isOnVerticalGrid)
                {
                    var mirrorOnLeft = IsMirrorAt(position.X - step, position.Y);
                    var mirrorOnRight = IsMirrorAt(position.X + step, position.Y);

                    reflectionOnX = mirrorOnLeft || mirrorOnRight;
                    reflectionOnY = false;
                }
                else if (IsMirrorAt(position.X, position.Y))
                {
                    Log("ray is destroyed");
                    return false;
                }
                else
                {
                    reflectionOnY = false;
                    reflectionOnX = false;
                }

                if (position.X <= 1 || position.X >= grid.GetLength(0) - 1) Debug.Assert(reflectionOnX);
                if (position.Y <= 1 || position.Y >= grid.GetLength(1) - 1) Debug.Assert(reflectionOnY);
                if (reflectionOnX) Log("reflection on Y");
                if (reflectionOnY) Log("reflection on Y");

                direction = new Direction(
                    direction.Dx * (reflectionOnX ? -1 : 1),
                    direction.Dy * (reflectionOnY ? -1 : 1));
            }
        }