コード例 #1
0
        public static Polygons GetCorrectedWinding(this Polygons polygonsToFix)
        {
            polygonsToFix = Clipper.CleanPolygons(polygonsToFix);
            var     boundsPolygon = new Polygon();
            IntRect bounds        = Clipper.GetBounds(polygonsToFix);

            bounds.minX -= 10;
            bounds.minY -= 10;
            bounds.maxY += 10;
            bounds.maxX += 10;

            boundsPolygon.Add(new IntPoint(bounds.minX, bounds.minY));
            boundsPolygon.Add(new IntPoint(bounds.maxX, bounds.minY));
            boundsPolygon.Add(new IntPoint(bounds.maxX, bounds.maxY));
            boundsPolygon.Add(new IntPoint(bounds.minX, bounds.maxY));

            var clipper = new Clipper();

            clipper.AddPaths(polygonsToFix, PolyType.ptSubject, true);
            clipper.AddPath(boundsPolygon, PolyType.ptClip, true);

            var intersectionResult = new PolyTree();

            clipper.Execute(ClipType.ctIntersection, intersectionResult);

            Polygons outputPolygons = Clipper.ClosedPathsFromPolyTree(intersectionResult);

            return(outputPolygons);
        }
コード例 #2
0
ファイル: PathFinder.cs プロジェクト: ucswift/MatterSlice
        private Polygons FixWinding(Polygons polygonsToPathAround)
        {
            polygonsToPathAround = Clipper.CleanPolygons(polygonsToPathAround);
            Polygon boundsPolygon = new Polygon();
            IntRect bounds        = Clipper.GetBounds(polygonsToPathAround);

            bounds.minX -= 10;
            bounds.maxY += 10;
            bounds.maxX += 10;
            bounds.minY -= 10;

            boundsPolygon.Add(new IntPoint(bounds.minX, bounds.minY));
            boundsPolygon.Add(new IntPoint(bounds.maxX, bounds.minY));
            boundsPolygon.Add(new IntPoint(bounds.maxX, bounds.maxY));
            boundsPolygon.Add(new IntPoint(bounds.minX, bounds.maxY));

            Clipper clipper = new Clipper();

            clipper.AddPaths(polygonsToPathAround, PolyType.ptSubject, true);
            clipper.AddPath(boundsPolygon, PolyType.ptClip, true);

            PolyTree intersectionResult = new PolyTree();

            clipper.Execute(ClipType.ctIntersection, intersectionResult);

            Polygons outputPolygons = Clipper.ClosedPathsFromPolyTree(intersectionResult);

            return(outputPolygons);
        }
コード例 #3
0
        private Polygons FixWinding(Polygons polygonsToPathAround)
        {
            polygonsToPathAround = Clipper.CleanPolygons(polygonsToPathAround);
            Polygon boundsPolygon = new Polygon();
            IntRect bounds        = Clipper.GetBounds(polygonsToPathAround);

            bounds.left   -= 10;
            bounds.bottom += 10;
            bounds.right  += 10;
            bounds.top    -= 10;

            boundsPolygon.Add(new IntPoint(bounds.left, bounds.top));
            boundsPolygon.Add(new IntPoint(bounds.right, bounds.top));
            boundsPolygon.Add(new IntPoint(bounds.right, bounds.bottom));
            boundsPolygon.Add(new IntPoint(bounds.left, bounds.bottom));

            Clipper clipper = new Clipper();

            clipper.AddPaths(polygonsToPathAround, PolyType.ptSubject, true);
            clipper.AddPath(boundsPolygon, PolyType.ptClip, true);

            PolyTree intersectionResult = new PolyTree();

            clipper.Execute(ClipType.ctIntersection, intersectionResult);

            Polygons outputPolygons = Clipper.ClosedPathsFromPolyTree(intersectionResult);

            Clipper.ReversePaths(outputPolygons);

            return(outputPolygons);
        }
コード例 #4
0
        //------------------------------------------------------------------------------

        public void Execute(ref List <List <IntPoint> > solution, double delta)
        {
            solution.Clear();
            FixOrientations();
            DoOffset(delta);
            //now clean up 'corners' ...
            Clipper clpr = new Clipper();

            clpr.AddPaths(m_destPolys, PolyType.ptSubject, true);
            if (delta > 0)
            {
                clpr.Execute(ClipType.ctUnion, solution,
                             PolyFillType.pftPositive, PolyFillType.pftPositive);
            }
            else
            {
                IntRect         r     = Clipper.GetBounds(m_destPolys);
                List <IntPoint> outer = new List <IntPoint>(4);

                outer.Add(new IntPoint(r.left - 10, r.bottom + 10));
                outer.Add(new IntPoint(r.right + 10, r.bottom + 10));
                outer.Add(new IntPoint(r.right + 10, r.top - 10));
                outer.Add(new IntPoint(r.left - 10, r.top - 10));

                clpr.AddPath(outer, PolyType.ptSubject, true);
                clpr.ReverseSolution = true;
                clpr.Execute(ClipType.ctUnion, solution, PolyFillType.pftNegative, PolyFillType.pftNegative);
                if (solution.Count > 0)
                {
                    solution.RemoveAt(0);
                }
            }
        }
コード例 #5
0
        public static Polygons GetCorrectedWinding(this Polygons polygonsToFix)
        {
            polygonsToFix = Clipper.CleanPolygons(polygonsToFix);
            Polygon boundsPolygon = new Polygon();
            IntRect bounds        = Clipper.GetBounds(polygonsToFix);

            bounds.left   -= 10;
            bounds.bottom += 10;
            bounds.right  += 10;
            bounds.top    -= 10;

            boundsPolygon.Add(new IntPoint(bounds.left, bounds.top));
            boundsPolygon.Add(new IntPoint(bounds.right, bounds.top));
            boundsPolygon.Add(new IntPoint(bounds.right, bounds.bottom));
            boundsPolygon.Add(new IntPoint(bounds.left, bounds.bottom));

            Clipper clipper = new Clipper();

            clipper.AddPaths(polygonsToFix, PolyType.ptSubject, true);
            clipper.AddPath(boundsPolygon, PolyType.ptClip, true);

            PolyTree intersectionResult = new PolyTree();

            clipper.Execute(ClipType.ctIntersection, intersectionResult);

            Polygons outputPolygons = Clipper.ClosedPathsFromPolyTree(intersectionResult);

            return(outputPolygons);
        }
コード例 #6
0
            private static void CleanUpSolution(Polygons solution, double delta)
            {
                Clipper clpr = new Clipper();

                clpr.AddPolygons(solution, PolyType.Subject);
                if (delta > 0)
                {
                    clpr.Execute(ClipType.Union, solution, PolyFillType.Positive, PolyFillType.Positive);
                }
                else
                {
                    RectangleL r     = clpr.GetBounds();
                    Polygon    outer = new Polygon(4);

                    outer.Add(new Vector2(r.left - 10, r.bottom + 10));
                    outer.Add(new Vector2(r.right + 10, r.bottom + 10));
                    outer.Add(new Vector2(r.right + 10, r.top - 10));
                    outer.Add(new Vector2(r.left - 10, r.top - 10));

                    clpr.AddPolygon(outer, PolyType.Subject);
                    clpr.Execute(ClipType.Union, solution, PolyFillType.Negative, PolyFillType.Negative);
                    if (solution.Count > 0)
                    {
                        solution.RemoveAt(0);
                        for (int i = 0; i < solution.Count; i++)
                        {
                            solution[i].Reverse();
                        }
                    }
                }
            }
コード例 #7
0
        public static void SaveToSvg(this Polygons polygons, string filename)
        {
            double  scaleDenominator = 150;
            IntRect bounds           = Clipper.GetBounds(polygons);
            long    temp             = bounds.maxY;

            bounds.maxY = bounds.minY;
            bounds.minY = temp;
            IntPoint     size   = new IntPoint(bounds.maxX - bounds.minX, bounds.maxY - bounds.minY);
            double       scale  = Max(size.X, size.Y) / scaleDenominator;
            StreamWriter stream = new StreamWriter(filename);

            stream.Write("<!DOCTYPE html><html><body>\n");
            stream.Write("<svg xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\" style='width:{0}px;height:{1}px'>\n".FormatWith((int)(size.X / scale), (int)(size.Y / scale)));
            stream.Write("<marker id='MidMarker' viewBox='0 0 10 10' refX='5' refY='5' markerUnits='strokeWidth' markerWidth='10' markerHeight='10' stroke='lightblue' stroke-width='2' fill='none' orient='auto'>");
            stream.Write("<path d='M 0 0 L 10 5 M 0 10 L 10 5'/>");
            stream.Write("</marker>");
            stream.Write("<g fill-rule='evenodd' style=\"fill: gray; stroke:black;stroke-width:1\">\n");
            stream.Write("<path marker-mid='url(#MidMarker)' d=\"");
            for (int polygonIndex = 0; polygonIndex < polygons.Count; polygonIndex++)
            {
                Polygon polygon = polygons[polygonIndex];
                for (int intPointIndex = 0; intPointIndex < polygon.Count; intPointIndex++)
                {
                    if (intPointIndex == 0)
                    {
                        stream.Write("M");
                    }
                    else
                    {
                        stream.Write("L");
                    }
                    stream.Write("{0},{1} ", (double)(polygon[intPointIndex].X - bounds.minX) / scale, (double)(polygon[intPointIndex].Y - bounds.maxY) / scale);
                }
                stream.Write("Z\n");
            }
            stream.Write("\"/>");
            stream.Write("</g>\n");
            for (int openPolygonIndex = 0; openPolygonIndex < polygons.Count; openPolygonIndex++)
            {
                Polygon openPolygon = polygons[openPolygonIndex];
                if (openPolygon.Count < 1)
                {
                    continue;
                }
                stream.Write("<polyline marker-mid='url(#MidMarker)' points=\"");
                for (int n = 0; n < openPolygon.Count; n++)
                {
                    stream.Write("{0},{1} ", (double)(openPolygon[n].X - bounds.minX) / scale, (double)(openPolygon[n].Y - bounds.maxY) / scale);
                }
                stream.Write("\" style=\"fill: none; stroke:red;stroke-width:1\" />\n");
            }
            stream.Write("</svg>\n");

            stream.Write("</body></html>");
            stream.Close();
        }
コード例 #8
0
        public static IntPoint getCenter(Paths paths)
        {
            if (paths == null)
            {
                return(new IntPoint());
            }


            IntRect ir = Clipper.GetBounds(paths);

            return(new IntPoint((ir.left + (ir.right - ir.left) / 2), (ir.bottom + (ir.top - ir.bottom) / 2)));
        }
コード例 #9
0
        //------------------------------------------------------------------------------

        public void Execute(ref PolyTree solution, double delta)
        {
            solution.Clear();
            FixOrientations();
            DoOffset(delta);

            //now clean up 'corners' ...
            Clipper clpr = new Clipper();

            clpr.AddPaths(m_destPolys, PolyType.ptSubject, true);
            if (delta > 0)
            {
                clpr.Execute(ClipType.ctUnion, solution,
                             PolyFillType.pftPositive, PolyFillType.pftPositive);
            }
            else
            {
                IntRect         r     = Clipper.GetBounds(m_destPolys);
                List <IntPoint> outer = new List <IntPoint>(4);

                outer.Add(new IntPoint(r.left - 10, r.bottom + 10));
                outer.Add(new IntPoint(r.right + 10, r.bottom + 10));
                outer.Add(new IntPoint(r.right + 10, r.top - 10));
                outer.Add(new IntPoint(r.left - 10, r.top - 10));

                clpr.AddPath(outer, PolyType.ptSubject, true);
                clpr.ReverseSolution = true;
                clpr.Execute(ClipType.ctUnion, solution, PolyFillType.pftNegative, PolyFillType.pftNegative);
                //remove the outer PolyNode rectangle ...
                if (solution.ChildCount == 1 && solution.Childs[0].ChildCount > 0)
                {
                    PolyNode outerNode = solution.Childs[0];
                    solution.Childs.Capacity    = outerNode.ChildCount;
                    solution.Childs[0]          = outerNode.Childs[0];
                    solution.Childs[0].m_Parent = solution;
                    for (int i = 1; i < outerNode.ChildCount; i++)
                    {
                        solution.AddChild(outerNode.Childs[i]);
                    }
                }
                else
                {
                    solution.Clear();
                }
            }
        }
コード例 #10
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);
        }
コード例 #11
0
        public static long[] getShifterToPathsCenter(Paths paths)
        {
            long[] shifter = new long[3];

            if (paths == null)
            {
                return(shifter);
            }


            IntRect ir = Clipper.GetBounds(paths);

            shifter[0] = ir.left + (ir.right - ir.left) / 2;
            shifter[1] = ir.bottom + (ir.top - ir.bottom) / 2;

            shifter[2] = Math.Max((ir.right - ir.left), (ir.top - ir.bottom));

            return(shifter);
        }
コード例 #12
0
		public override void calculateBounds()
		{
			AXParameter SelectedOutput = S_InputShape.getSelectedOutputParameter();

			Paths paths = (SelectedOutput != null) ? SelectedOutput.getPaths() : null;

			//Debug.Log(parametricObject.Name + ": " + P_Output);

			if (paths == null)
				return;

			IntRect cb = Clipper.GetBounds(SelectedOutput.getPaths());

			Vector3 size = new Vector3(cb.right-cb.left, cb.bottom-cb.top, 0);///Archimatix.IntPointPrecision;
			Vector3 center = new Vector3(cb.left+size.x/2, cb.top+size.y/2, 0);

	
			parametricObject.bounds = new Bounds( (center/AXGeometryTools.Utilities.IntPointPrecision-new Vector3(transX, transY, 0)), size/AXGeometryTools.Utilities.IntPointPrecision);

		}
コード例 #13
0
        public static Rect getClipperBounds(Paths paths)
        {
            if (paths == null)
            {
                return(new Rect());
            }

            /*
             * Debug.Log ("get bounds from these paths");
             * foreach(Path p in paths)
             *      Debug.Log (Archimatix.pathToString(p));
             */
            IntRect ir = Clipper.GetBounds(paths);

            float x1 = ((float)ir.left) / IntPointPrecision;
            float y1 = ((float)ir.top) / IntPointPrecision;
            float x2 = ((float)ir.right) / IntPointPrecision;
            float y2 = ((float)ir.bottom) / IntPointPrecision;

            return(new Rect(x1, y1, x2 - x1, y2 - y1));
        }
コード例 #14
0
ファイル: Slice.cs プロジェクト: ThenTech/CF-Slicer
        public void AddAdhesion(AdhesionType type, double diameter, bool add_to_polies = true /*else to fill*/, int distance = 12, int miter_dist = 5)
        {
            if (type == AdhesionType.NONE)
            {
                return;
            }

            Polygon2D outside_poly = null;

            if (add_to_polies)
            {
                // Select largest outer poly
                outside_poly = this.Polygons.Where(p => p.Hierarchy == 0).First();
            }
            else
            {
                // Get bounds instead of poly, because order and contents are not sure for fill...
                var rect = Clipper.GetBounds(this.FillPolygons.Select(p => p.IntPoints).ToList());
                outside_poly = new Polygon2D(new Path()
                {
                    new IntPoint(rect.top, rect.left),
                    new IntPoint(rect.top, rect.right),
                    new IntPoint(rect.bottom, rect.right),
                    new IntPoint(rect.bottom, rect.left),
                });
            }

            if (outside_poly == null)
            {
                return;
            }

            List <Polygon2D> adhesion_polies = null;

            switch (type)
            {
            case AdhesionType.SKIRT:
            {
                // Separated rings around ground poly
                const int rings = 2;
                adhesion_polies = new List <Polygon2D>(rings + this.Polygons.Count);

                for (int offsetted_line = 0; offsetted_line < rings; offsetted_line++)
                {
                    var offset = diameter * (distance - offsetted_line);
                    adhesion_polies.AddRange(outside_poly.Offset(offset, miter_dist)
                                             .Where(p => p.FilterShorts()));
                }

                break;
            }

            case AdhesionType.BRIM:
            {
                // Number of offsets going to ground poly, from distance away
                adhesion_polies = new List <Polygon2D>(distance + this.Polygons.Count);

                for (int offsetted_line = 0; offsetted_line < distance; offsetted_line++)
                {
                    var offset = diameter * (distance - offsetted_line);
                    adhesion_polies.AddRange(outside_poly.Offset(offset, miter_dist)
                                             .Where(p => p.FilterShorts()));
                }

                break;
            }
            }

            // Mark flags for proper drawing of colour, useless otherwise
            adhesion_polies.ForEach(p =>
            {
                p.IsInfill   = true;
                p.IsSupport  = true;
                p.IsShell    = true;
                p.IsSurface  = true;
                p.IsAdhesion = true;
            });

            adhesion_polies.AddRange(this.Polygons);
            this.Polygons = adhesion_polies;
        }
コード例 #15
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 ---
//			}
//
        }
コード例 #16
0
        public void carveTerrain()
        {
            Terrain terrain = parametricObject.terrain;

            if (terrain != null)
            {
                if (parametricObject.heightsOrig == null)
                {
                    memorizeTerrain();
                }

                // BOUNDING_SHAPE


                if (P_Plan != null && P_Plan.DependsOn != null)
                {
                    if (planSrc_po != null)
                    {
                        AXShape.thickenAndOffset(ref P_Plan, planSrc_p);
                        // now boundin_p has offset and thickened polytree or paths.
                    }
                }


                int hmWidth  = terrain.terrainData.heightmapWidth;
                int hmHeight = terrain.terrainData.heightmapHeight;



                Paths subjPaths = P_Plan.getTransformedSubjPaths();
                Paths holePaths = P_Plan.getTransformedHolePaths();

                //Pather.printPaths(subjPaths);

                if (subjPaths == null)
                {
                    return;
                }

                IntRect bounds = Clipper.GetBounds(subjPaths);

//				if (prevBounds.right > 0)
//				{
//					bounds.left     = ( prevBounds.left < bounds.left )         ? prevBounds.left   : bounds.left;
//					bounds.right    = ( prevBounds.right > bounds.right )       ? prevBounds.right  : bounds.right;
//
//
//					bounds.top      = ( prevBounds.top < bounds.top )           ? prevBounds.top : bounds.top;
//					bounds.bottom   = ( prevBounds.bottom > bounds.bottom )     ? prevBounds.bottom     : bounds.bottom;
//				}

                float percentHgt = height / terrain.terrainData.size.y;

                //Debug.Log(bounds.left +"->"+bounds.right+" :: " + bounds.top+ "->"+bounds.bottom);
                int padding = 50000;

                bounds.left   -= padding;
                bounds.right  += padding;
                bounds.top    -= padding;
                bounds.bottom += padding;

                int from_i = (int)((bounds.left / AXGeometryTools.Utilities.IntPointPrecision) * hmWidth / terrain.terrainData.size.x);
                int to_i   = (int)((bounds.right / AXGeometryTools.Utilities.IntPointPrecision) * hmWidth / terrain.terrainData.size.x);

                int from_j = (int)((bounds.top / AXGeometryTools.Utilities.IntPointPrecision) * hmHeight / terrain.terrainData.size.z);
                int to_j   = (int)((bounds.bottom / AXGeometryTools.Utilities.IntPointPrecision) * hmHeight / terrain.terrainData.size.z);

                //Debug.Log(from_i +"->"+to_i+" :: " + from_j+ "->"+to_j);

                from_i = Mathf.Max(0, from_i);
                to_i   = Mathf.Min(to_i, hmWidth);

                from_j = Mathf.Max(0, from_j);
                to_j   = Mathf.Min(to_j, hmHeight);

                //Debug.Log(from_i +"->"+to_i+" :: " + from_j+ "->"+to_j);

                // patch to be redrawn
                float[,] heights = new float[(to_j - from_j), (to_i - from_i)];

                //Debug.Log(heights.GetLength(0) +" -- " + heights.GetLength(1));
                if (from_i < to_i && from_j < to_j)
                {
                    // we set each sample of the terrain in the size to the desired height
                    for (int i = from_i; i < to_i; i++)
                    {
                        for (int j = from_j; j < to_j; j++)
                        {
                            // GET i, j in realworld coords
                            float x = terrain.terrainData.size.x * i / hmWidth;
                            float y = terrain.terrainData.size.z * j / hmHeight;

                            //Debug.Log("[" + i + ", " + j + "] :: " + x +", " + y);
                            if (isInside(x, y, subjPaths, holePaths))
                            {
                                heights [j - from_j, i - from_i] = percentHgt;
                            }
                            else
                            {
                                heights [j - from_j, i - from_i] = parametricObject.heightsOrig [j, i];
                            }
                        }
                    }
                    // set the new height
                    terrain.terrainData.SetHeights(from_i, from_j, heights);
                }

                //prevBounds = bounds;
            }
        }