public void WindingNumberAlgorithmLocationTest()
        {
            // simple convex polygon
            Coordinate[] polygon = new Coordinate[]
            {
                new Coordinate(0, 0),
                new Coordinate(10, 0),
                new Coordinate(10, 10),
                new Coordinate(0, 10),
                new Coordinate(0, 0),
            };

            WindingNumberAlgorithm.Location(polygon, new Coordinate(0, 5)).ShouldBe(RelativeLocation.Boundary);
            WindingNumberAlgorithm.Location(polygon, new Coordinate(10, 5)).ShouldBe(RelativeLocation.Boundary);
            WindingNumberAlgorithm.Location(polygon, new Coordinate(5, 0)).ShouldBe(RelativeLocation.Boundary);
            WindingNumberAlgorithm.Location(polygon, new Coordinate(10, 10)).ShouldBe(RelativeLocation.Boundary);
            WindingNumberAlgorithm.Location(polygon, new Coordinate(5, 5)).ShouldBe(RelativeLocation.Interior);
            WindingNumberAlgorithm.Location(polygon, new Coordinate(15, 5)).ShouldBe(RelativeLocation.Exterior);
            WindingNumberAlgorithm.Location(polygon, new Coordinate(0, 5)).ShouldBe(RelativeLocation.Boundary);

            // simple convex polygon with negative coordinates
            polygon = new Coordinate[]
            {
                new Coordinate(0, 0),
                new Coordinate(10, -5),
                new Coordinate(10, 15),
                new Coordinate(0, 10),
                new Coordinate(0, 0),
            };

            WindingNumberAlgorithm.Location(polygon, new Coordinate(5, 12.5)).ShouldBe(RelativeLocation.Boundary);
            WindingNumberAlgorithm.Location(polygon, new Coordinate(5, 10)).ShouldBe(RelativeLocation.Interior);
            WindingNumberAlgorithm.Location(polygon, new Coordinate(-5, 0)).ShouldBe(RelativeLocation.Exterior);
        }
示例#2
0
        /// <summary>
        /// Determines whether the area contains a geographic coordinate.
        /// </summary>
        /// <param name="coordinate">The coordinate.</param>
        /// <returns><c>true</c> if the coordinate is within the area; otherwise, <c>false</c>.</returns>
        public Boolean Contains(GeoCoordinate coordinate)
        {
            if (coordinate == null)
            {
                return(false);
            }

            // if the boundary is specified, the contained can be determined more exactly
            if (this.Boundary != null)
            {
                return(!WindingNumberAlgorithm.InExterior(this.Boundary.Select(coord => (Coordinate)coord).ToArray(), (Coordinate)coordinate));
            }

            return((this.West <= this.East && this.West <= coordinate.Latitude && coordinate.Latitude <= this.East) ||
                   (this.West > this.East && ((this.West - Angle.FromRadian(2 * Math.PI) <= coordinate.Latitude && coordinate.Latitude <= this.East) ||
                                              (this.West <= coordinate.Latitude && coordinate.Latitude <= this.East + Angle.FromRadian(2 * Math.PI)))));
        }
        public void WindingNumberAlgorithmLocationCheckingTest()
        {
            // simple polygon

            Coordinate[] shell = new Coordinate[]
            {
                new Coordinate(0, 0),
                new Coordinate(20, 0),
                new Coordinate(15, 5),
                new Coordinate(20, 10),
                new Coordinate(0, 20),
                new Coordinate(0, 0),
            };

            Coordinate coordinate = new Coordinate(-1, 7);
            WindingNumberAlgorithm.InInterior(shell, coordinate).ShouldBeFalse();
            WindingNumberAlgorithm.InExterior(shell, coordinate).ShouldBeTrue();
            WindingNumberAlgorithm.OnBoundary(shell, coordinate).ShouldBeFalse();

            coordinate = new Coordinate(0, 0);
            WindingNumberAlgorithm.InInterior(shell, coordinate).ShouldBeFalse();
            WindingNumberAlgorithm.InExterior(shell, coordinate).ShouldBeFalse();
            WindingNumberAlgorithm.OnBoundary(shell, coordinate).ShouldBeTrue();

            coordinate = new Coordinate(0, 5);
            WindingNumberAlgorithm.InInterior(shell, coordinate).ShouldBeFalse();
            WindingNumberAlgorithm.InExterior(shell, coordinate).ShouldBeFalse();
            WindingNumberAlgorithm.OnBoundary(shell, coordinate).ShouldBeTrue();

            coordinate = new Coordinate(1, 1);
            WindingNumberAlgorithm.InInterior(shell, coordinate).ShouldBeTrue();
            WindingNumberAlgorithm.InExterior(shell, coordinate).ShouldBeFalse();
            WindingNumberAlgorithm.OnBoundary(shell, coordinate).ShouldBeFalse();

            coordinate = new Coordinate(3, 3);
            WindingNumberAlgorithm.InInterior(shell, coordinate).ShouldBeTrue();
            WindingNumberAlgorithm.InExterior(shell, coordinate).ShouldBeFalse();
            WindingNumberAlgorithm.OnBoundary(shell, coordinate).ShouldBeFalse();

            coordinate = new Coordinate(5, 8);
            WindingNumberAlgorithm.InInterior(shell, coordinate).ShouldBeTrue();
            WindingNumberAlgorithm.InExterior(shell, coordinate).ShouldBeFalse();
            WindingNumberAlgorithm.OnBoundary(shell, coordinate).ShouldBeFalse();

            coordinate = new Coordinate(6, 0);
            WindingNumberAlgorithm.InInterior(shell, coordinate).ShouldBeFalse();
            WindingNumberAlgorithm.InExterior(shell, coordinate).ShouldBeFalse();
            WindingNumberAlgorithm.OnBoundary(shell, coordinate).ShouldBeTrue();

            coordinate = new Coordinate(8, 4);
            WindingNumberAlgorithm.InInterior(shell, coordinate).ShouldBeTrue();
            WindingNumberAlgorithm.InExterior(shell, coordinate).ShouldBeFalse();
            WindingNumberAlgorithm.OnBoundary(shell, coordinate).ShouldBeFalse();

            coordinate = new Coordinate(8, 22);
            WindingNumberAlgorithm.InInterior(shell, coordinate).ShouldBeFalse();
            WindingNumberAlgorithm.InExterior(shell, coordinate).ShouldBeTrue();
            WindingNumberAlgorithm.OnBoundary(shell, coordinate).ShouldBeFalse();

            coordinate = new Coordinate(12, -2);
            WindingNumberAlgorithm.InInterior(shell, coordinate).ShouldBeFalse();
            WindingNumberAlgorithm.InExterior(shell, coordinate).ShouldBeTrue();
            WindingNumberAlgorithm.OnBoundary(shell, coordinate).ShouldBeFalse();

            coordinate = new Coordinate(12, 8);
            WindingNumberAlgorithm.InInterior(shell, coordinate).ShouldBeTrue();
            WindingNumberAlgorithm.InExterior(shell, coordinate).ShouldBeFalse();
            WindingNumberAlgorithm.OnBoundary(shell, coordinate).ShouldBeFalse();

            coordinate = new Coordinate(15, 5);
            WindingNumberAlgorithm.InInterior(shell, coordinate).ShouldBeFalse();
            WindingNumberAlgorithm.InExterior(shell, coordinate).ShouldBeFalse();
            WindingNumberAlgorithm.OnBoundary(shell, coordinate).ShouldBeTrue();

            coordinate = new Coordinate(15, 9);
            WindingNumberAlgorithm.InInterior(shell, coordinate).ShouldBeTrue();
            WindingNumberAlgorithm.InExterior(shell, coordinate).ShouldBeFalse();
            WindingNumberAlgorithm.OnBoundary(shell, coordinate).ShouldBeFalse();

            coordinate = new Coordinate(16, 1);
            WindingNumberAlgorithm.InInterior(shell, coordinate).ShouldBeTrue();
            WindingNumberAlgorithm.InExterior(shell, coordinate).ShouldBeFalse();
            WindingNumberAlgorithm.OnBoundary(shell, coordinate).ShouldBeFalse();

            coordinate = new Coordinate(19, 3);
            WindingNumberAlgorithm.InInterior(shell, coordinate).ShouldBeFalse();
            WindingNumberAlgorithm.InExterior(shell, coordinate).ShouldBeTrue();
            WindingNumberAlgorithm.OnBoundary(shell, coordinate).ShouldBeFalse();

            // polygon with holes

            shell = new Coordinate[]
            {
                new Coordinate(0, 0),
                new Coordinate(20, 0),
                new Coordinate(15, 5),
                new Coordinate(20, 10),
                new Coordinate(0, 20),
                new Coordinate(0, 0),
            };

            Coordinate[] hole1 = new Coordinate[]
            {
                new Coordinate(2, 2),
                new Coordinate(2, 4),
                new Coordinate(4, 4),
                new Coordinate(4, 2),
                new Coordinate(2, 2),
            };
            Coordinate[] hole2 = new Coordinate[]
            {
                new Coordinate(10, 7),
                new Coordinate(10, 9),
                new Coordinate(16, 9),
                new Coordinate(16, 7),
                new Coordinate(10, 7),
            };

            coordinate = new Coordinate(-1, 7);
            WindingNumberAlgorithm.InInterior(shell, new[] { hole1, hole2 }, coordinate).ShouldBeFalse();
            WindingNumberAlgorithm.InExterior(shell, new[] { hole1, hole2 }, coordinate).ShouldBeTrue();
            WindingNumberAlgorithm.OnBoundary(shell, new[] { hole1, hole2 }, coordinate).ShouldBeFalse();

            coordinate = new Coordinate(0, 0);
            WindingNumberAlgorithm.InInterior(shell, new[] { hole1, hole2 }, coordinate).ShouldBeFalse();
            WindingNumberAlgorithm.InExterior(shell, new[] { hole1, hole2 }, coordinate).ShouldBeFalse();
            WindingNumberAlgorithm.OnBoundary(shell, new[] { hole1, hole2 }, coordinate).ShouldBeTrue();

            coordinate = new Coordinate(0, 5);
            WindingNumberAlgorithm.InInterior(shell, new[] { hole1, hole2 }, coordinate).ShouldBeFalse();
            WindingNumberAlgorithm.InExterior(shell, new[] { hole1, hole2 }, coordinate).ShouldBeFalse();
            WindingNumberAlgorithm.OnBoundary(shell, new[] { hole1, hole2 }, coordinate).ShouldBeTrue();

            coordinate = new Coordinate(1, 1);
            WindingNumberAlgorithm.InInterior(shell, new[] { hole1, hole2 }, coordinate).ShouldBeTrue();
            WindingNumberAlgorithm.InExterior(shell, new[] { hole1, hole2 }, coordinate).ShouldBeFalse();
            WindingNumberAlgorithm.OnBoundary(shell, new[] { hole1, hole2 }, coordinate).ShouldBeFalse();

            coordinate = new Coordinate(3, 3);
            WindingNumberAlgorithm.InInterior(shell, new[] { hole1, hole2 }, coordinate).ShouldBeFalse();
            WindingNumberAlgorithm.InExterior(shell, new[] { hole1, hole2 }, coordinate).ShouldBeTrue();
            WindingNumberAlgorithm.OnBoundary(shell, new[] { hole1, hole2 }, coordinate).ShouldBeFalse();

            coordinate = new Coordinate(5, 8);
            WindingNumberAlgorithm.InInterior(shell, new[] { hole1, hole2 }, coordinate).ShouldBeTrue();
            WindingNumberAlgorithm.InExterior(shell, new[] { hole1, hole2 }, coordinate).ShouldBeFalse();
            WindingNumberAlgorithm.OnBoundary(shell, new[] { hole1, hole2 }, coordinate).ShouldBeFalse();

            coordinate = new Coordinate(6, 0);
            WindingNumberAlgorithm.InInterior(shell, new[] { hole1, hole2 }, coordinate).ShouldBeFalse();
            WindingNumberAlgorithm.InExterior(shell, new[] { hole1, hole2 }, coordinate).ShouldBeFalse();
            WindingNumberAlgorithm.OnBoundary(shell, new[] { hole1, hole2 }, coordinate).ShouldBeTrue();

            coordinate = new Coordinate(8, 4);
            WindingNumberAlgorithm.InInterior(shell, new[] { hole1, hole2 }, coordinate).ShouldBeTrue();
            WindingNumberAlgorithm.InExterior(shell, new[] { hole1, hole2 }, coordinate).ShouldBeFalse();
            WindingNumberAlgorithm.OnBoundary(shell, new[] { hole1, hole2 }, coordinate).ShouldBeFalse();

            coordinate = new Coordinate(8, 22);
            WindingNumberAlgorithm.InInterior(shell, new[] { hole1, hole2 }, coordinate).ShouldBeFalse();
            WindingNumberAlgorithm.InExterior(shell, new[] { hole1, hole2 }, coordinate).ShouldBeTrue();
            WindingNumberAlgorithm.OnBoundary(shell, new[] { hole1, hole2 }, coordinate).ShouldBeFalse();

            coordinate = new Coordinate(12, -2);
            WindingNumberAlgorithm.InInterior(shell, new[] { hole1, hole2 }, coordinate).ShouldBeFalse();
            WindingNumberAlgorithm.InExterior(shell, new[] { hole1, hole2 }, coordinate).ShouldBeTrue();
            WindingNumberAlgorithm.OnBoundary(shell, new[] { hole1, hole2 }, coordinate).ShouldBeFalse();

            coordinate = new Coordinate(12, 8);
            WindingNumberAlgorithm.InInterior(shell, new[] { hole1, hole2 }, coordinate).ShouldBeFalse();
            WindingNumberAlgorithm.InExterior(shell, new[] { hole1, hole2 }, coordinate).ShouldBeTrue();
            WindingNumberAlgorithm.OnBoundary(shell, new[] { hole1, hole2 }, coordinate).ShouldBeFalse();

            coordinate = new Coordinate(15, 5);
            WindingNumberAlgorithm.InInterior(shell, new[] { hole1, hole2 }, coordinate).ShouldBeFalse();
            WindingNumberAlgorithm.InExterior(shell, new[] { hole1, hole2 }, coordinate).ShouldBeFalse();
            WindingNumberAlgorithm.OnBoundary(shell, new[] { hole1, hole2 }, coordinate).ShouldBeTrue();

            coordinate = new Coordinate(15, 9);
            WindingNumberAlgorithm.InInterior(shell, new[] { hole1, hole2 }, coordinate).ShouldBeFalse();
            WindingNumberAlgorithm.InExterior(shell, new[] { hole1, hole2 }, coordinate).ShouldBeFalse();
            WindingNumberAlgorithm.OnBoundary(shell, new[] { hole1, hole2 }, coordinate).ShouldBeTrue();

            coordinate = new Coordinate(16, 1);
            WindingNumberAlgorithm.InInterior(shell, new[] { hole1, hole2 }, coordinate).ShouldBeTrue();
            WindingNumberAlgorithm.InExterior(shell, new[] { hole1, hole2 }, coordinate).ShouldBeFalse();
            WindingNumberAlgorithm.OnBoundary(shell, new[] { hole1, hole2 }, coordinate).ShouldBeFalse();

            coordinate = new Coordinate(19, 3);
            WindingNumberAlgorithm.InInterior(shell, new[] { hole1, hole2 }, coordinate).ShouldBeFalse();
            WindingNumberAlgorithm.InExterior(shell, new[] { hole1, hole2 }, coordinate).ShouldBeTrue();
            WindingNumberAlgorithm.OnBoundary(shell, new[] { hole1, hole2 }, coordinate).ShouldBeFalse();
        }
        public void WindingNumberAlgorithmIsInsidePolygonTest()
        {
            // simple convex polygon

            Coordinate[] shell = new Coordinate[]
            {
                new Coordinate(0, 0),
                new Coordinate(10, 0),
                new Coordinate(10, 10),
                new Coordinate(0, 10),
                new Coordinate(0, 0),
            };

            Assert.IsTrue(WindingNumberAlgorithm.IsInsidePolygon(shell, new Coordinate(5, 5)));
            Assert.IsFalse(WindingNumberAlgorithm.IsInsidePolygon(shell, new Coordinate(10, 5)));
            Assert.IsFalse(WindingNumberAlgorithm.IsInsidePolygon(shell, new Coordinate(15, 5)));


            // simple convex polygon with negative coordinates

            shell = new Coordinate[]
            {
                new Coordinate(0, 0),
                new Coordinate(10, -5),
                new Coordinate(10, 15),
                new Coordinate(0, 10),
                new Coordinate(0, 0),
            };

            Assert.IsTrue(WindingNumberAlgorithm.IsInsidePolygon(shell, new Coordinate(5, 5)));
            Assert.IsTrue(WindingNumberAlgorithm.IsInsidePolygon(shell, new Coordinate(5, 0)));
            Assert.IsTrue(WindingNumberAlgorithm.IsInsidePolygon(shell, new Coordinate(5, 10)));
            Assert.IsFalse(WindingNumberAlgorithm.IsInsidePolygon(shell, new Coordinate(-5, 0)));
            Assert.IsFalse(WindingNumberAlgorithm.IsInsidePolygon(shell, new Coordinate(-5, 10)));


            // convex polygon with holes

            shell = new Coordinate[]
            {
                new Coordinate(0, 0),
                new Coordinate(20, 0),
                new Coordinate(20, 20),
                new Coordinate(0, 20),
                new Coordinate(0, 0),
            };
            Coordinate[] hole1 = new Coordinate[]
            {
                new Coordinate(5, 5),
                new Coordinate(5, 10),
                new Coordinate(10, 10),
                new Coordinate(10, 5),
                new Coordinate(5, 5),
            };
            Coordinate[] hole2 = new Coordinate[]
            {
                new Coordinate(10, 10),
                new Coordinate(5, 15),
                new Coordinate(15, 15),
                new Coordinate(15, 10),
                new Coordinate(10, 10),
            };

            Assert.IsFalse(WindingNumberAlgorithm.IsInsidePolygon(shell, new List <Coordinate[]>()
            {
                hole1, hole2
            }, new Coordinate(10, 10)));
            Assert.IsTrue(WindingNumberAlgorithm.IsInsidePolygon(shell, new List <Coordinate[]>()
            {
                hole1, hole2
            }, new Coordinate(18, 8)));
            Assert.IsTrue(WindingNumberAlgorithm.IsInsidePolygon(shell, new List <Coordinate[]>()
            {
                hole1, hole2
            }, new Coordinate(12, 2)));
            Assert.IsFalse(WindingNumberAlgorithm.IsInsidePolygon(shell, new List <Coordinate[]>()
            {
                hole1, hole2
            }, new Coordinate(12, 12)));
            Assert.IsFalse(WindingNumberAlgorithm.IsInsidePolygon(shell, new List <Coordinate[]>()
            {
                hole1, hole2
            }, new Coordinate(8, 8)));


            // concave polygon

            shell = new Coordinate[]
            {
                new Coordinate(0, 0),
                new Coordinate(15, 0),
                new Coordinate(15, 5),
                new Coordinate(12, 5),
                new Coordinate(12, 7),
                new Coordinate(10, 7),
                new Coordinate(10, 5),
                new Coordinate(5, 5),
                new Coordinate(5, 10),
                new Coordinate(0, 10),
                new Coordinate(0, 0),
            };

            Assert.IsTrue(WindingNumberAlgorithm.IsInsidePolygon(shell, new Coordinate(3, 3)));
            Assert.IsTrue(WindingNumberAlgorithm.IsInsidePolygon(shell, new Coordinate(3, 5)));
            Assert.IsTrue(WindingNumberAlgorithm.IsInsidePolygon(shell, new Coordinate(3, 7)));
            Assert.IsFalse(WindingNumberAlgorithm.IsInsidePolygon(shell, new Coordinate(3, 12)));
            Assert.IsTrue(WindingNumberAlgorithm.IsInsidePolygon(shell, new Coordinate(11, 3)));
            Assert.IsTrue(WindingNumberAlgorithm.IsInsidePolygon(shell, new Coordinate(11, 5)));
            Assert.IsTrue(WindingNumberAlgorithm.IsInsidePolygon(shell, new Coordinate(11, 6)));
            Assert.IsFalse(WindingNumberAlgorithm.IsInsidePolygon(shell, new Coordinate(11, 8)));
            Assert.IsFalse(WindingNumberAlgorithm.IsInsidePolygon(shell, new Coordinate(-5, 3)));
            Assert.IsFalse(WindingNumberAlgorithm.IsInsidePolygon(shell, new Coordinate(-5, 5)));
            Assert.IsFalse(WindingNumberAlgorithm.IsInsidePolygon(shell, new Coordinate(-5, 6)));
            Assert.IsFalse(WindingNumberAlgorithm.IsInsidePolygon(shell, new Coordinate(-5, 7)));
            Assert.IsFalse(WindingNumberAlgorithm.IsInsidePolygon(shell, new Coordinate(-5, 8)));
            Assert.IsFalse(WindingNumberAlgorithm.IsInsidePolygon(shell, new Coordinate(-5, 12)));
            Assert.IsFalse(WindingNumberAlgorithm.IsInsidePolygon(shell, new Coordinate(4, -1)));
            Assert.IsFalse(WindingNumberAlgorithm.IsInsidePolygon(shell, new Coordinate(5, -1)));
            Assert.IsFalse(WindingNumberAlgorithm.IsInsidePolygon(shell, new Coordinate(20, -1)));
        }
        public void WindingNumberAlgorithmIsOnBoundaryTest()
        {
            // simple convex polygon

            Coordinate[] shell = new Coordinate[]
            {
                new Coordinate(0, 0),
                new Coordinate(10, 0),
                new Coordinate(10, 10),
                new Coordinate(0, 10),
                new Coordinate(0, 0),
            };

            WindingNumberAlgorithm algorithm = new WindingNumberAlgorithm(shell, new Coordinate(0, 5), true, PrecisionModel.Default);

            algorithm.Compute();
            Assert.IsTrue(algorithm.IsOnBoundary.Value);

            algorithm.Coordinate = new Coordinate(10, 5);
            algorithm.Compute();
            Assert.IsTrue(algorithm.IsOnBoundary.Value);

            algorithm.Coordinate = new Coordinate(5, 0);
            algorithm.Compute();
            Assert.IsTrue(algorithm.IsOnBoundary.Value);

            algorithm.Coordinate = new Coordinate(10, 10);
            algorithm.Compute();
            Assert.IsTrue(algorithm.IsOnBoundary.Value);

            algorithm.Coordinate = new Coordinate(5, 5);
            algorithm.Compute();
            Assert.IsFalse(algorithm.IsOnBoundary.Value);

            algorithm.Coordinate = new Coordinate(15, 5);
            algorithm.Compute();
            Assert.IsFalse(algorithm.IsOnBoundary.Value);


            // simple convex polygon with negative coordinates

            shell = new Coordinate[]
            {
                new Coordinate(0, 0),
                new Coordinate(10, -5),
                new Coordinate(10, 15),
                new Coordinate(0, 10),
                new Coordinate(0, 0),
            };

            algorithm = new WindingNumberAlgorithm(shell, new Coordinate(5, 12.5), true, PrecisionModel.Default);
            algorithm.Compute();
            Assert.IsTrue(algorithm.IsOnBoundary.Value);

            algorithm.Coordinate = new Coordinate(5, 10);
            algorithm.Compute();
            Assert.IsFalse(algorithm.IsOnBoundary.Value);

            algorithm.Coordinate = new Coordinate(-5, 0);
            algorithm.Compute();
            Assert.IsFalse(algorithm.IsOnBoundary.Value);
        }