Example #1
0
        /// <summary>
        /// Changes the envelope extent by the specified amount relative
        /// to it's current extent in that dimension (preserving the aspect ratio).
        /// So Zoom(10) on a 100 unit wide envelope creates a 110 unit wide envlope,
        /// while Zoom(-10) on a 100 unit wide envelope creates a 90 unit wide envelope.
        /// Zoom(-100) on an envelope makes it 100% smaller, or effectively a point.
        /// Tragically, a point cannot be "zoomed" back in, so a check should be used
        /// to ensure that the envelope is not currently a point before attempting
        /// to zoom in.
        /// </summary>
        /// <param name="self">The IEnvelope that this zoom method modifies</param>
        /// <param name="percent">
        /// Positive 50 makes the envelope 50% larger
        /// Negative 50 makes the envelope 50% smaller
        /// </param>
        /// <example>
        ///  perCent = -50 compact the envelope a 50% (make it smaller).
        ///  perCent = 200 enlarge envelope by 2.
        /// </example>
        public static void Zoom(this IEnvelope self, double percent)
        {
            if (self == null)
            {
                return;
            }
            if (self.IsNull)
            {
                return;
            }
            double     ratio = percent / 100;
            Coordinate size  = new Coordinate();

            for (int i = 0; i < self.NumOrdinates; i++)
            {
                double oldSize = self.Maximum[i] - self.Minimum[i];
                size[i] = oldSize + ratio * oldSize;
            }
            SetCenter(self, self.Center(), size);
        }
Example #2
0
        /// <summary>
        /// The original algorithm simply allows edges that have one defined point and
        /// another "NAN" point.  Simply excluding the not a number coordinates fails
        /// to preserve the known direction of the ray.  We only need to extend this
        /// long enough to encounter the bounding box, not infinity.
        /// </summary>
        /// <param name="graph">The VoronoiGraph with the edge list.</param>
        /// <param name="bounds">The polygon bounding the datapoints.</param>
        private static void HandleBoundaries(VoronoiGraph graph, IEnvelope bounds)
        {
            List <ILineString> boundSegments = new List <ILineString>();
            List <VoronoiEdge> unboundEdges  = new List <VoronoiEdge>();

            // Identify bound edges for intersection testing
            foreach (VoronoiEdge edge in graph.Edges)
            {
                if (edge.VVertexA.ContainsNan() || edge.VVertexB.ContainsNan())
                {
                    unboundEdges.Add(edge);
                    continue;
                }

                boundSegments.Add(
                    new LineString(new List <Coordinate> {
                    edge.VVertexA.ToCoordinate(), edge.VVertexB.ToCoordinate()
                }));
            }

            // calculate a length to extend a ray to look for intersections
            IEnvelope env = bounds;
            double    h   = env.Height;
            double    w   = env.Width;
            double    len = Math.Sqrt((w * w) + (h * h));

            // len is now long enough to pass entirely through the dataset no matter where it starts

            foreach (VoronoiEdge edge in unboundEdges)
            {
                // the unbound line passes thorugh start
                Coordinate start = (edge.VVertexB.ContainsNan())
                                       ? edge.VVertexA.ToCoordinate()
                                       : edge.VVertexB.ToCoordinate();

                // the unbound line should have a direction normal to the line joining the left and right source points
                double dx = edge.LeftData.X - edge.RightData.X;
                double dy = edge.LeftData.Y - edge.RightData.Y;
                double l  = Math.Sqrt((dx * dx) + (dy * dy));

                // the slope of the bisector between left and right
                double sx = -dy / l;
                double sy = dx / l;

                Coordinate center = bounds.Center();
                if ((start.X > center.X && start.Y > center.Y) || (start.X < center.X && start.Y < center.Y))
                {
                    sx = dy / l;
                    sy = -dx / l;
                }

                Coordinate end1 = new Coordinate(start.X + (len * sx), start.Y + (len * sy));
                Coordinate end2 = new Coordinate(start.X - (sx * len), start.Y - (sy * len));
                Coordinate end  = (end1.Distance(center) < end2.Distance(center)) ? end2 : end1;
                if (bounds.Contains(end))
                {
                    end = new Coordinate(start.X - (sx * len), start.Y - (sy * len));
                }

                if (edge.VVertexA.ContainsNan())
                {
                    edge.VVertexA = new Vector2(end.ToArray());
                }
                else
                {
                    edge.VVertexB = new Vector2(end.ToArray());
                }
            }
        }
Example #3
0
        /// <summary>
        /// The original algorithm simply allows edges that have one defined point and 
        /// another "NAN" point.  Simply excluding the not a number coordinates fails
        /// to preserve the known direction of the ray.  We only need to extend this
        /// long enough to encounter the bounding box, not infinity.
        /// </summary>
        /// <param name="graph">The VoronoiGraph with the edge list</param>
        /// <param name="bounds">The polygon bounding the datapoints</param>
        private static void HandleBoundaries(VoronoiGraph graph, IEnvelope bounds)
        {
            
            List<ILineString> boundSegments = new List<ILineString>();
            List<VoronoiEdge> unboundEdges = new List<VoronoiEdge>();
            // Identify bound edges for intersection testing
            foreach (VoronoiEdge edge in graph.Edges)
            {
                if(edge.VVertexA.ContainsNan() || edge.VVertexB.ContainsNan())
                {
                    unboundEdges.Add(edge);
                    continue;
                }
                boundSegments.Add(new LineString(new List<Coordinate>{edge.VVertexA.ToCoordinate(), edge.VVertexB.ToCoordinate()}));
            }

            // calculate a length to extend a ray to look for intersections
            IEnvelope env = bounds;
            double h = env.Height;
            double w = env.Width;
            double len = Math.Sqrt(w * w + h * h);  // len is now long enough to pass entirely through the dataset no matter where it starts

            foreach (VoronoiEdge edge in unboundEdges)
            {
                // the unbound line passes thorugh start
                Coordinate start = (edge.VVertexB.ContainsNan())
                                        ? edge.VVertexA.ToCoordinate()
                                        : edge.VVertexB.ToCoordinate();

                // the unbound line should have a direction normal to the line joining the left and right source points
                double dx = edge.LeftData.X - edge.RightData.X;
                double dy = edge.LeftData.Y - edge.RightData.Y;
                double l = Math.Sqrt(dx*dx + dy*dy);

                

                // the slope of the bisector between left and right
                double sx = -dy/l;
                double sy = dx/l;

                Coordinate center = bounds.Center();
                if((start.X > center.X && start.Y > center.Y) || (start.X < center.X && start.Y < center.Y))
                {
                    sx = dy/l;
                    sy = -dx/l;
                }

                Coordinate end1 = new Coordinate(start.X + len*sx, start.Y + len * sy);
                Coordinate end2 = new Coordinate(start.X - sx * len, start.Y - sy * len);
                
                Coordinate end = (end1.Distance(center) < end2.Distance(center)) ? end2 : end1;
                if(bounds.Contains(end))
                {
                    end = new Coordinate(start.X - sx * len, start.Y - sy * len);
                }
                if (edge.VVertexA.ContainsNan())
                {
                    edge.VVertexA = new Vector2(end.ToArray());
                }
                else
                {
                    edge.VVertexB = new Vector2(end.ToArray());
                }
                
                
                
                
            }
            
        }