public void alignPathsDirectionsWithSource(ref Paths segs, ref Paths sourceSegs)
        {
            // The assumption is that a seg in segs will be on only one of the sourceSegs.

            foreach (Path seg in segs)
            {
                if (seg == null || seg.Count < 2)
                {
                    continue;
                }
                IntPoint first  = seg[0];
                IntPoint second = seg[1];

                bool foundSource = false;

                foreach (Path src in sourceSegs)
                {
                    // setp through each src line to see if first falls on it.
                    for (int k = 0; k < src.Count - 1; k++)
                    {
                        if (PointOnLineSegment(first, src[k], src[k + 1], true))
                        {
                            //Debug.Log(first.X + ", "+ first.Y + " on line " + src[k].X + ", " +src[k].Y + "->" +src[k+1].X + ", " + src[k+1].Y);

                            if (AXSegment.pointsAreEqual(second, src[k]) || (Pather.Distance(src[k], second) < Pather.Distance(src[k], first)))
                            {
                                foundSource = true;
                                seg.Reverse();
                            }

                            break;
                        }
                    }

                    if (foundSource)
                    {
                        break;
                    }
                }
            }
        }
Exemple #2
0
        /// <summary>
        ///  Home-grown offsetter that can handle open paths (which clipper can't)
        ///  and returns paths for left and right.
        /// </summary>
        /// <returns>The offsets.</returns>
        /// <param name="planSpline">Plan spline.</param>
        /// <param name="thickR">Thick r.</param>
        /// <param name="thickL">Thick l.</param>
        public static Paths  wallOffsets(Spline planSpline, float thickR, float thickL)
        {
            /*
             *      When generating a PlanSweep, we need to know the breaking angles of each plan layer.
             *      This is because the original plan node might be convex at a certain section offset, it is concave, depending on how far out that section goes.
             *
             *      To do this:
             *      1. for each section node, do an offset using clipper - or use bevelAngles of the orginnal plan and make a new spline, whichever is more efficient
             *      2. store these offset plans as AX.Splines in a list.
             *      3. use these Splines for the isSharp and isBlend conditionals
             *
             */

            if (planSpline == null || planSpline.controlVertices == null || planSpline.controlVertices.Count == 0)
            {
                return(null);
            }


//			if (tex == null)
//				return null;



            Paths paths = new Paths();

            Path pathR = new Path();
            Path pathL = new Path();

            float samePointTolerence = .001f;


            int terminIndexSubtractor = 0;

            if (Vector2.Distance(planSpline.controlVertices[0], planSpline.controlVertices[planSpline.controlVertices.Count - 1]) < samePointTolerence)
            {
                terminIndexSubtractor = 1;
            }


            Matrix4x4 prevBevelTransform;

            for (int i = 0; i < planSpline.controlVertices.Count - terminIndexSubtractor; i++)
            {
                Matrix4x4 bevelTransform = planSpline.nodeTransforms[i];

                if (planSpline.shapeState == ShapeState.Open)
                {
                    if (i == 0)
                    {
                        bevelTransform = planSpline.begTransform;
                    }
                    else if (i == planSpline.controlVertices.Count - 1)
                    {
                        bevelTransform = planSpline.endTransform;
                    }
                }


                // Transform plan vert
                Vector3 vertr = bevelTransform.MultiplyPoint(new Vector3(thickR, 0, 0));
                Debug.Log(vertr);

                pathR.Add(Pather.Vector2IPWithPrecision(new Vector2(vertr.x, vertr.z)));

                Vector3 vertl = bevelTransform.MultiplyPoint(new Vector3(thickL, 0, 0));
                pathL.Add(Pather.Vector2IPWithPrecision(new Vector2(vertl.x, vertl.z)));
            }

            paths.Add(pathR);
            paths.Add(pathL);

            return(paths);
        }
Exemple #3
0
        public static Mesh triangulatePolyNode(PolyNode node, AXTexCoords tex, int seglenBigInt = 1000000)
        {
            //Debug.Log ("D " + seglenBigInt);
            Polygon _polygon = null;

            if (seglenBigInt < 10)
            {
                seglenBigInt = 999999;
            }


            List <Mesh> meshes = new List <Mesh>();

            // Contour is Solid

            PolygonPoints _points = null;

            if (seglenBigInt > 0 && seglenBigInt != 9999999)
            {
                _points = AXGeometryTools.Utilities.path2polygonPts(Pather.segmentPath(Clipper.CleanPolygon(node.Contour), seglenBigInt));
            }
            else
            {
                _points = AXGeometryTools.Utilities.path2polygonPts(Clipper.CleanPolygon(node.Contour));
            }

            // POLYGON
            if (_points.Count >= 3)
            {
                _polygon = new Polygon(_points);
            }

            //Debug.Log ("_polygon="+_points.Count);
            // ADD HOLES TO POLYGON
            foreach (PolyNode subnode in node.Childs)
            {
                PolygonPoints hpoints = null;

                if (seglenBigInt > 0 && seglenBigInt != 9999999)
                {
                    hpoints = AXGeometryTools.Utilities.path2polygonPts(Pather.segmentPath(Clipper.CleanPolygon(subnode.Contour), seglenBigInt));
                }
                else
                {
                    hpoints = AXGeometryTools.Utilities.path2polygonPts(Clipper.CleanPolygon(subnode.Contour));
                }



                if (hpoints.Count >= 3)
                {
                    _polygon.AddHole(new Polygon(hpoints));
                }
            }

            try {
                // STEINER POINTS

                ClipperOffset co = new ClipperOffset();
                co.AddPath(node.Contour, AXClipperLib.JoinType.jtSquare, AXClipperLib.EndType.etClosedPolygon);

                //addSteinerPointsAtAllOffsets(ref _polygon, ref co, seglenBigInt/AXGeometryTools.Utilities.IntPointPrecision, seglenBigInt);
                addSteinerPointsAtAllOffsets(ref _polygon, ref co, (float)seglenBigInt / ((float)AXGeometryTools.Utilities.IntPointPrecision), seglenBigInt);



                P2T.Triangulate(_polygon);

                meshes.Add(polygon2mesh(_polygon, tex));
            } catch {
                //Debug.Log ("Can't triangulate: probably point on edge.");
            }


            // Continue down the tree...

            /*
             * foreach(PolyNode cnode in node.Childs)
             * {
             *      Mesh submesh = triangulatePolyNode(cnode, tex);
             *      if (submesh != null)
             *              meshes.Add(submesh);
             * }
             */



            CombineInstance[] combine = new CombineInstance[meshes.Count];
            for (int i = 0; i < meshes.Count; i++)
            {
                combine[i].mesh      = meshes[i];
                combine[i].transform = Matrix4x4.identity;
            }



            Mesh mesh = new Mesh();

            mesh.CombineMeshes(combine);

            mesh.RecalculateNormals();

            return(mesh);
        }
Exemple #4
0
        /* bridges to poly2tri
         *
         */



        public static Mesh triangulate(Path path, AXTexCoords tex, int seglen = 0)
        {
            /* Assume a single path with no holes
             * and return a mesh.
             */
            if (path == null || path.Count < 3)
            {
                return(null);
            }


            if (path[path.Count - 1].X == path[0].X && path[path.Count - 1].Y == path[0].Y)
            {
                path.RemoveAt(path.Count - 1);
            }

            else if (AXGeometryTools.Utilities.IntPointsAreNear(path[0], path[path.Count - 1]))
            {
                path.RemoveAt(path.Count - 1);
            }



            //Paths tmpPaths = Clipper.SimplifyPolygon (path);


            //CombineInstance[] combinator = new CombineInstance[tmpPaths.Count];

            //for (int i = 0; i < tmpPaths.Count; i++) {
            Mesh          mesh = null;
            PolygonPoints _points;            // = AXGeometryTools.Utilities.path2polygonPts (Pather.cleanPath(path));

            if (seglen > 0)
            {
                _points = AXGeometryTools.Utilities.path2polygonPts(Pather.segmentPath(Clipper.CleanPolygon(path), seglen));
            }
            else
            {
                _points = AXGeometryTools.Utilities.path2polygonPts(Clipper.CleanPolygon(path));
            }



            Polygon _polygon = null;

            if (_points.Count >= 3)
            {
                _polygon = new Polygon(_points);


                if (_polygon != null)
                {
                    try {
                        // Testing Steiner

//							for (int j = -10; j<10; j++)
//							{
//								for (int k = -10; k<10; k++)
//									_polygon.AddSteinerPoint(new TriangulationPoint(.1f*j, k*.1f));
//							}


                        P2T.Triangulate(_polygon);


                        //foreach (DelaunayTriangle triangle in _polygon.Triangles)
                        mesh = polygon2mesh(_polygon, tex);
                    } catch {
                        Debug.Log("Can't triangulate: probably point on edge.");
                    }
                }

                //combinator[i].mesh        = mesh;
                //combinator [i].transform = Matrix4x4.identity;
                //return mesh;

                //}
            }


//			Mesh returnMesh = new Mesh();
//				returnMesh.CombineMeshes(combinator);
//				return returnMesh;
            return(mesh);
        }
Exemple #5
0
        public static Mesh triangulate(List <PolyNode> childs, AXTexCoords tex, int seglenBigInt = 1000000)
        {
            //Debug.Log ("C " + seglenBigInt);
            Polygon _polygon = null;


            List <Mesh> meshes = new List <Mesh>();

            if (seglenBigInt < 10)
            {
                seglenBigInt = 100000;
            }


            //int count = 0;
            foreach (PolyNode node in childs)
            {
                // Contour is Solid
//				List<TriangulationPoint> tripoints = new List<TriangulationPoint>();
//
//				// Testing Steiner
//				int cells = 6;
//				for (int j = -cells/2; j<cells/2; j++)
//				{
//					for (int k = -cells/3; k<cells/2; k++)
//						if (Clipper.PointInPolygon( AXGeometryTools.Utilities.Vec2_2_IntPt(new Vector2(2f*j, k*2f)), node.Contour) > 0)
//						{
//							//Debug.Log("add steiner " + .4f*j +", " + k*.2f);
//							tripoints.Add(new TriangulationPoint(.4f*j, k*.2f));
//						}
//				}


                PolygonPoints _points = null;

                if (seglenBigInt > 0 && seglenBigInt != 9999999)
                {
                    _points = AXGeometryTools.Utilities.path2polygonPts(Pather.segmentPath(Clipper.CleanPolygon(node.Contour), seglenBigInt));
                }
                else
                {
                    _points = AXGeometryTools.Utilities.path2polygonPts(Clipper.CleanPolygon(node.Contour));
                }

                // POLYGON
                if (_points.Count >= 3)
                {
                    _polygon = new Polygon(_points);
                }

                // ADD HOLES TO POLYGON
                foreach (PolyNode subnode in node.Childs)
                {
                    PolygonPoints hpoints = null;

                    if (seglenBigInt > 0 && seglenBigInt != 9999999)
                    {
                        hpoints = AXGeometryTools.Utilities.path2polygonPts(Pather.segmentPath(Clipper.CleanPolygon(subnode.Contour), seglenBigInt));
                    }
                    else
                    {
                        hpoints = AXGeometryTools.Utilities.path2polygonPts(Clipper.CleanPolygon(subnode.Contour));
                    }

                    if (hpoints.Count >= 3)
                    {
                        _polygon.AddHole(new Polygon(hpoints));
                    }
                }

                try {
                    // STEINER POINTS

                    ClipperOffset co = new ClipperOffset();
                    co.AddPath(node.Contour, AXClipperLib.JoinType.jtSquare, AXClipperLib.EndType.etClosedPolygon);

                    addSteinerPointsAtAllOffsets(ref _polygon, ref co, (float)seglenBigInt / ((float)AXGeometryTools.Utilities.IntPointPrecision), seglenBigInt);



                    P2T.Triangulate(_polygon);
                    meshes.Add(polygon2mesh(_polygon, tex));
                } catch {
                    //Debug.Log ("Can't triangulate: probably point on edge.");
                }


                // Continue down the tree...
                foreach (PolyNode cnode in node.Childs)
                {
                    Mesh submesh = triangulate(cnode, tex);
                    if (submesh != null)
                    {
                        meshes.Add(submesh);
                    }
                }
            }

            CombineInstance[] combine = new CombineInstance[meshes.Count];
            for (int i = 0; i < meshes.Count; i++)
            {
                combine[i].mesh      = meshes[i];
                combine[i].transform = Matrix4x4.identity;
            }



            Mesh mesh = new Mesh();

            mesh.CombineMeshes(combine);

            mesh.RecalculateNormals();

            return(mesh);
        }
        // RAIL

        public void genrateRail()
        {
            // generate a rail for all three: difference, intersection, union


            if (inputs.Count == 0)
            {
                return;
            }


            PolyFillType subjPolyFillType = PolyFillType.pftNonZero;
            //if (hasHoles)
            //subjPolyFillType = PolyFillType.pftPositive;


            //* organize by solids, holes (from SOLID designation) and clippers (from VOID designation)
            Paths subjPaths = new Paths();
            Paths clipPaths = new Paths();

            AXParameter inp = null;
            AXParameter src = null;


            Paths segments = new Paths();
            Path  tmp      = null;


            for (int i = 0; i < inputs.Count; i++)
            {
                inp = inputs [i];
                src = inp.DependsOn;

                if (src == null)
                {
                    continue;
                }

                Paths srcPaths = src.getPaths();

                if (srcPaths == null)
                {
                    continue;
                }

                if (inp.polyType == PolyType.ptSubject)
                {
                    subjPaths.AddRange(srcPaths);


                    foreach (Path sp in srcPaths)
                    {
                        // When clipping open shapes, don't add a closingsegment:
                        int ender = (inp.shapeState == ShapeState.Open) ? sp.Count - 1 : sp.Count;

                        for (int j = 0; j < ender; j++)
                        {
                            int next_j = (j == sp.Count - 1) ? 0 : j + 1;
                            tmp = new Path();
                            tmp.Add(sp[j]);
                            tmp.Add(sp[next_j]);
                            segments.Add(tmp);
                        }
                    }

                    //subjPaths.AddRange (src.getTransformedHolePaths());
                }
                else if (inp.polyType == PolyType.ptClip)
                {
                    clipPaths.AddRange(srcPaths);
                    //clipPaths.AddRange (src.getTransformedHolePaths());
                }
                else
                {
                    continue;
                }
            }


            // turn subjs and holes into segments to be clipped
//			foreach(Path sp in subjPaths)
//			{
//				// each path
//				//int ender =
//				for(int i=0; i<sp.Count-1; i++)
//				{
//					int next_i = (i == sp.Count-1) ? 0 : i+1;
//					tmp = new Path();
//					tmp.Add (sp[i]);
//					tmp.Add (sp[next_i]);
//					segments.Add(tmp);
//				}
//			}

            //Debug.Log ("segments");
            //Archimatix.printPaths(segments);

            Clipper railc = new Clipper(Clipper.ioPreserveCollinear);

            if (segments != null)
            {
                railc.AddPaths(segments, PolyType.ptSubject, false);
            }

            if (clipPaths != null)
            {
                railc.AddPaths(clipPaths, PolyType.ptClip, true);
            }

            AXClipperLib.PolyTree solutionRail = new AXClipperLib.PolyTree();



            // DIFFERENCE_RAIL
            if ((differenceRail.Dependents != null && differenceRail.Dependents.Count > 0) || combineType == CombineType.DifferenceRail)
            {
                // Execute Difference
                railc.Execute(ClipType.ctDifference, solutionRail, subjPolyFillType, PolyFillType.pftNonZero);


                differenceRail.polyTree = null;


                differenceRail.paths = assembleRailPathsFromClippedSegments(solutionRail);



//				Debug.Log("******** " + differenceRail.paths.Count);
//				Pather.printPaths(differenceRail.paths);


                if (differenceRail.paths.Count == 0)
                {
                    differenceRail.paths = subjPaths;
                }

                if (differenceRail.paths.Count > 1)
                {
                    differenceRail.paths = Pather.cleanPaths(differenceRail.paths);
                }

//				Debug.Log("-- " + differenceRail.paths.Count);
//				Pather.printPaths(differenceRail.paths);


                alignPathsDirectionsWithSource(ref differenceRail.paths, ref segments);



                if (differenceRail.paths.Count > 1)
                {
                    joinPathsIfEndpointsMatch(ref differenceRail.paths);
                }



                thickenAndOffset(ref differenceRail, differenceRail);
            }

            // INTERSECTION RAIL
            if ((intersectionRail.Dependents != null && intersectionRail.Dependents.Count > 0) || combineType == CombineType.IntersectionRail)
            {
                //railc.Execute(ClipType.ctIntersection, solutionRail, subjPolyFillType, PolyFillType.pftNonZero);
                railc.Execute(ClipType.ctIntersection, solutionRail, PolyFillType.pftEvenOdd, PolyFillType.pftEvenOdd);

                intersectionRail.polyTree = null;

                intersectionRail.paths = assembleRailPathsFromClippedSegments(solutionRail);
                if (intersectionRail.paths.Count == 0)
                {
                    AXGeometryTools.Utilities.reversePaths(ref intersectionRail.paths);
                }

                alignPathsDirectionsWithSource(ref intersectionRail.paths, ref segments);

                thickenAndOffset(ref intersectionRail, intersectionRail);
            }
        }