Example #1
0
        // use the clipper library to return an offset to the given polygon. Positive offset expands the polygon, negative contracts
        // note that this returns an array of polygons
        public static NFP[] polygonOffsetDeepNest(NFP polygon, double offset)
        {
            if (offset == 0 || GeometryUtil._almostEqual(offset, 0))
            {
                return(new[] { polygon });
            }

            var p = svgToClipper(polygon).ToList();

            var miterLimit = 4;
            var co         = new ClipperLib.ClipperOffset(miterLimit, Config.curveTolerance * Config.clipperScale);

            co.AddPath(p.ToList(), ClipperLib.JoinType.jtMiter, ClipperLib.EndType.etClosedPolygon);

            var newpaths = new List <List <ClipperLib.IntPoint> >();

            co.Execute(ref newpaths, offset * Config.clipperScale);


            var result = new List <NFP>();

            for (var i = 0; i < newpaths.Count; i++)
            {
                result.Add(clipperToSvg(newpaths[i]));
            }


            return(result.ToArray());
        }
Example #2
0
    public List <List <Vector3> > Offset(float amount, float height)
    {
        var orderedPoints = GetAllOrderedIntPoints();

        var result = new List <List <Vector3> >();

        foreach (var path in orderedPoints)
        {
            Debug.Log("New path");
            foreach (var intpoint in path.Points)
            {
                Debug.Log("Ordered point: " + intpoint.X + ", " + intpoint.Y);
            }
            var co      = new ClipperLib.ClipperOffset();
            var endType = path.IsClosedLoop ? ClipperLib.EndType.etClosedLine : ClipperLib.EndType.etOpenSquare;
            co.AddPath(path.Points, ClipperLib.JoinType.jtSquare, endType);

            var results = new List <List <ClipperLib.IntPoint> >();
            co.Execute(ref results, (int)(amount * 1000.0f));

            result.AddRange(results.Select(
                                xs => xs.Select(
                                    x => new Vector3((float)x.X / 1000.0f, height, (float)x.Y / 1000.0f)).ToList()));
        }

        return(result);
    }
Example #3
0
 public List<List<IntPoint>> Run (List<List<IntPoint>> subject, double scale)
 {
   var clipperOffset = new ClipperOffset (miterLimit, arcTolerance);
   clipperOffset.AddPaths (subject, joinType, endType);
   var result = new List<List<IntPoint>> ();
   clipperOffset.Execute (ref result, scale * delta);
   return result;
 }
Example #4
0
		public override List<List<IntPoint>> GetCopyOfClipperPolygon(double relativeWidth, List<List<IntPoint>> outerPolygon)
		{
			var delta = (-2 * relativeWidth) * ClosedSymbolBase.ClipperScalingInt;
			var clipper = new ClipperOffset();
			clipper.AddPaths(outerPolygon, JoinType.jtMiter, EndType.etClosedPolygon);
			var result = new List<List<IntPoint>>();
			clipper.Execute(ref result, delta);
			return result;
		}
Example #5
0
        //------------------------------------------------------------------------------

        public static Paths OffsetPaths(Paths pp, double delta, JoinType jt, EndType et)
        {
            Paths         result = new Paths();
            ClipperOffset co     = new ClipperOffset();

            co.AddPaths(pp, jt, et);
            co.Execute(ref result, delta);
            return(result);
        }
Example #6
0
        /// <summary>
        /// 对一个点集路径进行偏移 需要注意 对于一个闭合路径 使用ClipperOffset 得到的结果,会有两个点集,第一个结果为外圈点集,第二结果为内圈点集
        /// </summary>
        public static List <List <IntPoint> > _GetOffsetPonts_clipper_Path(Path_xyz _Path_xyz_RedLine, double _offset)
        {
            Paths         solution      = new Paths();
            ClipperOffset _Co           = new ClipperOffset();//ClipperOffset构造函数。其包含可选参数
            Path          _Path_RedLine = Path_xyzToPath(_Path_xyz_RedLine);

            _Co.AddPath(_Path_RedLine, JoinType.jtSquare, EndType.etClosedLine);
            _offset = _offset * 1000; //放大倍数与clipper_methods中放大倍数保持一致
            _Co.Execute(ref solution, _offset);
            return(solution);         //一根线偏移后,应该具有四个端点,为矩形
        }
Example #7
0
        public static Polygons Offset(this Polygons polygons, double distance)
        {
            var offseter = new ClipperOffset();

            offseter.AddPaths(polygons, JoinType.jtRound, EndType.etClosedPolygon);
            var solution = new Polygons();

            offseter.Execute(ref solution, distance);

            return(solution);
        }
Example #8
0
        public static bool GetPoint(Vector2[] quad, bool outter, out List<Vector2> list, bool isClose=true)
        {
            List<IntPoint> quadLines = new List<IntPoint>();
            for(int i=0; i < quad.Length; i++){
                Vector3 from = quad[i];
                IntPoint to = new IntPoint(from.x * DrawHelper.ClipScalling, from.y * DrawHelper.ClipScalling);
                quadLines.Add(to);

                //				IntPoint to = quad[i+1];
                //				to = new IntPoint(to.X * scale.X * scalling, to.Y * scale.Y * scalling);
                //				quadLines.Add(to);
            }

            EndType endType = EndType.etOpenButt;
            if(isClose){
                endType = EndType.etClosedPolygon;
            }

            //Debug.Log("endType: " + endType);

            ClipperOffset co = new ClipperOffset();
            co.AddPath(quadLines, JoinType.jtMiter, endType);
            Paths solution = new Paths();
            double delta = -DrawHelper.WallThick/2 * DrawHelper.ClipScalling;
            if(outter){
                delta = -delta;
            }

            co.MiterLimit = 8;
            co.Execute(ref solution, delta);

            list = new List<Vector2>();

            if(solution.Count > 0){
                foreach(IntPoint p in solution[0]){
                    Vector3 re = new Vector3(p.X * 1.0f/DrawHelper.ClipScalling, p.Y * 1.0f/DrawHelper.ClipScalling, 0f);

                    if(!isClose){
                        //Debug.Log("result: " + re);
                    }

                    list.Add(re);
                }
                list.Add(list[0]);
                return Clipper.Orientation(solution[0]);
            }
            else{
                Debug.LogError("no solution..");
            }

            return true;
        }
Example #9
0
    public void assignNewBuildings(string data)
    {
        ClipperLib.ClipperOffset  co  = new ClipperLib.ClipperOffset();
        InvisBuildingJsonRepsonse res = JsonUtility.FromJson <InvisBuildingJsonRepsonse>(data);

        for (int i = 0; i < res.response.Length; ++i)
        {
            bool duplicate = false;
            for (int j = 0; j < all_buildings.Count; ++j)
            {
                if (res.response[i].id == all_buildings[j].id)
                {
                    duplicate = true;
                }
            }
            if (!duplicate)
            {
                // invisible building and fade building
                GameObject fb = Instantiate(Resources.Load("FadeBuilding"), new Vector3(0, 0, 0), Quaternion.identity) as GameObject;
                fb.transform.SetParent(building_container);
                List <ClipperLib.IntPoint> path = new List <ClipperLib.IntPoint>();
                for (int k = 0; k < res.response[i].building.Length; k += 2)
                {
                    path.Add(new ClipperLib.IntPoint(res.response[i].building[k] * prec, res.response[i].building[k + 1] * prec));
                }

                co.AddPath(path, ClipperLib.JoinType.jtRound, ClipperLib.EndType.etClosedPolygon);
                List <List <ClipperLib.IntPoint> > l = new List <List <ClipperLib.IntPoint> >();
                co.Execute(ref l, -smaller * prec);
                co.Clear();
                InvisBuildingJsonRepsonse_Building ibb = new InvisBuildingJsonRepsonse_Building();
                ibb.startPoint = res.response[i].startPoint;
                ibb.id         = res.response[i].id;
                ibb.building   = new float[l[0].Count * 2];
                //ibb.building =

                for (int k = 0; k < l[0].Count; ++k)
                {
                    ibb.building[k * 2]     = l[0][k].X / prec;
                    ibb.building[k * 2 + 1] = l[0][k].Y / prec;
                }


                fb.GetComponent <InvisBuilding>().init(res.response[i], poi_handler);

                all_buildings.Add(fb.GetComponent <InvisBuilding>());
            }
        }
    }
Example #10
0
        /// <summary>
        /// 使用clipper对 单根个线段进行偏移,其结果点集是一个矩形路径
        /// </summary>
        public static List <IntPoint> _GetOffsetPonts_clipper_line(Curve _curve, double _offset)
        {
            //拿出线段断点转化为 Intpont
            XYZ      _startPoint = _curve.GetEndPoint(0);
            XYZ      _endPoint   = _curve.GetEndPoint(1);
            Path_xyz _Path_xyz   = new Path_xyz()
            {
                _startPoint, _endPoint
            };
            Path  _Path    = Path_xyzToPath(_Path_xyz);
            Paths solution = new Paths();
            //开展偏移工作
            ClipperOffset _Co = new ClipperOffset();//ClipperOffset构造函数。其包含可选参数

            _Co.AddPath(_Path, JoinType.jtSquare, EndType.etClosedLine);
            _offset = _offset * _multiple; //放大倍数与clipper_methods中放大倍数保持一致
            _Co.Execute(ref solution, _offset);
            return(solution[0]);           //一根线偏移后,应该具有四个端点,为矩形
        }
Example #11
0
        public static NFP[] offset(NFP polygon, double offset, JoinType jType = JoinType.jtMiter, double clipperScale = 10000000, double curveTolerance = 0.72, double miterLimit = 4)
        {
            var p = ScaleUpPaths(polygon, clipperScale).ToList();

            var co = new ClipperLib.ClipperOffset(miterLimit, curveTolerance * clipperScale);

            co.AddPath(p.ToList(), jType, ClipperLib.EndType.etClosedPolygon);

            var newpaths = new List <List <ClipperLib.IntPoint> >();

            co.Execute(ref newpaths, offset * clipperScale);

            var result = new List <NFP>();

            for (var i = 0; i < newpaths.Count; i++)
            {
                result.Add(clipperToSvg(newpaths[i]));
            }
            return(result.ToArray());
        }
Example #12
0
        /// <summary>
        /// Generates a solid outline of the path.
        /// </summary>
        /// <param name="path">the path to outline</param>
        /// <param name="width">The final width outline</param>
        /// <returns>A new path representing the outline.</returns>
        public static IPath GenerateOutline(this IPath path, float width)
        {
            ClipperOffset offset = new ClipperLib.ClipperOffset();

            // Pattern can be applied to the path by cutting it into segments
            IEnumerable <ISimplePath> paths = path.Flatten();

            foreach (ISimplePath p in paths)
            {
                IReadOnlyList <PointF> vectors = p.Points;
                List <IntPoint>        points  = new List <ClipperLib.IntPoint>(vectors.Count);
                foreach (Vector2 v in vectors)
                {
                    points.Add(new IntPoint(v.X * ScalingFactor, v.Y * ScalingFactor));
                }

                EndType type = p.IsClosed ? EndType.etClosedLine : EndType.etOpenButt;

                offset.AddPath(points, JoinType.jtSquare, type);
            }

            return(ExecuteOutliner(width, offset));
        }
Example #13
0
 static ClipperHelper()
 {
     Clipper = new Clipper(Clipper.ioStrictlySimple);
     Offsetter = new ClipperOffset();
 }
Example #14
0
    //---------------------------------------------------------------------------

    private void DrawBitmap(bool justClip = false)
    {
      Cursor.Current = Cursors.WaitCursor;
      try
      {
        if (!justClip)
        {
          if (rbTest2.Checked)
            GenerateAustPlusRandomEllipses((int)nudCount.Value);
          else
            GenerateRandomPolygon((int)nudCount.Value);
        }
        using (Graphics newgraphic = Graphics.FromImage(mybitmap))
        using (GraphicsPath path = new GraphicsPath())
        {
          newgraphic.SmoothingMode = SmoothingMode.AntiAlias;
          newgraphic.Clear(Color.White);
          if (rbNonZero.Checked)
            path.FillMode = FillMode.Winding;

          //draw subjects ...
          foreach (Polygon pg in subjects)
          {
            PointF[] pts = PolygonToPointFArray(pg, scale);
            path.AddPolygon(pts);
            pts = null;
          }
          using (Pen myPen = new Pen(Color.FromArgb(196, 0xC3, 0xC9, 0xCF), (float)0.6))
          using (SolidBrush myBrush = new SolidBrush(Color.FromArgb(127, 0xDD, 0xDD, 0xF0)))
          {
            newgraphic.FillPath(myBrush, path);
            newgraphic.DrawPath(myPen, path);
            path.Reset();

            //draw clips ...
            if (rbNonZero.Checked)
              path.FillMode = FillMode.Winding;
            foreach (Polygon pg in clips)
            {
              PointF[] pts = PolygonToPointFArray(pg, scale);
              path.AddPolygon(pts);
              pts = null;
            }
            myPen.Color = Color.FromArgb(196, 0xF9, 0xBE, 0xA6);
            myBrush.Color = Color.FromArgb(127, 0xFF, 0xE0, 0xE0);
            newgraphic.FillPath(myBrush, path);
            newgraphic.DrawPath(myPen, path);

            //do the clipping ...
            if ((clips.Count > 0 || subjects.Count > 0) && !rbNone.Checked)
            {
              Polygons solution2 = new Polygons();
              Clipper c = new Clipper();
              c.AddPaths(subjects, PolyType.ptSubject, true);
              c.AddPaths(clips, PolyType.ptClip, true);
              solution.Clear();
#if UsePolyTree
              bool succeeded = c.Execute(GetClipType(), solutionTree, GetPolyFillType(), GetPolyFillType());
              //nb: we aren't doing anything useful here with solutionTree except to show
              //that it works. Convert PolyTree back to Polygons structure ...
              Clipper.PolyTreeToPolygons(solutionTree, solution);
#else
              bool succeeded = c.Execute(GetClipType(), solution, GetPolyFillType(), GetPolyFillType());
#endif
              if (succeeded)
              {
                //SaveToFile("solution", solution);
                myBrush.Color = Color.Black;
                path.Reset();

                //It really shouldn't matter what FillMode is used for solution
                //polygons because none of the solution polygons overlap. 
                //However, FillMode.Winding will show any orientation errors where 
                //holes will be stroked (outlined) correctly but filled incorrectly  ...
                path.FillMode = FillMode.Winding;

                //or for something fancy ...

                if (nudOffset.Value != 0)
                {
                  ClipperOffset co = new ClipperOffset();
                  co.AddPaths(solution, JoinType.jtRound, EndType.etClosedPolygon);
                  co.Execute(ref solution2, (double)nudOffset.Value * scale);
                }
                else
                  solution2 = new Polygons(solution);

                foreach (Polygon pg in solution2)
                {
                  PointF[] pts = PolygonToPointFArray(pg, scale);
                  if (pts.Count() > 2)
                    path.AddPolygon(pts);
                  pts = null;
                }
                myBrush.Color = Color.FromArgb(127, 0x66, 0xEF, 0x7F);
                myPen.Color = Color.FromArgb(255, 0, 0x33, 0);
                myPen.Width = 1.0f;
                newgraphic.FillPath(myBrush, path);
                newgraphic.DrawPath(myPen, path);

                //now do some fancy testing ...
                using (Font f = new Font("Arial", 8))
                using (SolidBrush b = new SolidBrush(Color.Navy))
                {
                  double subj_area = 0, clip_area = 0, int_area = 0, union_area = 0;
                  c.Clear();
                  c.AddPaths(subjects, PolyType.ptSubject, true);
                  c.Execute(ClipType.ctUnion, solution2, GetPolyFillType(), GetPolyFillType());
                  foreach (Polygon pg in solution2)
                    subj_area += Clipper.Area(pg);
                  c.Clear();
                  c.AddPaths(clips, PolyType.ptClip, true);
                  c.Execute(ClipType.ctUnion, solution2, GetPolyFillType(), GetPolyFillType());
                  foreach (Polygon pg in solution2)
                    clip_area += Clipper.Area(pg);
                  c.AddPaths(subjects, PolyType.ptSubject, true);
                  c.Execute(ClipType.ctIntersection, solution2, GetPolyFillType(), GetPolyFillType());
                  foreach (Polygon pg in solution2)
                    int_area += Clipper.Area(pg);
                  c.Execute(ClipType.ctUnion, solution2, GetPolyFillType(), GetPolyFillType());
                  foreach (Polygon pg in solution2)
                    union_area += Clipper.Area(pg);

                  using (StringFormat lftStringFormat = new StringFormat())
                  using (StringFormat rtStringFormat = new StringFormat())
                  {
                    lftStringFormat.Alignment = StringAlignment.Near;
                    lftStringFormat.LineAlignment = StringAlignment.Near;
                    rtStringFormat.Alignment = StringAlignment.Far;
                    rtStringFormat.LineAlignment = StringAlignment.Near;
                    Rectangle rec = new Rectangle(pictureBox1.ClientSize.Width - 108,
                                     pictureBox1.ClientSize.Height - 116, 104, 106);
                    newgraphic.FillRectangle(new SolidBrush(Color.FromArgb(196, Color.WhiteSmoke)), rec);
                    newgraphic.DrawRectangle(myPen, rec);
                    rec.Inflate(new Size(-2, 0));
                    newgraphic.DrawString("Areas", f, b, rec, rtStringFormat);
                    rec.Offset(new Point(0, 14));
                    newgraphic.DrawString("subj: ", f, b, rec, lftStringFormat);
                    newgraphic.DrawString((subj_area / 100000).ToString("0,0"), f, b, rec, rtStringFormat);
                    rec.Offset(new Point(0, 12));
                    newgraphic.DrawString("clip: ", f, b, rec, lftStringFormat);
                    newgraphic.DrawString((clip_area / 100000).ToString("0,0"), f, b, rec, rtStringFormat);
                    rec.Offset(new Point(0, 12));
                    newgraphic.DrawString("intersect: ", f, b, rec, lftStringFormat);
                    newgraphic.DrawString((int_area / 100000).ToString("0,0"), f, b, rec, rtStringFormat);
                    rec.Offset(new Point(0, 12));
                    newgraphic.DrawString("---------", f, b, rec, rtStringFormat);
                    rec.Offset(new Point(0, 10));
                    newgraphic.DrawString("s + c - i: ", f, b, rec, lftStringFormat);
                    newgraphic.DrawString(((subj_area + clip_area - int_area) / 100000).ToString("0,0"), f, b, rec, rtStringFormat);
                    rec.Offset(new Point(0, 10));
                    newgraphic.DrawString("---------", f, b, rec, rtStringFormat);
                    rec.Offset(new Point(0, 10));
                    newgraphic.DrawString("union: ", f, b, rec, lftStringFormat);
                    newgraphic.DrawString((union_area / 100000).ToString("0,0"), f, b, rec, rtStringFormat);
                    rec.Offset(new Point(0, 10));
                    newgraphic.DrawString("---------", f, b, rec, rtStringFormat);
                  }
                }
              } //end if succeeded
            } //end if something to clip
            pictureBox1.Image = mybitmap;
          }
        }
      }
      finally
      {
        Cursor.Current = Cursors.Default;
      }
    }
Example #15
0
        private PolyTreeEdgesRetained PrepairPolyTree(Collider2D[] floorColliders, Collider2D[] wallColliders)
        {
            if(floorColliders.Length == 0)
            {
                throw new System.Exception("No colliders in the scene on the floor layer.");
            }

            PolyTreeEdgesRetained TreeAndEdges = new PolyTreeEdgesRetained();

            TreeAndEdges.Edges = new List<List<IntPoint>>();
            TreeAndEdges.Tree = new PolyTree();

            Clipper finalClipper = new Clipper();

            if (floorColliders.Length > 0)
            {
                Clipper tempC = new Clipper();
                ClipperOffset tempCo = new ClipperOffset();

                foreach (Collider2D d in floorColliders)
                {
                    List<IntPoint> p = PolygonFromCollider2D(d, false);
                    if (p != null && p.Count != 0)
                    {
                        if (ClipperLib.Clipper.Orientation(p))
                            p.Reverse();

                        tempC.AddPath(p, PolyType.ptSubject, true);
                    }
                }

                List<List<IntPoint>> solution = new List<List<IntPoint>>();
                tempC.Execute(ClipType.ctUnion, solution, PolyFillType.pftNonZero, PolyFillType.pftNonZero);
                tempC.Clear();

                foreach (List<IntPoint> intPoints in solution)
                {
                    tempCo.AddPath(intPoints, (JoinType)GenerationInformation.JoinType, EndType.etClosedPolygon);
                    TreeAndEdges.Edges.Add(intPoints);
                }
                solution.Clear();
                tempCo.Execute(ref solution, -GenerationInformation.ColliderPadding * GenerationInformation.CalculationScaleFactor);
                finalClipper.AddPaths(solution, PolyType.ptSubject, true);
            }

            if(wallColliders.Length > 0)
            {
                Clipper tempC = new Clipper();
                ClipperOffset tempCo = new ClipperOffset();

                foreach (Collider2D d in wallColliders)
                {
                    List<IntPoint> p = PolygonFromCollider2D(d, false);
                    if (p != null && p.Count != 0)
                    {
                        if (ClipperLib.Clipper.Orientation(p))
                            p.Reverse();

                        tempC.AddPath(p, PolyType.ptSubject, true);
                    }
                }

                List<List<IntPoint>> solution = new List<List<IntPoint>>();
                tempC.Execute(ClipType.ctUnion, solution, PolyFillType.pftNonZero, PolyFillType.pftNonZero);
                tempC.Clear();

                foreach (List<IntPoint> intPoints in solution)
                {
                    tempCo.AddPath(intPoints, (JoinType)GenerationInformation.JoinType, EndType.etClosedPolygon);
                    TreeAndEdges.Edges.Add(intPoints);
                }
                solution.Clear();

                tempCo.Execute(ref solution, GenerationInformation.ColliderPadding * GenerationInformation.CalculationScaleFactor);
                finalClipper.AddPaths(solution, PolyType.ptClip, true);
            }

            finalClipper.Execute(ClipType.ctDifference, TreeAndEdges.Tree, PolyFillType.pftPositive, PolyFillType.pftEvenOdd);

            return TreeAndEdges;
        }
Example #16
0
        public void CreateSideWalks(List<GameObject> streetWeb, List<List<Vector3>> streetsPoly)
        {
            List<GameObject> sideWalks = new List<GameObject>();

            for (int i = 0; i < streetWeb.Count; i++)
            {
                GameObject sideWalk = new GameObject("sideWalk", typeof(MeshRenderer), typeof(MeshFilter));
                sideWalk.transform.parent = this.transform;
                sideWalk.GetComponent<MeshRenderer>().material = (Material)Resources.Load("SideWalkMat");

                List<List<IntPoint>> solution = new List<List<IntPoint>>();
                //transform vertices of each mesh in points for clipper

                //List<IntPoint> intPoint = FromVecToIntPoint(streetWeb[i].GetComponent<MeshFilter>().sharedMesh.vertices);
                List<IntPoint> intPoint = FromVecToIntPoint(streetsPoly[i].ToArray());

                //offset each mesh
                ClipperOffset co = new ClipperOffset();
                co.AddPath(intPoint, JoinType.jtRound, EndType.etOpenRound);
                co.Execute(ref solution, 1000.0);

                List<Vector2> vertices2D = new List<Vector2>();
                for (int j = 0; j < solution.Count; j++)
                {
                    vertices2D = vertices2D.Concat(FromIntPointToVec(solution[j])).ToList();
                }

                // Use the triangulator to get indices for creating triangles
                Triangulator tr = new Triangulator(vertices2D.ToArray());
                int[] indices = tr.Triangulate();

                // Create the Vector3 vertices
                Vector3[] vertices = new Vector3[vertices2D.Count];
                for (int k = 0; k < vertices.Length; k++)
                {
                    vertices[k] = new Vector3(vertices2D[k].x, 0f, vertices2D[k].y);
                }
                // Create the mesh
                Mesh msh = new Mesh();
                msh.vertices = vertices;
                msh.triangles = indices;
                msh.RecalculateNormals();
                msh.RecalculateBounds();

                // Set up game object with mesh;
                sideWalk.GetComponent<MeshFilter>().mesh = msh;

                sideWalks.Add(sideWalk);
            }

            //foreach intersectionCluster unify streets and sidewalks and subtract
            int swNumber = 1;
            foreach (HashSet<int> cluster in intersectionClusters)
            {
                Mesh newMesh = Subtract(UnifyPolygons(sideWalks, "sidewalks", cluster), UnifyPolygons(streetWeb, "streets", cluster));

                //build 3D sidewalk
                List<GameObject> objs = new List<GameObject>();

                GameObject sub = new GameObject("unifiedSideWalks", typeof(MeshFilter), typeof(MeshRenderer));
                sub.transform.parent = this.transform;
                sub.GetComponent<MeshRenderer>().material = (Material)Resources.Load("SideWalkMat");
                sub.GetComponent<MeshFilter>().mesh = newMesh;

                objs.Add(sub);

                GameObject sub1 = new GameObject("unifiedSideWalks", typeof(MeshFilter), typeof(MeshRenderer));
                sub1.transform.parent = this.transform;
                sub1.GetComponent<MeshRenderer>().material = (Material)Resources.Load("SideWalkMat");
                sub1.GetComponent<MeshFilter>().mesh = newMesh;
                sub1.transform.position = new Vector3(0f, 0.2f, 0f);

                objs.Add(sub1);

                GameObject sidewalk = new GameObject("sidewalk", typeof(MeshFilter), typeof(MeshRenderer));
                sidewalk.transform.parent = this.transform;
                sidewalk.GetComponent<MeshRenderer>().material = (Material)Resources.Load("SideWalkMat");
                sidewalk.GetComponent<MeshFilter>().sharedMesh = MeshOps.CreateSolid(newMesh, 0.15f);

                objs.Add(sidewalk);

                UnifyAndClearMesh(objs, "sideWalk" + swNumber, (Material)Resources.Load("SideWalkMat"));
                swNumber += 1;
            }

            foreach (GameObject sw in sideWalks)
                DestroyImmediate(sw.gameObject);
        }
Example #17
0
 public static PolygonSet offsetLineSquare(PolygonSet p, float d)
 {
     if (float.IsNaN(d)) { return p; }
     ClipperOffset co = new ClipperOffset();
     co.AddPaths(p, JoinType.jtSquare, EndType.etClosedPolygon);
     PolygonSet solution = new PolygonSet();
     co.Execute(ref solution, d);
     return solution;
 }
Example #18
0
        public List<GameObject> CreateStreets(List<List<Vector3>> streetsPoly)
        {
            List<GameObject> streets = new List<GameObject>();

            for (int i = 0; i < streetsPoly.Count; i++)
            {
                GameObject street = new GameObject("street" + i, typeof(MeshRenderer), typeof(MeshFilter));
                street.transform.parent = this.transform;
                street.GetComponent<MeshRenderer>().material = (Material)Resources.Load("StreetMat");

                List<List<IntPoint>> solution = new List<List<IntPoint>>();
                //transform vertices of each mesh in points for clipper
                List<IntPoint> intPoint = FromVecToIntPoint(streetsPoly[i].ToArray());
                //offset each mesh
                ClipperOffset co = new ClipperOffset();
                co.AddPath(intPoint, JoinType.jtRound, EndType.etOpenRound);
                co.Execute(ref solution, 700.0);

                List<Vector2> vertices2D = new List<Vector2>();
                for (int j = 0; j < solution.Count; j++)
                {
                    vertices2D = vertices2D.Concat(FromIntPointToVec(solution[j])).ToList();
                }

                // Use the triangulator to get indices for creating triangles
                Triangulator tr = new Triangulator(vertices2D.ToArray());
                int[] indices = tr.Triangulate();

                // Create the Vector3 vertices
                Vector3[] vertices = new Vector3[vertices2D.Count];
                for (int k = 0; k < vertices.Length; k++)
                {
                    vertices[k] = new Vector3(vertices2D[k].x, 0f, vertices2D[k].y);
                }
                // Create the mesh
                Mesh msh = new Mesh();
                msh.vertices = vertices;
                msh.triangles = indices;
                msh.RecalculateNormals();
                msh.RecalculateBounds();

                // Set up game object with mesh;
                street.GetComponent<MeshFilter>().mesh = msh;
                street.AddComponent<MeshCollider>();
                street.transform.position = new Vector3(street.transform.position.x, 0.02f, street.transform.position.z);
                streets.Add(street);
            }
            DrawStreetLineMesh(streetsPoly, streets);
            return streets;
        }
Example #19
0
    public List<List<Vector3>> Offset(float amount, float height)
    {
        var orderedPoints = GetAllOrderedIntPoints();

        var result = new List<List<Vector3>>();

        foreach (var path in orderedPoints)
        {
            Debug.Log("New path");
            foreach (var intpoint in path.Points)
            {
                Debug.Log("Ordered point: " + intpoint.X + ", " + intpoint.Y);
            }
            var co = new ClipperLib.ClipperOffset();
            var endType = path.IsClosedLoop ? ClipperLib.EndType.etClosedLine : ClipperLib.EndType.etOpenSquare;
            co.AddPath(path.Points, ClipperLib.JoinType.jtSquare, endType);

            var results = new List<List<ClipperLib.IntPoint>>();
            co.Execute(ref results, (int)(amount * 1000.0f));

            result.AddRange(results.Select(
                    xs => xs.Select(
                        x => new Vector3((float)x.X / 1000.0f, height, (float)x.Y / 1000.0f)).ToList()));
        }

        return result;
    }
Example #20
0
        private void RecalculateVertices()
        {
            if (points.Count < 2)
            {
                return;
            }

            vertexPositionColorArray = null;

            var lineColor = Color.Red;

            #region clipper
            List<IntPoint> clipperPath = new List<IntPoint>(points.Count);
            foreach (var point in points)
            {
                clipperPath.Add(new IntPoint(point.X * ClipperScale, point.Y * ClipperScale));
            }

            List<List<IntPoint>> clipperSolution = new List<List<IntPoint>>();
            ClipperOffset clipperOffset = new ClipperOffset();

            clipperOffset.AddPath(clipperPath, JoinType.jtRound, EndType.etOpenRound);
            clipperOffset.Execute(ref clipperSolution, lineThickness / 2.0f * ClipperScale);
            #endregion

            #region triangle.net
            InputGeometry InputGeometry = new InputGeometry();
            Mesh TriangleMesh = new Mesh();

            for (int iii = 0; iii < clipperSolution.Count; iii++)
            {
                var trianglePath = clipperSolution[iii].Select(p => new TrianglePoint(p.X / (float)ClipperScale, p.Y / (float)ClipperScale)).ToList();

                if (iii == 0)
                {
                    InputGeometry.AddRing(trianglePath);
                }
                else
                {
                    InputGeometry.AddRingAsHole(trianglePath);
                }
            }
            #endregion

            if (InputGeometry.Count > 0)
            {
                TriangleMesh.Triangulate(InputGeometry);

                vertexPositionColorArray = TriangleMesh.GetTriangleList().Select(v => new VertexPositionColor(new Vector3((float)v.X, (float)v.Y, 0.0f), lineColor)).ToArray();

                vertexBuffer = new VertexBuffer(GraphicsDevice, VertexPositionColor.VertexDeclaration, vertexPositionColorArray.Length, BufferUsage.WriteOnly);
                vertexBuffer.SetData<VertexPositionColor>(vertexPositionColorArray);
            }
        }
		private void AddCharacterMeshes(string currentText, TypeFacePrinter printer)
		{
			int newIndex = asyncMeshGroups.Count;
			StyledTypeFace typeFace = printer.TypeFaceStyle;

			for (int i = 0; i < currentText.Length; i++)
			{
				string letter = currentText[i].ToString();
				TypeFacePrinter letterPrinter = new TypeFacePrinter(letter, typeFace);

				if (CharacterHasMesh(letterPrinter, letter))
				{
#if true
					Mesh textMesh = VertexSourceToMesh.Extrude(letterPrinter, unscaledLetterHeight / 2);
#else
					Mesh textMesh = VertexSourceToMesh.Extrude(letterPrinter, unscaledLetterHeight / 2);
					// this is the code to make rounded tops
					// convert the letterPrinter to clipper polygons
					List<List<IntPoint>> insetPoly = VertexSourceToPolygon.CreatePolygons(letterPrinter);
					// inset them
					ClipperOffset clipper = new ClipperOffset();
					clipper.AddPaths(insetPoly, JoinType.jtMiter, EndType.etClosedPolygon);
					List<List<IntPoint>> solution = new List<List<IntPoint>>();
					clipper.Execute(solution, 5.0);
					// convert them back into a vertex source
					// merge both the inset and original vertex sources together
					// convert the new vertex source into a mesh (triangulate them)
					// offset the inner loop in z
					// create the polygons from the inner loop to a center point so that there is the rest of an approximation of the bubble
					// make the mesh for the bottom 
					// add the top and bottom together
					// done
#endif

					asyncMeshGroups.Add(new MeshGroup(textMesh));

					PlatingMeshGroupData newMeshInfo = new PlatingMeshGroupData();

					newMeshInfo.spacing = printer.GetOffsetLeftOfCharacterIndex(i);
					asyncPlatingDatas.Add(newMeshInfo);
					asyncMeshGroupTransforms.Add(Matrix4X4.Identity);

					PlatingHelper.CreateITraceableForMeshGroup(asyncPlatingDatas, asyncMeshGroups, newIndex, null);
					asyncMeshGroupTransforms[newIndex] *= Matrix4X4.CreateTranslation(new Vector3(0, 0, unscaledLetterHeight / 2));

					newIndex++;
				}

				processingProgressControl.PercentComplete = ((i + 1) * 95 / currentText.Length);
			}
		}
Example #22
0
        List<List<IntPoint>> Offset(List<List<IntPoint>> polygons, double delta)
        {
            var result = new List<List<IntPoint>>();

            var clipper = new ClipperOffset();
            clipper.AddPaths(polygons, JoinType.jtSquare, EndType.etClosedPolygon);
            clipper.Execute(ref result, delta);

            return result;
        }
Example #23
0
    //static GameObject CreateBaseMeshFromColl(LevelBase l, Transform, LevelShape[] s)
    //{
    //}
    public void CreateForLine(List<Vector2> vecs, float thickness)
    {
        float factor = 100;

        ClipperOffset off = new ClipperOffset();

        Clipper c = new Clipper();

        for (int i = 1; i < vecs.Count; i++)
        {
            Vector2 start = vecs[i - 1];
            Vector2 end = vecs[i];

            List<List<IntPoint>> sol = new List<List<IntPoint>>();

            List<IntPoint> l = new List<IntPoint>() {
            new IntPoint((int)(start.x * factor), (int)(start.y * factor)),
            new IntPoint((int)(end.x * factor), (int)(end.y * factor)) };
            off.AddPath(l, JoinType.jtSquare, EndType.etOpenSquare);
            off.Execute(ref sol, thickness);

            c.AddPaths(sol, PolyType.ptSubject, true);
        }
        List<List<IntPoint>> polys = new List<List<IntPoint>>();
        c.Execute(ClipType.ctUnion, polys);

        //off.AddPath()
    }
Example #24
0
        public void DrawSegment(List<Vector3> segment, List<Mesh> intersectionPolys, List<GameObject> lines)
        {
            List<List<IntPoint>> solution = new List<List<IntPoint>>();
            //transform vertices of each mesh in points for clipper
            List<IntPoint> intPoint = FromVecToIntPoint(segment.ToArray());
            //offset each mesh
            ClipperOffset co = new ClipperOffset();
            co.AddPath(intPoint, JoinType.jtRound, EndType.etOpenRound);
            co.Execute(ref solution, 100.0);

            List<Vector2> vertices2D = new List<Vector2>();
            for (int j = 0; j < solution.Count; j++)
            {
                vertices2D = vertices2D.Concat(FromIntPointToVec(solution[j])).ToList();
            }

            // Use the triangulator to get indices for creating triangles
            Triangulator tr = new Triangulator(vertices2D.ToArray());
            int[] indices = tr.Triangulate();

            // Create the Vector3 vertices
            Vector3[] vertices = new Vector3[vertices2D.Count];
            for (int k = 0; k < vertices.Length; k++)
            {
                vertices[k] = new Vector3(vertices2D[k].x, 0f, vertices2D[k].y);
            }
            // Create the mesh
            Mesh msh = new Mesh();
            msh.vertices = vertices;
            msh.triangles = indices;
            msh.RecalculateNormals();
            msh.RecalculateBounds();

            Mesh newMesh = ExecuteMultiDifferencePoly(msh, intersectionPolys);
            GameObject lineSegment = new GameObject("segment", typeof(MeshFilter), typeof(MeshRenderer));
            lineSegment.GetComponent<MeshFilter>().sharedMesh = newMesh;
            lines.Add(lineSegment);
        }
Example #25
0
 public static PolygonSet offsetLineRound(Polygon p, float d)
 {
     if (float.IsNaN(d)) { return new List<List<IntPoint>>() {p}; }
     ClipperOffset co = new ClipperOffset();
     co.AddPath(p, JoinType.jtRound, EndType.etClosedPolygon);
     PolygonSet solution = new PolygonSet();
     co.Execute(ref solution, d);
     return solution;
 }
Example #26
0
        /// <summary>
        /// Create a slice from an open path with the given width
        /// </summary>
        /// <param name="path"></param>
        /// <param name="width"></param>
        /// <param name="plane"></param>
        public Slice(LineStrip path, float width, Plane plane, bool closed = false)
        {
            this.plane = plane;
            transform = plane.CreateMatrix();
            transform = Matrix4.Mult(transform, Matrix4.CreateScale(scale));
            inverseTransform = Matrix4.Invert(transform);
            polyTree = new PolyTree();

            ClipperOffset co = new ClipperOffset();
            co.ArcTolerance = scale * 0.0001f;
            if (closed)
            {
                co.AddPath(LineStripToPolygon(path), JoinType.jtRound, EndType.etClosedLine);
            }
            else
            {
                co.AddPath(LineStripToPolygon(path), JoinType.jtRound, EndType.etOpenRound);
            }
            co.Execute(ref this.polyTree, scale * width / 2.0f);
        }
Example #27
0
 public void Offset(float offset)
 {
     Paths polygons = Clipper.ClosedPathsFromPolyTree(polyTree);
     ClipperOffset co = new ClipperOffset();
     co.ArcTolerance = scale * .0001f;
     co.AddPaths(polygons, JoinType.jtRound, EndType.etClosedPolygon);
     polyTree = new PolyTree();
     Paths offsetPaths = new Paths();
     co.Execute(ref offsetPaths, scale * offset);
     offsetPaths = Clipper.CleanPolygons(offsetPaths, scale * .0001f);
     polyTree = PolygonsToPolyTree(offsetPaths);
 }
 private PolyTree Offset(PolyTree input, double delta)
 {
     var clipperOffset = new ClipperOffset();
      for (var currentNode = input.GetFirst(); currentNode != null; currentNode = currentNode.GetNext()) {
     clipperOffset.AddPath(currentNode.Contour, JoinType.jtMiter, EndType.etClosedPolygon);
      }
      var result = new PolyTree();
      clipperOffset.Execute(ref result, delta);
      return result;
 }
Example #29
0
		public static Polygons Offset(this Polygons polygons, long distance)
		{
			ClipperOffset offseter = new ClipperOffset();
			offseter.AddPaths(polygons, JoinType.jtMiter, EndType.etClosedPolygon);
			Paths solution = new Polygons();
			offseter.Execute(ref solution, distance);
			return solution;
		}
Example #30
0
        /// <summary>
        /// Offsets the specified polylines.
        /// </summary>
        /// <param name="polylines">A list of polylines</param>
        /// <param name="openFilletType">Optional: line endtype (Butt, Square, Round)</param>
        /// <param name="closedFilltetType">Optional: join type: Round, Miter (uses miter parameter) or Square</param>
        /// <param name="plane">Plane to project the polylines to</param>
        /// <param name="tolerance">Tolerance: Cutoff point. Eg. point {1.245; 9.244351; 19.3214} with precision {0.1} will be cut
        /// off to {1.2; 9.2; 19.3}.</param>
        /// <param name="distance">Distances to offset set of shapes.</param>
        /// <param name="miter">Miter deterimines how long narrow spikes can become before they are cut off: A miter setting of 2
        /// means not longer than 2 times the offset distance. A miter of 25 will give big spikes.</param>
        /// <param name="arcTolerance">The arc tolerance.</param>
        /// <param name="outContour">The out contour.</param>
        /// <param name="outHoles">The out holes.</param>
        public static void Offset(IEnumerable <Polyline> polylines, List <OpenFilletType> openFilletType,
                                  List <ClosedFilletType> closedFilltetType, Plane plane, double tolerance, IEnumerable <double> distance,
                                  double miter, double arcTolerance, out List <List <Polyline> > outContour, out List <List <Polyline> > outHoles, EndType endType = default)
        {
            outContour = new List <List <Polyline> >();
            outHoles   = new List <List <Polyline> >();

            /*
             * iEndType: How to handle open ended polygons.
             * Open				Closed
             * etOpenSquare		etClosedLine    (fill inside & outside)
             * etOpenRound			etClosedPolygon (fill outside only)
             * etOpenButt
             *
             * See: http://www.angusj.com/delphi/clipper/documentation/Docs/Units/ClipperLib/Types/EndType.htm
             */

            /*
             * jtJoinType
             * How to fill angles of closed polygons
             * jtRound: Round
             * jtMiter: Square with variable distance
             * jtSquare: Square with fixed distance (jtMiter = 1)
             */

            var cOffset = new ClipperOffset(miter, arcTolerance);
            var i       = 0;

            foreach (var pl in polylines)
            {
                var et = EndType.etOpenButt;
                var jt = JoinType.jtSquare;
                if (pl.IsClosed)
                {
                    et = EndType.etClosedLine;
                }
                else if (openFilletType.Count != 0)
                {
                    var oft = IndexOrLast(openFilletType, i);
                    switch (oft)
                    {
                    case OpenFilletType.Butt:
                        et = EndType.etOpenButt;
                        break;

                    case OpenFilletType.Round:
                        et = EndType.etOpenRound;
                        break;

                    case OpenFilletType.Square:
                        et = EndType.etOpenSquare;
                        break;
                    }
                }
                else
                {
                    et = EndType.etOpenButt;
                }

                if (closedFilltetType.Count != 0)
                {
                    var cft = IndexOrLast(closedFilltetType, i);
                    switch (cft)
                    {
                    case ClosedFilletType.Miter:
                        jt = JoinType.jtMiter;
                        break;

                    case ClosedFilletType.Round:
                        jt = JoinType.jtRound;
                        break;

                    case ClosedFilletType.Square:
                        jt = JoinType.jtSquare;
                        break;
                    }
                }
                else
                {
                    jt = JoinType.jtSquare;
                }
                if (endType != default)
                {
                    et = endType;
                }
                cOffset.AddPath(pl.ToPath2D(plane, tolerance), jt, et);
                i++;
            }

            foreach (var offsetDistance in distance)
            {
                var tree = new PolyTree();
                cOffset.Execute(ref tree, offsetDistance / tolerance);

                var holes    = new List <Polyline>();
                var contours = new List <Polyline>();
                foreach (var path in tree.Iterate())
                {
                    if (path.Contour.Count == 0)
                    {
                        continue;
                    }
                    Polyline polyline = path.Contour.ToPolyline(plane, tolerance, !path.IsOpen);
                    if (path.IsHole)
                    {
                        holes.Add(polyline);
                    }
                    else
                    {
                        contours.Add(polyline);
                    }
                }

                outContour.Add(contours);
                outHoles.Add(holes);
            }
        }