コード例 #1
0
        /// <summary>
        /// TO BE REMOVED!!! Processing geometries is out of scope.
        /// Clip geometries extending beyond the tile border.
        /// </summary>
        /// <param name="geoms">Raw tile geometries of the feature</param>
        /// <param name="geomType">Geometry type of the feature</param>
        /// <param name="extent">Extent of the layer </param>
        /// <param name="bufferSize">Units (in internal tile coordinates) to go beyond the tile border. Pass '0' to clip exactly at the tile border</param>
        /// <param name="scale">Factor for scaling the geometries</param>
        /// <returns></returns>
        public static List <List <Point2d <long> > > ClipGeometries(
            List <List <Point2d <long> > > geoms
            , GeomType geomType
            , long extent
            , uint bufferSize
            , float scale
            )
        {
            List <List <Point2d <long> > > retVal = new List <List <Point2d <long> > >();

            //points: simply remove them if one part of the coordinate pair is out of bounds:
            // <0 || >extent
            if (geomType == GeomType.POINT)
            {
                foreach (var geomPart in geoms)
                {
                    List <Point2d <long> > outGeom = new List <Point2d <long> >();
                    foreach (var geom in geomPart)
                    {
                        if (
                            geom.X < (0L - bufferSize) ||
                            geom.Y < (0L - bufferSize) ||
                            geom.X > (extent + bufferSize) ||
                            geom.Y > (extent + bufferSize)
                            )
                        {
                            continue;
                        }
                        outGeom.Add(geom);
                    }

                    if (outGeom.Count > 0)
                    {
                        retVal.Add(outGeom);
                    }
                }

                return(retVal);
            }

            //use clipper for lines and polygons
            bool closed = true;

            if (geomType == GeomType.LINESTRING)
            {
                closed = false;
            }


            Polygons subjects = new Polygons();
            Polygons clip     = new Polygons(1);
            Polygons solution = new Polygons();

            clip.Add(new Polygon(4));
            clip[0].Add(new InternalClipper.IntPoint(0L - bufferSize, 0L - bufferSize));
            clip[0].Add(new InternalClipper.IntPoint(extent + bufferSize, 0L - bufferSize));
            clip[0].Add(new InternalClipper.IntPoint(extent + bufferSize, extent + bufferSize));
            clip[0].Add(new InternalClipper.IntPoint(0L - bufferSize, extent + bufferSize));

            foreach (var geompart in geoms)
            {
                Polygon part = new Polygon();

                foreach (var geom in geompart)
                {
                    part.Add(new InternalClipper.IntPoint(geom.X, geom.Y));
                }
                subjects.Add(part);
            }

            InternalClipper.Clipper c = new InternalClipper.Clipper();
            c.AddPaths(subjects, InternalClipper.PolyType.ptSubject, closed);
            c.AddPaths(clip, InternalClipper.PolyType.ptClip, true);

            bool succeeded = false;

            if (geomType == GeomType.LINESTRING)
            {
                InternalClipper.PolyTree lineSolution = new InternalClipper.PolyTree();
                succeeded = c.Execute(
                    InternalClipper.ClipType.ctIntersection
                    , lineSolution
                    , InternalClipper.PolyFillType.pftNonZero
                    , InternalClipper.PolyFillType.pftNonZero
                    );
                if (succeeded)
                {
                    solution = InternalClipper.Clipper.PolyTreeToPaths(lineSolution);
                }
            }
            else
            {
                succeeded = c.Execute(
                    InternalClipper.ClipType.ctIntersection
                    , solution
                    , InternalClipper.PolyFillType.pftNonZero
                    , InternalClipper.PolyFillType.pftNonZero
                    );
            }

            if (succeeded)
            {
                retVal = new List <List <Point2d <long> > >();
                foreach (var part in solution)
                {
                    List <Point2d <long> > geompart = new List <Point2d <long> >();
                    // HACK:
                    // 1. clipper may or may not reverse order of vertices of LineStrings
                    // 2. clipper semms to drop the first vertex of a Polygon
                    // * We don't care about 1.
                    // * Added a check for 2 and insert a copy of last vertex as first
                    foreach (var geom in part)
                    {
                        geompart.Add(new Point2d <long>()
                        {
                            X = geom.X, Y = geom.Y
                        });
                    }
                    if (geomType == GeomType.POLYGON)
                    {
                        if (!geompart[0].Equals(geompart[geompart.Count - 1]))
                        {
                            geompart.Insert(0, geompart[geompart.Count - 1]);
                        }
                    }
                    retVal.Add(geompart);
                }

                return(retVal);
            }
            else
            {
                //if clipper was not successfull return original geometries
                return(geoms);
            }
        }
        private static List <List <Point2d> > clipGeometries(
            List <List <Point2d> > geoms
            , GeomType geomType
            , long extent
            , uint bufferSize
            )
        {
            List <List <Point2d> > retVal = new List <List <Point2d> >();

            //points: simply remove them if one part of the coordinate pair is out of bounds:
            // <0 || >extent
            if (geomType == GeomType.POINT)
            {
                foreach (var geomPart in geoms)
                {
                    List <Point2d> outGeom = new List <Point2d>();
                    foreach (var geom in geomPart)
                    {
                        if (
                            geom.X < (0L - bufferSize) ||
                            geom.Y < (0L - bufferSize) ||
                            geom.X > (extent + bufferSize) ||
                            geom.Y > (extent + bufferSize)
                            )
                        {
                            continue;
                        }
                        outGeom.Add(geom);
                    }

                    if (outGeom.Count > 0)
                    {
                        retVal.Add(outGeom);
                    }
                }

                return(retVal);
            }

            //use clipper for lines and polygons
            bool closed = true;

            if (geomType == GeomType.LINESTRING)
            {
                closed = false;
            }


            Polygons subjects = new Polygons();
            Polygons clip     = new Polygons(1);
            Polygons solution = new Polygons();

            clip.Add(new Polygon(4));
            clip[0].Add(new InternalClipper.IntPoint(0L - bufferSize, 0L - bufferSize));
            clip[0].Add(new InternalClipper.IntPoint(extent + bufferSize, 0L - bufferSize));
            clip[0].Add(new InternalClipper.IntPoint(extent + bufferSize, extent + bufferSize));
            clip[0].Add(new InternalClipper.IntPoint(0L - bufferSize, extent + bufferSize));

            foreach (var geompart in geoms)
            {
                Polygon part = new Polygon();

                foreach (var geom in geompart)
                {
                    part.Add(new InternalClipper.IntPoint(geom.X, geom.Y));
                }
                subjects.Add(part);
            }

            InternalClipper.Clipper c = new InternalClipper.Clipper();
            c.AddPaths(subjects, InternalClipper.PolyType.ptSubject, closed);
            c.AddPaths(clip, InternalClipper.PolyType.ptClip, true);

            bool succeeded = false;

            if (geomType == GeomType.LINESTRING)
            {
                InternalClipper.PolyTree lineSolution = new InternalClipper.PolyTree();
                succeeded = c.Execute(
                    InternalClipper.ClipType.ctIntersection
                    , lineSolution
                    , InternalClipper.PolyFillType.pftNonZero
                    , InternalClipper.PolyFillType.pftNonZero
                    );
                if (succeeded)
                {
                    solution = InternalClipper.Clipper.PolyTreeToPaths(lineSolution);
                }
            }
            else
            {
                succeeded = c.Execute(
                    InternalClipper.ClipType.ctIntersection
                    , solution
                    , InternalClipper.PolyFillType.pftNonZero
                    , InternalClipper.PolyFillType.pftNonZero
                    );
            }

            if (succeeded)
            {
                retVal = new List <List <Point2d> >();
                foreach (var part in solution)
                {
                    List <Point2d> geompart = new List <Point2d>();
                    foreach (var geom in part)
                    {
                        geompart.Add(new Point2d()
                        {
                            X = geom.X, Y = geom.Y
                        });
                    }
                    retVal.Add(geompart);
                }

                return(retVal);
            }
            else
            {
                //if clipper was not successfull return original geometries
                return(geoms);
            }
        }
コード例 #3
0
        public override void Run(VectorFeatureUnity feature, MeshData md, UnityTile tile = null)
        {
            if (feature.Points.Count < 1)
            {
                return;
            }

            InternalClipper.PolyTree      solution = new InternalClipper.PolyTree();
            InternalClipper.ClipperOffset co       = new InternalClipper.ClipperOffset();

            foreach (var roadSegment in feature.Points)
            {
                co.AddPath(roadSegment.Select(i => new InternalClipper.IntPoint(i.x, i.z)).ToList(), InternalClipper.JoinType.jtSquare, InternalClipper.EndType.etOpenButt);
            }

            co.Execute(ref solution, Width / 2);
            var x = solution;

            var    polygon = new Polygon();
            Vertex prev    = null;
            Vertex current = null;
            Vertex first   = null;

            foreach (var poly in solution.m_AllPolys)
            {
                prev    = null;
                current = null;
                first   = null;
                foreach (var item in poly.Contour)
                {
                    prev    = current;
                    current = new Vertex(item.X, item.Y, 0);
                    if (first == null)
                    {
                        first = current;
                    }
                    polygon.Add(current);
                    if (prev != null)
                    {
                        polygon.Add(new Segment(current, prev));
                    }
                }
                polygon.Add(new Segment(first, current));
            }

            var mesh = polygon.Triangulate();
            var data = new List <int>();

            foreach (var tri in mesh.Triangles)
            {
                data.Add(tri.GetVertexID(0));
                data.Add(tri.GetVertexID(2));
                data.Add(tri.GetVertexID(1));
            }

            foreach (var edge in mesh.Edges)
            {
                if (edge.Label == 0)
                {
                    continue;
                }

                md.Edges.Add(edge.P0);
                md.Edges.Add(edge.P1);
            }
            md.Vertices.Clear();
            using (var sequenceEnum = mesh.Vertices.GetEnumerator())
            {
                while (sequenceEnum.MoveNext())
                {
                    md.Vertices.Add(new Vector3((float)sequenceEnum.Current.x, 0, (float)sequenceEnum.Current.y));
                }
            }
            md.Triangles.Add(data);

            //foreach (var roadSegment in feature.Points)
            //{
            //    var count = roadSegment.Count;
            //    for (int i = 1; i < count*2; i++)
            //    {
            //        md.Edges.Add(md.Vertices.Count + i);
            //        md.Edges.Add(md.Vertices.Count + i - 1);
            //    }
            //    md.Edges.Add(md.Vertices.Count);
            //    md.Edges.Add(md.Vertices.Count + (count*2) - 1);

            //    var newVerticeList = new Vector3[count * 2];
            //    var uvList = new Vector2[count * 2];
            //    Vector3 norm;
            //    var lastUv = 0f;
            //    var p1 = Mapbox.Unity.Constants.Math.Vector3Zero;
            //    var p2 = Mapbox.Unity.Constants.Math.Vector3Zero;
            //    var p3 = Mapbox.Unity.Constants.Math.Vector3Zero;
            //    for (int i = 1; i < count; i++)
            //    {
            //        p1 = roadSegment[i - 1];
            //        p2 = roadSegment[i];
            //        p3 = p2;
            //        if (i + 1 < roadSegment.Count)
            //            p3 = roadSegment[i + 1];

            //        if (i == 1)
            //        {
            //            norm = GetNormal(p1, p1, p2) * Width; //road width
            //            newVerticeList[0] = (p1 + norm);
            //            newVerticeList[count * 2 - 1] = (p1 - norm);
            //            uvList[0] = new Vector2(0, 0);
            //            uvList[count * 2 - 1] = new Vector2(1, 0);
            //        }
            //        var dist = Vector3.Distance(p1, p2);
            //        lastUv += dist;
            //        norm = GetNormal(p1, p2, p3) * Width;
            //        newVerticeList[i] = (p2 + norm);
            //        newVerticeList[2 * count - 1 - i] = (p2 - norm);

            //        uvList[i] = new Vector2(0, lastUv);
            //        uvList[2 * count - 1 - i] = new Vector2(1, lastUv);
            //    }

            //    //if (_mergeStartEnd)
            //    //{
            //    //    //brnkhy -2 because first and last items are same
            //    //    p1 = segment[count - 2];
            //    //    p2 = segment[0];
            //    //    p3 = segment[1];

            //    //    norm = GetNormal(p1, p2, p3) * Width;
            //    //    newVerticeList[count - 1] = p2 + norm;
            //    //    newVerticeList[0] = p2 + norm;
            //    //    newVerticeList[count] = p2 - norm;
            //    //    newVerticeList[2 * count - 1] = p2 - norm;
            //    //}

            //    var pcount = md.Vertices.Count;
            //    md.Vertices.AddRange(newVerticeList);
            //    md.UV[0].AddRange(uvList);
            //    var lineTri = new List<int>();
            //    var n = count;

            //    for (int i = 0; i < n - 1; i++)
            //    {
            //        lineTri.Add(pcount + i);
            //        lineTri.Add(pcount + i + 1);
            //        lineTri.Add(pcount + 2 * n - 1 - i);

            //        lineTri.Add(pcount + i + 1);
            //        lineTri.Add(pcount + 2 * n - i - 2);
            //        lineTri.Add(pcount + 2 * n - i - 1);
            //    }

            //    if (md.Triangles.Count < 1)
            //        md.Triangles.Add(new List<int>());
            //    md.Triangles[0].AddRange(lineTri);
            //}
        }