Example #1
0
        public static bool addSteinerPointsAtOffset(ref Polygon _polygon, ref ClipperOffset co, float offset, int seglenBigInt)
        {
            PolyTree resPolytree = new AXClipperLib.PolyTree();

            co.Execute(ref resPolytree, (double)(-offset * AXGeometryTools.Utilities.IntPointPrecision));
            Paths paths = Clipper.PolyTreeToPaths(resPolytree);

            if (paths != null && paths.Count > 0 && paths[0] != null && paths[0].Count > 0)
            {
                foreach (Path path in paths)
                {
                    if (path != null && path.Count > 0)
                    {
                        Path ppp = Pather.segmentPath(path, seglenBigInt);
                        if (ppp != null && ppp.Count > 0)
                        {
                            foreach (IntPoint ip in ppp)
                            {
                                _polygon.AddSteinerPoint(new TriangulationPoint((double)ip.X / (double)AXGeometryTools.Utilities.IntPointPrecision, (double)ip.Y / (double)AXGeometryTools.Utilities.IntPointPrecision));
                            }
                        }
                    }
                }


                return(true);
            }
            return(false);
        }
Example #2
0
        // TRANSFORM_POLY_TREE
        public static void shiftPolyTree(AXClipperLib.PolyTree polyTree, IntPoint ip)
        {
            if (polyTree == null)
            {
                return;
            }

            if (polyTree.Childs != null && polyTree.Childs.Count > 0)
            {
                shiftPolyNode(polyTree.Childs, ip);
            }
        }
Example #3
0
        public static PolyNode mergeSubjPathAndClipPath(Path subj_p, Path clip_p)
        {
            Clipper c = new Clipper(Clipper.ioPreserveCollinear);

            c.AddPath(subj_p, PolyType.ptSubject, true);
            c.AddPath(clip_p, PolyType.ptClip, true);

            PolyTree polyTree = new AXClipperLib.PolyTree();

            c.Execute(ClipType.ctDifference, polyTree, PolyFillType.pftNonZero, PolyFillType.pftNonZero);

            return(polyTree);
        }
Example #4
0
        public static Paths offset(Paths paths, float offset)
        {
            // Set cleaning precision
            IntRect brect = Clipper.GetBounds(paths);
            int     cleanPolygonPrecision = 2;

            if ((brect.right - brect.left) > 10000)
            {
                cleanPolygonPrecision = 30;
            }


            // Clean...
            AXClipperLib.JoinType jt = AXClipperLib.JoinType.jtSquare;
            paths = AXGeometryTools.Utilities.cleanPaths(paths, cleanPolygonPrecision);



            Paths resPaths = new Paths();

            AXClipperLib.PolyTree resPolytree = null;


            // OFFSETTER
            ClipperOffset co = new ClipperOffset();

            co.MiterLimit = 2.0f;



            foreach (Path path in paths)
            {
                co.Clear();
                resPolytree = null;

                co.AddPath(path, jt, AXClipperLib.EndType.etClosedPolygon);                  //JoinType.jtSquare, AXClipperLib.EndType.etClosedPolygon);

                // this resPolytree has transformed curves in it
                resPolytree = new AXClipperLib.PolyTree();
                co.Execute(ref resPolytree, (double)(offset * AXGeometryTools.Utilities.IntPointPrecision));
                resPaths.AddRange(Clipper.ClosedPathsFromPolyTree(resPolytree));
            }

            return(resPaths);
        }
Example #5
0
        // 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)
            {
                railc.Execute(ClipType.ctDifference, solutionRail, subjPolyFillType, PolyFillType.pftNonZero);

                differenceRail.polyTree = null;

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

                alignPathsDirestionsWithSource(ref differenceRail.paths, ref segments);

                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);
                }

                alignPathsDirestionsWithSource(ref intersectionRail.paths, ref segments);

                thickenAndOffset(ref intersectionRail, intersectionRail);
            }
        }
Example #6
0
        public static void thickenAndOffset(ref AXParameter sp, AXParameter src)
        {
            if (sp == null || src == null)
            {
                return;
            }
            //sp.polyTree = null;



            float thickness = sp.thickness;
            float roundness = sp.roundness;
            float offset    = sp.offset;
            bool  flipX     = sp.flipX;

            //Debug.Log(sp.parametricObject.Name + "." + sp.Name +"."+ sp.offset);

            //bool srcIsCC = src.isCCW();



            Paths subjPaths = src.getClonePaths();

            if (subjPaths == null)
            {
                return;
            }


            // FLIP_X
            if (flipX)
            {
                //Debug.Log(subjPaths.Count);
                //AXGeometryTools.Utilities.printPaths(subjPaths);

                subjPaths = AXGeometryTools.Utilities.transformPaths(subjPaths, Matrix4x4.TRS(Vector3.zero, Quaternion.identity, new Vector3(-1, 1, 1)));

                sp.transformedControlPaths = AXGeometryTools.Utilities.transformPaths(sp.transformedControlPaths, Matrix4x4.TRS(Vector3.zero, Quaternion.identity, new Vector3(-1, 1, 1)));
            }



            // SYMMETRY
            if (sp.symmetry)
            {
                if (subjPaths != null && subjPaths.Count > 0)
                {
                    for (int i = 0; i < subjPaths.Count; i++)
                    {
                        Path orig = subjPaths[i];

                        Path sym = new Path();

                        float seperation = sp.symSeperation * AXGeometryTools.Utilities.IntPointPrecision;
                        float apex       = .1f * seperation;


                        for (int j = 0; j < orig.Count; j++)
                        {
                            sym.Add(new IntPoint(orig[j].X + seperation / 2, orig[j].Y));
                        }

                        // midpoint. slightly raised
                        sym.Add(new IntPoint(0, orig[orig.Count - 1].Y + apex));

                        for (int j = orig.Count - 1; j >= 0; j--)
                        {
                            sym.Add(new IntPoint(-orig[j].X - seperation / 2, orig[j].Y));
                        }

                        subjPaths[i] = sym;
                    }
                }
            }



            AX.Generators.Generator2D gener2D = sp.parametricObject.generator as AX.Generators.Generator2D;


            if (subjPaths != null && gener2D != null && (gener2D.scaleX != 1 || gener2D.scaleY != 1))
            {
                sp.transformedButUnscaledOutputPaths = AX.Generators.Generator2D.transformPaths(subjPaths, gener2D.localUnscaledMatrix);
            }
            else
            {
                sp.transformedButUnscaledOutputPaths = null;
            }



            //cleanPolygonPrecision
            IntRect brect = Clipper.GetBounds(subjPaths);

            if ((brect.right - brect.left) < 10000)
            {
                cleanPolygonPrecision = 2;
            }
            else
            {
                cleanPolygonPrecision = 30;
            }

            //Debug.Log("cleanPolygonPrecision="+cleanPolygonPrecision);

            /*
             * if (offset_p.FloatVal == 0 && wallthick_p.FloatVal == 0)
             * {
             *      sp.polyTree = src.polyTree;
             *      sp.paths = src.paths;
             *      return;
             * }
             *
             */
            //sp.polyTree = null;



            //Debug.Log("new count a = " + subjPaths[0].Count);


            bool hasOffset = false;

            sp.hasThickness = false;


            Paths resPaths = new Paths();

            AXClipperLib.PolyTree resPolytree = null;

            ClipperOffset co = new ClipperOffset();


            //co.ArcTolerance = sp.arcTolerance;
            float smooth    = (float)(120 / (sp.arcTolerance * sp.arcTolerance));
            float smoothLOD = ((smooth - .048f) * sp.parametricObject.model.segmentReductionFactor) + .048f;

            co.ArcTolerance = (float)(Mathf.Sqrt(120 / smoothLOD));


            co.MiterLimit = 2.0f;


            //if (offset != 0)


            // 1. Offset? Can't offset an open shape
            if (sp.shapeState == ShapeState.Closed && (sp.endType == AXClipperLib.EndType.etClosedLine || sp.endType == AXClipperLib.EndType.etClosedPolygon))
            {
                //AXClipperLib.JoinType jt = (sp.endType == AXClipperLib.EndType.etClosedLine) ? JoinType.jtMiter : sp.joinType;//output.joinType;
                AXClipperLib.JoinType jt = (sp.parametricObject.model.segmentReductionFactor < .15f) ? AXClipperLib.JoinType.jtSquare  : sp.joinType;                //output.joinType;
                //Debug.Log ("sp.endType="+sp.endType+", jt="+jt);

                if (roundness != 0)
                {
                    // reduce
                    co.Clear();

                    if (subjPaths != null)
                    {
                        co.AddPaths(AXGeometryTools.Utilities.cleanPaths(subjPaths, cleanPolygonPrecision), jt, AXClipperLib.EndType.etClosedPolygon);                           //JoinType.jtSquare, AXClipperLib.EndType.etClosedPolygon);
                    }
                    co.Execute(ref subjPaths, (double)(-roundness * AXGeometryTools.Utilities.IntPointPrecision));
                }

                offset += roundness;

                if (subjPaths != null)
                {
                    subjPaths = Clipper.SimplifyPolygons(subjPaths, PolyFillType.pftNonZero);
                }

                co.Clear();

                hasOffset = true;

//				if (offset != 0 || thickness == 0) { // --! PUC ** Removed because the pass thru was causing a problem with Instance2D of a ShapeMerger
                // Do Offset

                // = true;

                if (subjPaths != null)
                {
                    // After changes made mid April to allow for FlipX, this started doubling the localMatrix and thus became redundent, though not sure why.
                    //if (gener2D != null)
                    //	sp.transformedAndScaledButNotOffsetdOutputPaths = AX.Generators.Generator2D.transformPaths(subjPaths, gener2D.localMatrix);

                    co.AddPaths(AXGeometryTools.Utilities.cleanPaths(subjPaths, cleanPolygonPrecision), jt, AXClipperLib.EndType.etClosedPolygon);                              //JoinType.jtSquare, AXClipperLib.EndType.etClosedPolygon);

                    // this resPolytree has transformed curves in it
                    resPolytree = new AXClipperLib.PolyTree();
                    co.Execute(ref resPolytree, (double)(offset * AXGeometryTools.Utilities.IntPointPrecision));
                }
//				}
                if (thickness > 0)
                {                       // No offset, but is closed
                    sp.transformedAndScaledButNotOffsetdOutputPaths = null;
                    if (src.polyTree != null)
                    {
                        if (thickness > 0)
                        {
                            resPaths = subjPaths;                             // Clipper.PolyTreeToPaths(src.polyTree);
                        }
                        else
                        {
                            resPolytree = src.polyTree;
                        }
                    }
                    else
                    {
                        resPaths = subjPaths;
                    }
                }
            }
            else
            {
                //resPolytree = src.polyTree;
                if (src.polyTree != null)
                {
                    if (thickness > 0)
                    {
                        resPaths = subjPaths;                         // Clipper.PolyTreeToPaths(src.polyTree);
                    }
                    else
                    {
                        resPolytree = src.polyTree;
                    }
                }
                else
                {
                    resPaths = subjPaths;
                }
            }


            // 2. Thickness?
            //subjPaths = sp.getPaths();


            if ((sp.endType != AXClipperLib.EndType.etClosedPolygon) && thickness > 0)              //input.endType != AXClipperLib.EndType.etClosedPolygon) {
            {
                // this is a wall
                if (resPaths != null && gener2D != null)
                {
                    sp.transformedFullyAndOffsetdButNotThickenedOutputPaths = AX.Generators.Generator2D.transformPaths(resPaths, gener2D.localMatrix);
                }

                sp.hasThickness = true;


                co.Clear();
                if (resPolytree != null)                                                                                                                     // closed block has happened
                {
                    co.AddPaths(AXGeometryTools.Utilities.cleanPaths(Clipper.PolyTreeToPaths(resPolytree), cleanPolygonPrecision), sp.joinType, sp.endType); //input.endType);
                }
                else if (resPaths != null)
                {
                    co.AddPaths(AXGeometryTools.Utilities.cleanPaths(resPaths, cleanPolygonPrecision), sp.joinType, sp.endType);                     //input.endType);
                }

                resPolytree = new AXClipperLib.PolyTree();
                co.Execute(ref resPolytree, (double)(thickness * AXGeometryTools.Utilities.IntPointPrecision));
            }
            else
            {
                sp.transformedFullyAndOffsetdButNotThickenedOutputPaths = null;
            }



            // 3. Update input data
            //Debug.Log(sp.parametricObject.Name  + "." + sp.Name + " here ["+hasOffset+"] " + (! sp.symmetry) + " " +  (! flipX)  + " " + (! hasOffset)  + " " +  (! hasThicken)  + " " +  (roundness == 0));


            // SIMPLE PASSTHRU?
            if (!sp.symmetry && !flipX && !hasOffset && !sp.hasThickness && roundness == 0)
            {
                // SIMPLE PASS THROUGH
                sp.polyTree = src.polyTree;
                sp.paths    = src.paths;
            }

            else
            {
                if (resPolytree == null)
                {
                    //sp.paths      = resPaths; //Generator2D.transformPaths(resPaths, gener2D.localMatrix);
                    //if (Clipper.Orientation(resPaths[0]) != srcIsCC)
                    //	AXGeometryTools.Utilities.reversePaths(ref resPaths);

                    sp.paths = AXGeometryTools.Utilities.cleanPaths(resPaths, cleanPolygonPrecision);
                }
                else
                {
                    //Generator2D.transformPolyTree(resPolytree, gener2D.localMatrix);

                    //if (resPolytree != null && resPolytree.Childs.Count > 0 &&  Clipper.Orientation(resPolytree.Childs[0].Contour) != srcIsCC)
                    //	AXGeometryTools.Utilities.reversePolyTree(resPolytree);


                    sp.polyTree = resPolytree;
                }
            }



            // REVERSE
            if (sp.reverse)
            {
                if (sp.polyTree != null)
                {
                    AXGeometryTools.Utilities.reversePolyTree(sp.polyTree);
                }
                else if (sp.paths != null && sp.paths.Count > 0)
                {
                    for (int i = 0; i < sp.paths.Count; i++)
                    {
                        sp.paths[i].Reverse();
                    }
                }
            }



//			if (sp.paths != null && sp.paths.Count > 0)
//			{
//				// SUBDIVISION
//				Debug.Log("sp.paths.Count="+sp.paths.Count);
//
//				for(int i=0; i<sp.paths.Count; i++)
//				{
//
//
//					Path path = sp.paths[i];
//					Path subdivPath = new Path();
//
//					for (int j=0; j<path.Count-1; j++)
//					{
//						subdivPath.Add(path[j]);
//						Vector2 v0 = new Vector2(path[j].X, path[j].Y);
//						Vector2 v1 = new Vector2(path[j+1].X, path[j+1].Y);
//
//						Debug.Log("["+i+"]["+j+"] " + Vector2.Distance(v0, v1)/10000);
//						 Vector2 newp = Vector2.Lerp(v0, v1, .5f);
//
//						subdivPath.Add(new IntPoint(newp.x, newp.y));
//					}
//					subdivPath.Add(path[path.Count-1]);
//
//
//					sp.paths[i] = subdivPath;
//
//					Debug.Log("------------");
//					AXGeometryTools.Utilities.printPath(sp.paths[i]);
//				}
//					// SUBDIVISION ---
//			}
//
        }
Example #7
0
        // This is used with rails since the Clipper Lib does not support
        // difference with the lines of the clip object removed.
        // In other words, to open a door in a closed polygon,
        // we use this to remove the edges that were originally on the clip object
        // leaving only the line segments of the subject that were not inside the clip shape.
        public Paths assembleRailPathsFromClippedSegments(AXClipperLib.PolyTree solutionRail)
        {
            // Take all the clipped segments and connect
            Paths clippedSegments = Clipper.OpenPathsFromPolyTree(solutionRail);

            //Debug.Log ("clipped segments " + clippedSegments.Count);
            //Archimatix.printPaths(clippedSegments);

            Dictionary <Path, AXSegment> axsegs = new Dictionary <Path, AXSegment>();

            foreach (Path p in clippedSegments)
            {
                axsegs.Add(p, new AXSegment(p));
            }

            int cc = 0;

            foreach (Path clipseg in clippedSegments)
            {
                //Debug.Log ("PASS["+cc+"] " + AXGeometryTools.Utilities.pathToString(clipseg));

                if (axsegs[clipseg].prev != null && axsegs[clipseg].next != null)
                {
                    //Debug.Log("Already done");
                    cc++;
                    continue;
                }
                int ccc = 0;
                foreach (Path compseg in clippedSegments)
                {
                    if (compseg == clipseg)
                    {
                        //Debug.Log("COMP["+cc+"]["+ccc+"] skip same");
                        ccc++;
                        continue;
                    }
                    //Debug.Log ("COMP["+cc+"]["+ccc+"]"+AXGeometryTools.Utilities.pathToString(clipseg)+ " with "+AXGeometryTools.Utilities.pathToString(compseg));

                    if (axsegs[clipseg].prev == null && axsegs[compseg].next == null)
                    {
                        if (AXSegment.pointsAreEqual(clipseg[0], compseg[1]))
                        {
                            axsegs[clipseg].prev = axsegs[compseg];
                            axsegs[compseg].next = axsegs[clipseg];
                            //Debug.Log ("prev");
                        }
                    }
                    if (axsegs[clipseg].prev == null && axsegs[compseg].prev == null)
                    {
                        if (AXSegment.pointsAreEqual(clipseg[0], compseg[0]))
                        {
                            compseg.Reverse();
                            axsegs[clipseg].prev = axsegs[compseg];
                            axsegs[compseg].next = axsegs[clipseg];
                        }
                    }
                    if (axsegs[clipseg].next == null && axsegs[compseg].prev == null)
                    {
                        if (AXSegment.pointsAreEqual(clipseg[1], compseg[0]))
                        {
                            axsegs[clipseg].next = axsegs[compseg];
                            axsegs[compseg].prev = axsegs[clipseg];
                        }
                    }
                    if (axsegs[clipseg].next == null && axsegs[compseg].next == null)
                    {
                        if (AXSegment.pointsAreEqual(clipseg[1], compseg[1]))
                        {
                            compseg.Reverse();
                            axsegs[clipseg].next = axsegs[compseg];
                            axsegs[compseg].prev = axsegs[clipseg];
                        }
                    }
                    ccc++;
                }
                cc++;
            }

            // now all segs should be linked.
            // go through each that has no prev and create new paths...
            Paths retPaths = new Paths();

            foreach (KeyValuePair <Path, AXSegment> item in axsegs)
            {
                Path path = item.Key;
                if (item.Value.prev == null)
                {                   // now crawl up the nexts adding pt[1]s
                    AXSegment next = item.Value;
                    while ((next = next.next) != null)
                    {
                        path.Add(next.path[1]);
                    }

                    retPaths.Add(path);
                }
            }

            return(retPaths);
        }
Example #8
0
        // GENERATE WINWALL
        public override GameObject generate(bool makeGameObjects, AXParametricObject initiator_po, bool renderToOutputParameter)
        {
            if (parametricObject == null || !parametricObject.isActive)
            {
                return(null);
            }


            //Debug.Log("PlanSweep::generate()");

            // RESULTING MESHES
            ax_meshes = new List <AXMesh>();


            preGenerate();



            // PLAN
            // The plan may have multiple paths. Each may generate a separate GO.

            if (P_Plan == null)
            {
                return(null);
            }


            planSrc_p  = getUpstreamSourceParameter(P_Plan);
            planSrc_po = (planSrc_p != null)                                                           ? planSrc_p.parametricObject    : null;

            if (planSrc_p == null || !planSrc_p.parametricObject.isActive)
            {
                return(null);
            }


            planIsClosed = (P_Plan.hasThickness || P_Plan.shapeState == ShapeState.Closed) ? true : false;


            P_Plan.polyTree = null;

            Paths planPaths = planSrc_p.getPaths();

            Path planPath = planPaths[0];

            Spline planSpline = new Spline(planPath, planIsClosed, P_Plan.breakGeom, P_Plan.breakNorm);



            Paths offsetPaths = Pather.wallOffsets(planSpline, .5f, .5f);

            Pather.printPaths(offsetPaths);


            // each path, step through and mak a rectangle
            // segment wide and height and then subtract windows.

            //Then make poly and add to combiner

            Path window = AXTurtle.Rectangle(1, 1, false);

            //window.Reverse();
            Pather.shiftPath(window, new IntPoint(10000, 5000));

            Debug.Log("==========");
            Pather.printPath(window);



            Pather rightPather = new Pather(offsetPaths[0]);

            int[] rightLengths = rightPather.segment_lengths;

            for (int i = 0; i < rightLengths.Length; i++)
            {
                Debug.Log(rightLengths[i]);

                int next_i = (i == rightLengths.Length - 1) ? 0 : i + 1;

                Path rect = AXTurtle.Rectangle(rightLengths[next_i] / 10000f, 3, false);



                Clipper c = new Clipper();
                c.AddPath(rect, PolyType.ptSubject, true);

                // fenestration
                c.AddPath(window, PolyType.ptClip, true);

                AXClipperLib.PolyTree polytree = new AXClipperLib.PolyTree();
                c.Execute(ClipType.ctDifference, polytree, PolyFillType.pftNonZero, PolyFillType.pftNonZero);

                Paths pathResult = Clipper.PolyTreeToPaths(polytree);


                Pather.printPaths(pathResult);

                Mesh mesh = AXPolygon.triangulate(polytree, new AXTexCoords());


                Matrix4x4 wallm = Matrix4x4.TRS(new Vector3(offsetPaths[0][i].X / 10000f, 0, offsetPaths[0][i].Y / 10000f), Quaternion.Euler(-90, planSpline.edgeRotations[i], 0), Vector3.one);

                ax_meshes.Add(new AXMesh(mesh, wallm));
            }

            parametricObject.finishMultiAXMeshAndOutput(ax_meshes, renderToOutputParameter);


            // FINISH BOUNDING

            setBoundaryFromAXMeshes(ax_meshes);


            if (makeGameObjects)
            {
                return(parametricObject.makeGameObjectsFromAXMeshes(ax_meshes));
            }


            return(null);
        }