Exemplo n.º 1
0
        /// <summary>
        /// Calculate the list of rects that need to be updated when moving a clip level from one source area to another.
        /// </summary>
        /// <param name="oldData">The area the clip level is moving from.</param>
        /// <param name="newData">The area the clip level is moving to.</param>
        /// <returns>A list of rectangles that need to be updated.</returns>
        protected List<RectangleI> _CalculateModuloDeltaBounds(RectangleI oldData, RectangleI newData)
        {
            // sanity checking
            Assert.Fatal(oldData.Point.X >= 0 && oldData.Point.Y >= 0 && oldData.IsValid, "ClipMap.CalculateModuloDeltaBounds - Negative oldData origin or bad rect.");
            Assert.Fatal(newData.Point.X >= 0 && newData.Point.Y >= 0 && newData.IsValid, "ClipMap.CalculateModuloDeltaBounds - Negative newData origin or bad rect.");
            Assert.Fatal(newData.Extent == oldData.Extent, "ClipMap.CalculateModuloDeltaBounts - Mismatching extents, can only work with matching extents.");

            _updateRectList.Clear();

            // easiest case - if they're the same then do nothing
            if (oldData.Point == newData.Point)
                return _updateRectList;

            // easy case - if there's no overlap then it's all new
            if (!oldData.Overlaps(newData))
            {
                // clip out to return buffer, and we're done
                _ClipAgainstGrid(_clipMapSize, newData, ref _updateRectList);
                return _updateRectList;
            }

            // calculate some useful values for both X and Y. delta is used a lot
            // in determining bounds, and the boundary values are important for
            // determining where to start copying new data in.
            int xDelta = newData.Point.X - oldData.Point.X;
            int yDelta = newData.Point.Y - oldData.Point.Y;

            int xBoundary = (oldData.Point.X + oldData.Extent.X) % _clipMapSize;
            int yBoundary = (oldData.Point.Y + oldData.Extent.Y) % _clipMapSize;

            Assert.Fatal(xBoundary % _clipMapSize == oldData.Point.X % _clipMapSize, "ClipMap.CalculateModuleDeltaBounds - We assume that left and right of the dataset are identical (ie, it's periodical on size of clipmap!) (x)");
            Assert.Fatal(yBoundary % _clipMapSize == oldData.Point.Y % _clipMapSize, "ClipMap.CalculateModuleDeltaBounds - We assume that left and right of the dataset are identical (ie, it's periodical on size of clipmap!) (y)");

            // now, let's build up our rects. we have one rect if we are moving
            // on the X or Y axis, two if both. we dealt with the no-move case
            // previously.
            if (xDelta == 0)
            {
                // moving on Y! so generate and store clipped results.
                RectangleI yRect = new RectangleI();

                if (yDelta < 0)
                {
                    // we need to generate the box from right of old to right of new
                    yRect.Point = newData.Point;
                    yRect.Extent = new Point(_clipMapSize, -yDelta);
                }
                else
                {
                    // we need to generate the box from left of old to left of new
                    yRect.Point = new Point(newData.Point.X, (oldData.Point.Y + oldData.Extent.Y));
                    yRect.Extent = new Point(_clipMapSize, yDelta);
                }

                // clip out to return buffer, and we're done
                _ClipAgainstGrid(_clipMapSize, yRect, ref _updateRectList);

                return _updateRectList;
            }
            else if (yDelta == 0)
            {
                // moving on X! So generate and store clipped results.
                RectangleI xRect = new RectangleI();

                if (xDelta < 0)
                {
                    // We need to generate the box from right of old to right of new.
                    xRect.Point = newData.Point;
                    xRect.Extent = new Point(-xDelta, _clipMapSize);
                }
                else
                {
                    // we need to generate the box from left of old to left of new.
                    xRect.Point = new Point((oldData.Point.X + oldData.Extent.X), newData.Point.Y);
                    xRect.Extent = new Point(xDelta, _clipMapSize);
                }

                // clip out to return buffer, and we're done
                _ClipAgainstGrid(_clipMapSize, xRect, ref _updateRectList);

                return _updateRectList;
            }
            else
            {
                // Both! We have an L shape. So let's do the bulk of it in one rect,
                // and the remainder in the other. We'll choose X as the dominant axis.
                //
                // a-----b---------c   going from e to a.
                // |     |         |
                // |     |         |
                // d-----e---------f   So the dominant rect is abgh and the passive
                // |     |         |   rect is bcef. Obviously depending on delta we
                // |     |         |   have to switch things around a bit.
                // |     |         |          y+ ^
                // |     |         |             |
                // g-----h---------i   x+->      |

                RectangleI xRect = new RectangleI();
                RectangleI yRect = new RectangleI();

                if (xDelta < 0)
                {
                    // case in the diagram
                    xRect.Point = newData.Point;
                    xRect.Extent = new Point(-xDelta, _clipMapSize);

                    // set up what of yRect we know too
                    yRect.Point = new Point(xRect.Point.X + xRect.Extent.X, 0);
                    yRect.Extent = new Point(_clipMapSize + xDelta, 0);
                }
                else
                {
                    // opposite of case in diagram
                    xRect.Point = new Point(oldData.Point.X + oldData.Extent.X, newData.Point.Y);
                    xRect.Extent = new Point(xDelta, _clipMapSize);

                    // set up what of yRect we know too
                    yRect.Point = new Point((xRect.Point.X + xRect.Extent.X) - _clipMapSize, 0);
                    yRect.Extent = new Point(_clipMapSize - xRect.Extent.X, 0);
                }

                if (yDelta < 0)
                {
                    // case in the diagram.
                    yRect.Point = new Point(yRect.Point.X, newData.Point.Y);
                    yRect.Extent = new Point(yRect.Extent.X, -yDelta);
                }
                else
                {
                    // case in the diagram.
                    yRect.Point = new Point(yRect.Point.X, oldData.Point.Y + oldData.Extent.Y);
                    yRect.Extent = new Point(yRect.Extent.X, yDelta);
                }

                // make sure we don't overlap.
                Assert.Fatal(!yRect.Overlaps(xRect), "ClipMap.CalculateModuloDeltaBounds() - overlap in result rects - should not happen!");

                // now run them through the clipper and we're done
                _ClipAgainstGrid(_clipMapSize, xRect, ref _updateRectList);
                _ClipAgainstGrid(_clipMapSize, yRect, ref _updateRectList);

                return _updateRectList;
            }
        }