예제 #1
0
        /// <summary>
        /// Enlarges the boundary of the <c>Envelope</c> so that it contains (p).
        /// Does nothing if (p) is already on or within the boundaries.
        /// This executes to the minimum of dimensions between p and this envelope.
        /// </summary>
        /// <param name="self">The first envelope (this object when extending)</param>
        /// <param name="p">The Coordinate.</param>
        public static void ExpandToInclude(this IEnvelope self, Coordinate p)
        {
            if (self == null)
            {
                return;
            }
            if (self.IsNull)
            {
                self.Init(p, p);
                return;
            }
            int        numDimensions = Math.Min(self.NumOrdinates, p.NumOrdinates);
            Coordinate min           = self.Minimum;
            Coordinate max           = self.Maximum;

            for (int i = 0; i < numDimensions; i++)
            {
                if (p[i] < min[i])
                {
                    min[i] = p[i];
                }
                if (p[i] > max[i])
                {
                    max[i] = p[i];
                }
            }
            self.Init(min, max); // this is to ensure we don't break the min/max relationships.
        }
예제 #2
0
        /// <summary>
        /// Translates the envelope by given amounts up to the minimum dimension between
        /// the envelope and the shift coordinate.  (e.g., A 2D envelope will only
        /// be shifted in 2 dimensions because it has no Z, while a 2D coordinate
        /// can only shift a cube based on the X and Y positions, leaving the Z
        /// info alone.
        /// </summary>
        /// <param name="self">The IEnvelope to use with this method</param>
        /// <param name="shift"></param>
        /// <remarks>This does nothing to a "NULL" envelope</remarks>
        public static void Translate(this IEnvelope self, Coordinate shift)
        {
            if (self == null)
            {
                return;
            }
            if (self.IsNull)
            {
                return;
            }
            if (shift == null)
            {
                return;
            }
            Coordinate min           = self.Minimum;
            Coordinate max           = self.Maximum;
            int        numDimensions = Math.Min(self.NumOrdinates, shift.NumOrdinates);

            for (int i = 0; i < numDimensions; i++)
            {
                min[i] += shift[i];
                max[i] += shift[i];
            }
            self.Init(min, max);
        }
예제 #3
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="level"></param>
        /// <param name="itemEnv"></param>
        private void ComputeKey(int level, IEnvelope itemEnv)
        {
            double quadSize = DoubleBits.PowerOf2(level);

            pt.X = Math.Floor(itemEnv.MinX / quadSize) * quadSize;
            pt.Y = Math.Floor(itemEnv.MinY / quadSize) * quadSize;
            env.Init(pt.X, pt.X + quadSize, pt.Y, pt.Y + quadSize);
        }
예제 #4
0
        /// <summary>
        /// The two dimensional overload for consistency with other code.
        /// Despite the names, this will force the smallest X coordinate given
        /// to become maxX.
        /// </summary>
        /// <param name="self">The IEnvelope to use with this method</param>
        /// <param name="minX">An X coordinate</param>
        /// <param name="minY">A Y coordinate</param>
        /// <param name="maxX">Another X coordinate</param>
        /// <param name="maxY">Another Y coordinate</param>
        public static void SetExtents(this IEnvelope self, double minX, double minY, double maxX, double maxY)
        {
            if (self == null)
            {
                return;
            }
            Coordinate min = new Coordinate(minX, minY);
            Coordinate max = new Coordinate(maxX, maxY);

            self.Init(min, max);
        }
예제 #5
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="start0"></param>
        /// <param name="end0"></param>
        /// <param name="mce"></param>
        /// <param name="start1"></param>
        /// <param name="end1"></param>
        /// <param name="ei"></param>
        private void ComputeIntersectsForChain(int start0, int end0, MonotoneChainEdge mce, int start1, int end1, SegmentIntersector ei)
        {
            ICoordinate p00 = pts[start0];
            ICoordinate p01 = pts[end0];
            ICoordinate p10 = mce.pts[start1];
            ICoordinate p11 = mce.pts[end1];

            // terminating condition for the recursion
            if (end0 - start0 == 1 && end1 - start1 == 1)
            {
                ei.AddIntersections(e, start0, mce.e, start1);
                return;
            }

            // nothing to do if the envelopes of these chains don't overlap
            env1.Init(p00, p01);
            env2.Init(p10, p11);
            if (!env1.Intersects(env2))
            {
                return;
            }

            // the chains overlap, so split each in half and iterate  (binary search)
            int mid0 = (start0 + end0) / 2;
            int mid1 = (start1 + end1) / 2;

            // check terminating conditions before recursing
            if (start0 < mid0)
            {
                if (start1 < mid1)
                {
                    ComputeIntersectsForChain(start0, mid0, mce, start1, mid1, ei);
                }
                if (mid1 < end1)
                {
                    ComputeIntersectsForChain(start0, mid0, mce, mid1, end1, ei);
                }
            }
            if (mid0 < end0)
            {
                if (start1 < mid1)
                {
                    ComputeIntersectsForChain(mid0, end0, mce, start1, mid1, ei);
                }
                if (mid1 < end1)
                {
                    ComputeIntersectsForChain(mid0, end0, mce, mid1, end1, ei);
                }
            }
        }
예제 #6
0
        /// <summary>
        /// Enlarges the boundary of the <c>Envelope</c> so that it contains
        /// <c>other</c>. Does nothing if <c>other</c> is wholly on or
        /// within the boundaries.
        /// </summary>
        /// <param name="self">The first envelope (this object when extending)</param>
        /// <param name="other">the <c>Envelope</c> to merge with.</param>
        public static void ExpandToInclude(this IEnvelope self, IEnvelope other)
        {
            if (self == null)
            {
                return;
            }
            if (other == null)
            {
                return;
            }
            if (other.IsNull)
            {
                return;
            }
            if (self.IsNull)
            {
                self.Init(other.Minimum, other.Maximum);
                return;
            }
            int numDimensions = Math.Min(self.NumOrdinates, other.NumOrdinates);

            Coordinate min = self.Minimum;
            Coordinate max = self.Maximum;

            for (int i = 0; i < numDimensions; i++)
            {
                if (other.Minimum[i] < min[i])
                {
                    min[i] = other.Minimum[i];
                }
                if (other.Maximum[i] > max[i])
                {
                    max[i] = other.Maximum[i];
                }
            }
            self.Init(min, max); // re-initialize to prevent sign errors and indicate a change.
        }
예제 #7
0
        /// <summary>
        /// Uses the dimensions of the specified distances coordinate to
        /// specify the amount to expand the envelopes in each ordinate.
        /// This will apply the method to the minimum dimensions between
        /// the distances coordinate and this envelope.  (eg. A 2D
        /// distances coordinate will not affect Z values in the envelope).
        /// </summary>
        /// <param name="self">The first envelope (this object when extending)</param>
        /// <param name="distances">The distance to expand the envelope.</param>
        public static void ExpandBy(this IEnvelope self, Coordinate distances)
        {
            if (self == null)
            {
                return;
            }
            int        numDimensions = Math.Min(self.NumOrdinates, distances.NumOrdinates);
            Coordinate min           = self.Minimum;
            Coordinate max           = self.Maximum;

            for (int i = 0; i < numDimensions; i++)
            {
                min[i] -= distances[i];
                max[i] += distances[i];
            }
            self.Init(min, max); // this is important in case negative values are used, and
            // the maximum is now the minimum etc.
        }
예제 #8
0
        /// <summary>
        /// This handles setting the center and scale in N dimensions.  The size is equivalent to the
        /// span in each dimension, while the center is the central position in each dimension.  The
        /// envelope will have values in each dimension where either the existing envelope or both the
        /// specified center and size values have been specified.  If only the existing envelope
        /// and a size is specified for dimension 3, for example, the existing center will be used.
        /// </summary>
        /// <param name="self">The envelope to modify</param>
        /// <param name="center">The center position.  This can also be null.</param>
        /// <param name="size">The size (or span) in each dimension.  This can also be null.</param>
        public static void SetCenter(this IEnvelope self, Coordinate center, Coordinate size)
        {
            int centerDimensions = 0;
            int sizeDimensions   = 0;

            if (self == null)
            {
                return;
            }
            if (center != null)
            {
                centerDimensions = center.NumOrdinates;
            }
            if (size != null)
            {
                sizeDimensions = size.NumOrdinates;
            }
            int numDimensionsCenterAndSize = Math.Min(centerDimensions, sizeDimensions);

            int        numDimensions = Math.Max(self.NumOrdinates, numDimensionsCenterAndSize);
            Coordinate min           = new Coordinate();
            Coordinate max           = new Coordinate();

            for (int i = 0; i < numDimensions; i++)
            {
                if (centerDimensions > i && sizeDimensions > i)
                {
                    // we have completely new information for this dimension
                    if (center != null)
                    {
                        if (size != null)
                        {
                            min[i] = center[i] - size[i] / 2;
                            max[i] = center[i] + size[i] / 2;
                        }
                    }
                }
                if (centerDimensions <= i && sizeDimensions <= i)
                {
                    // we have no new information at all, so just use the existing envelope
                    min[i] = self.Minimum[i];
                    max[i] = self.Maximum[i];
                }
                if (centerDimensions > i && sizeDimensions <= i)
                {
                    // We have a center specified in this dimension, but not a size, so keep the old size
                    double oldSize = self.Maximum[i] - self.Minimum[i];
                    if (center != null)
                    {
                        min[i] = center[i] - oldSize / 2;
                        max[i] = center[i] + oldSize / 2;
                    }
                }
                if (centerDimensions <= i && sizeDimensions > i)
                {
                    // We have a size specified in this dimension, but not any center information, so use the old center.
                    double oldCenter = (self.Minimum[i] + self.Maximum[i]) / 2;
                    if (size != null)
                    {
                        min[i] = oldCenter - size[i];
                        max[i] = oldCenter + size[i];
                    }
                }
            }
            self.Init(min, max);
        }