コード例 #1
0
        public static VectorTileGeometry GetCCWPolygon(int factor)
        {
            // arrange
            var firstp = new Point()
            {
                X = factor, Y = factor
            };
            var secondp = new Point()
            {
                X = -factor, Y = factor
            };
            var thirdp = new Point()
            {
                X = -factor, Y = -factor
            };
            var fourthp = new Point()
            {
                X = factor, Y = -factor
            };
            var coords = new VectorTileGeometry(new List <Point> {
                firstp, secondp, thirdp, fourthp, firstp
            });

            return(coords);
        }
コード例 #2
0
        public void SignedAreaTest()
        {
            // arrange
            // create a closed polygon (first point is the same as the last)
            var points = new VectorTileGeometry(new List <Point>
            {
                new Point()
                {
                    X = 1, Y = 1
                },
                new Point()
                {
                    X = 2, Y = 2
                },
                new Point()
                {
                    X = 3, Y = 1
                },
                new Point()
                {
                    X = 1, Y = 1
                },
            });

            var polygon = new VectorTilePolygon(points);

            // act
            var area = polygon.SignedArea();

            // assert
            // polygon is defined clock-wise so area should be negative
            Assert.IsTrue(area == -1);
        }
コード例 #3
0
 private void CalcRingBBox(double[] min, double[] max, VectorTileGeometry points)
 {
     for (var i = 0; i < points.Count; i++)
     {
         var p = points[i];
         min[0] = Math.Min(p[0], min[0]);
         max[0] = Math.Max(p[0], max[0]);
         min[1] = Math.Min(p[1], min[1]);
         max[1] = Math.Max(p[1], max[1]);
     }
 }
コード例 #4
0
        private VectorTileGeometry NewSlice(List <VectorTileGeometry> slices, VectorTileGeometry slice, double area, double dist)
        {
            if (slice.Any())
            {
                // we don't recalculate the area/length of the unclipped geometry because the case where it goes
                // below the visibility threshold as a result of clipping is rare, so we avoid doing unnecessary work
                slice.Area     = area;
                slice.Distance = dist;

                slices.Add(slice);
            }
            return(new VectorTileGeometry());
        }
コード例 #5
0
        private VectorTileGeometry Project(double[][] lonlats, double?tolerance = null)
        {
            var projected = new VectorTileGeometry();

            for (var i = 0; i < lonlats.Length; i++)
            {
                projected.Add(ProjectPoint(lonlats[i]));
            }
            if (tolerance.HasValue && tolerance.Value > 0)
            {
                Simplifier.simplify(projected, tolerance.Value);
                calcSize(projected);
            }
            return(projected);
        }
コード例 #6
0
        private VectorTileGeometry ShiftCoords(VectorTileGeometry points, double offset)
        {
            var newPoints = new VectorTileGeometry()
            {
                Area     = points.Area,
                Distance = points.Distance
            };

            for (var i = 0; i < points.Count; i++)
            {
                newPoints.Add(new[] { points[i][0] + offset, points[i][1], points[i][2] });
            }

            return(newPoints);
        }
コード例 #7
0
        private VectorTileGeometry[] clipPoints(VectorTileGeometry geometry, double k1, double k2, int axis)
        {
            var slice = new VectorTileGeometry();

            for (var i = 0; i < geometry.Count; i++)
            {
                var a  = geometry[i];
                var ak = a[axis];

                if (ak >= k1 && ak <= k2)
                {
                    slice.Add(a);
                }
            }
            return(new[] { slice });
        }
コード例 #8
0
        private void calcSize(VectorTileGeometry points)
        {
            double area = 0;
            double dist = 0;

            double[] a = null;
            double[] b = null;
            for (int i = 0; i < points.Count - 1; i++)
            {
                a = b ?? points[i];
                b = points[i + 1];

                area += a[0] * b[1] - b[0] * a[1];

                // use Manhattan distance instead of Euclidian one to avoid expensive square root computation
                dist += Math.Abs(b[0] - a[0]) + Math.Abs(b[1] - a[1]);
            }
            points.Area     = Math.Abs(area / 2);
            points.Distance = dist;
        }
コード例 #9
0
        private void AddFeature(VectorTileFeature feature, double tolerance, bool noSimplify)
        {
            //   var geom = feature.Geometry;
            var type       = feature.Type;
            var simplified = new List <VectorTileGeometry>();

            var sqTolerance = tolerance * tolerance;

            // i, j, ring, p;

            if (type == 1)
            {
                var first  = new VectorTileGeometry(); simplified.Add(first);
                var points = feature.GetPoints();
                for (var i = 0; i < points.Count; i++)
                {
                    first.Add(points[i]);
                    NumPoints++;
                    NumSimplified++;
                }
            }
            else
            {
                var geom = feature.GetRings();
                // simplify and transform projected coordinates for tile geometry
                for (var i = 0; i < geom.Length; i++)
                {
                    var ring = geom[i];

                    // filter out tiny polylines & polygons
                    if (!noSimplify && ((type == 2 && ring.Distance < tolerance) ||
                                        (type == 3 && ring.Area < sqTolerance)))
                    {
                        NumPoints += ring.Count;
                        continue;
                    }

                    var simplifiedRing = new VectorTileGeometry()
                    {
                        Area = ring.Area, Distance = ring.Distance
                    };

                    for (var j = 0; j < ring.Count; j++)
                    {
                        var p = ring[j];
                        // keep points with importance > tolerance
                        if (noSimplify || p[2] > sqTolerance)
                        {
                            simplifiedRing.Add(p);
                            NumSimplified++;
                        }
                        NumPoints++;
                    }

                    simplified.Add(simplifiedRing);
                }
            }

            if (simplified.Count > 0)
            {
                Features.Add(new VectorTileFeature
                {
                    Geometry = type == 1? simplified.Single() : simplified.ToArray() as object,
                    Type     = type,
                    Tags     = feature.Tags
                });
            }
        }
コード例 #10
0
        private VectorTileGeometry[] clipGeometry(VectorTileGeometry[] geometry, double k1, double k2, int axis, Func <double[], double[], double, double[]> intersect, bool closed)
        {
            var slices = new List <VectorTileGeometry>();

            for (var i = 0; i < geometry.Length; i++)
            {
                double?  ak     = null;
                double?  bk     = null;
                double[] b      = null;
                var      points = geometry[i];
                var      area   = points.Area;
                var      dist   = points.Distance;
                var      len    = points.Count;
                double[] a;
                //  var j;
                //  var last;

                var slice = new VectorTileGeometry();

                for (var j = 0; j < len - 1; j++)
                {
                    a  = b ?? points[j];
                    b  = points[j + 1];
                    ak = bk ?? a[axis];
                    bk = b[axis];

                    if (ak.Value < k1)
                    {
                        if ((bk.Value > k2))
                        { // ---|-----|-->
                            slice.Add(intersect(a, b, k1)); slice.Add(intersect(a, b, k2));
                            if (!closed)
                            {
                                slice = NewSlice(slices, slice, area, dist);
                            }
                        }
                        else if (bk.Value >= k1)
                        {
                            slice.Add(intersect(a, b, k1));                      // ---|-->  |
                        }
                    }
                    else if (ak.Value > k2)
                    {
                        if ((bk.Value < k1))
                        { // <--|-----|---
                            slice.Add(intersect(a, b, k2)); slice.Add(intersect(a, b, k1));
                            if (!closed)
                            {
                                slice = NewSlice(slices, slice, area, dist);
                            }
                        }
                        else if (bk.Value <= k2)
                        {
                            slice.Add(intersect(a, b, k2));                      // |  <--|---
                        }
                    }
                    else
                    {
                        slice.Add(a);

                        if (bk.Value < k1)
                        { // <--|---  |
                            slice.Add(intersect(a, b, k1));
                            if (!closed)
                            {
                                slice = NewSlice(slices, slice, area, dist);
                            }
                        }
                        else if (bk.Value > k2)
                        { // |  ---|-->
                            slice.Add(intersect(a, b, k2));
                            if (!closed)
                            {
                                slice = NewSlice(slices, slice, area, dist);
                            }
                        }
                        // | --> |
                    }
                }

                // add the last point
                a  = points[len - 1];
                ak = a[axis];
                if (ak.Value >= k1 && ak.Value <= k2)
                {
                    slice.Add(a);
                }

                // close the polygon if its endpoints are not the same after clipping
                if (slice.Any())
                {
                    var last = slice[slice.Count - 1];
                    if (closed && (slice[0][0] != last[0] || slice[0][1] != last[1]))
                    {
                        slice.Add(slice[0]);
                    }
                }

                // add the final slice
                NewSlice(slices, slice, area, dist);
            }

            return(slices.ToArray());
        }