private static IPolygon Clopening(IPolygon p, Box2 boundingBox, double offset)
        {
            if (p.IsEmpty)
            {
                return(Polygon.Empty);
            }

            double scale           = Math.Max(boundingBox.Width, boundingBox.Height);
            var    fixedPointRange = new Box2(boundingBox.MinCorner, new Vector2(scale, scale));

            var fixedP           = ConvertToFixedPoint(p, fixedPointRange);
            var fixedScaleOffset = offset * _fixedPointRange / scale;

            try
            {
                var offsetter = new ClipperOffset();
                offsetter.AddPaths(fixedP, JoinType.jtMiter, EndType.etClosedPolygon);

                var fixedIntermediate = new ClipperPolygon();
                offsetter.Execute(ref fixedIntermediate, fixedScaleOffset);

                offsetter.Clear();
                offsetter.AddPaths(fixedIntermediate, JoinType.jtMiter, EndType.etClosedPolygon);

                var fixedAnswer = new ClipperPolygon();
                offsetter.Execute(ref fixedAnswer, -fixedScaleOffset);

                return(ConvertToFloatingPoint(fixedAnswer, fixedPointRange));
            }
            catch (Exception e)
            {
                Console.WriteLine("EXCEPTION: {0}", e);
                return(p);
            }
        }
        private Paths GetOffsetSolution(Dictionary <float, Paths> roads)
        {
            foreach (var carRoadEntry in roads)
            {
                var offsetSolution = new Paths();
                _offset.AddPaths(carRoadEntry.Value, JoinType.jtMiter, EndType.etOpenSquare);
                _offset.Execute(ref offsetSolution, carRoadEntry.Key);
                _clipper.AddPaths(offsetSolution, PolyType.ptSubject, true);
                _offset.Clear();
            }
            var polySolution = new Paths();

            _clipper.Execute(ClipType.ctUnion, polySolution, PolyFillType.pftPositive, PolyFillType.pftPositive);
            _clipper.Clear();
            return(polySolution);
        }
Example #3
0
        public static List <List <Vector2> > Outline(List <Vector2> polygon, FillMode fillMode, bool closed, StrokeStyle strokeStyle, float strokeWidth, out PolyTree tree)
        {
            List <List <Vector2> > simplified = Clipper.SimplifyPolygon(polygon, fillMode.ToPolyFillType());

            Offsetter.Clear();
            Offsetter.MiterLimit = strokeStyle.MiterLimit;
            Offsetter.AddPaths(simplified, (JoinType)strokeStyle.LineJoin, closed ? EndType.etClosedLine : strokeStyle.CapStyle.ToEndType());

            tree = new PolyTree();
            Offsetter.Execute(ref tree, strokeWidth / 2);
            return(Clipper.ClosedPathsFromPolyTree(tree));
        }
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);
        }
        /// <summary>
        /// Simplifies an list INTPolygons using expand and shrink technique.
        /// </summary>
        /// <param name="polygons">The INTPolygons.</param>
        /// <param name="value">The value used for expand and shrink.</param>
        /// <returns>INTPolygons.</returns>
        public INTPolygons SimplifyINTPolygons(INTPolygons polygons, double value)
        {
            double        simplificationFactor = Math.Pow(10.0, this.PolygonalBooleanPrecision) * UnitConversion.Convert(value, Length_Unit_Types.FEET, UnitType);
            ClipperOffset clipperOffset        = new ClipperOffset();

            clipperOffset.AddPaths(polygons, ClipperLib.JoinType.jtMiter, EndType.etClosedPolygon);
            INTPolygons shrink = new INTPolygons();

            clipperOffset.Execute(ref shrink, -simplificationFactor);
            //expanding to return the polygons to their original position
            clipperOffset.Clear();
            clipperOffset.AddPaths(shrink, ClipperLib.JoinType.jtMiter, EndType.etClosedPolygon);
            INTPolygons expand = new INTPolygons();

            clipperOffset.Execute(ref expand, simplificationFactor);
            shrink        = null;
            clipperOffset = null;
            return(expand);
        }
Example #6
0
        internal void ExtendThePolygon(ref List <IntPoint> enterPoints, ref Vector2[] extendedPoints, float extraOffset)
        {
            double distance = (AgentRadius + extraOffset) * (float)_Accuracy;

            _ClipperOffset.Clear();
            _ExitExtendPoints.Clear();

            _ClipperOffset.AddPath(enterPoints, JoinType.jtMiter, EndType.etClosedPolygon);
            _ClipperOffset.Execute(ref _ExitExtendPoints, distance);

            if (_ExitExtendPoints[0].Count != extendedPoints.Length)
            {
                extendedPoints = new Vector2[_ExitExtendPoints[0].Count];
            }

            for (int i = 0; i < _ExitExtendPoints[0].Count; ++i)
            {
                extendedPoints[i] = ParseToVector2(_ExitExtendPoints[0][i]);
            }
        }
        /// <summary>
        /// Returns an array of barriers that is used for autonomous walking scenarios
        /// </summary>
        /// <param name="offsetValue">Human body size which is the distance that you want the agents from barriers</param>
        /// <returns>Expanded version of all barrier polygons including field naked edges and holes, visual barriers and physical barriers </returns>
        public BarrierPolygon[] ExpandAllBarrierPolygons(double offsetValue)
        {
            ClipperOffset clipperOffset = new ClipperOffset();

            //clipperOffset.AddPaths(this.FootPrintOfAllBarriers, JoinType.jtSquare, EndType.etClosedPolygon);
            clipperOffset.AddPaths(this.FootPrintPolygonsOfFieldWithVoids, JoinType.jtSquare, EndType.etClosedPolygon);
            INTPolygons plygns            = new INTPolygons();
            double      uniqueOffsetValue = -Math.Pow(10.0, this.PolygonalBooleanPrecision) * offsetValue;

            clipperOffset.Execute(ref plygns, uniqueOffsetValue);
            List <BarrierPolygon> brrs = new List <BarrierPolygon>();

            for (int i = 0; i < plygns.Count; i++)
            {
                BarrierPolygon brr = this.ConvertINTPolygonToBarrierPolygon(plygns[i]);
                if (brr.Length > 0)
                {
                    brrs.Add(brr);
                }
            }
            clipperOffset.Clear();
            plygns.Clear();
            return(brrs.ToArray());
        }
Example #8
0
        internal static List <SliceLine2D> ConvertPolyTreeWithOffsetToSliceLine2D(float sliceHeight, List <PolyTree> polytrees, float insideOffset, float outsideOffset)
        {
            //calc model points using polygon offset
            var result = new List <SliceLine2D>();

            if (sliceHeight != 10.65f)
            {
                return(result);
            }

            var decimalCorrectionFactor        = 10000f;
            var selectedPrinterProjectorVector = new Vector2(RenderEngine.PrintJob.SelectedPrinter.ProjectorResolutionX, RenderEngine.PrintJob.SelectedPrinter.ProjectorResolutionY);

            var clipperOffset = new ClipperOffset();
            var holes         = new List <PolyNode>();
            var outsides      = new List <PolyNode>();

            foreach (var polygon in polytrees)
            {
                foreach (var pointInPath in polygon._allPolys)
                {
                    if (pointInPath.Contour.Count > 2)
                    {
                        clipperOffset.Clear();
                        clipperOffset = new ClipperOffset();

                        var results = new PolyTree();
                        clipperOffset.AddPath(pointInPath.Contour, JoinType.jtMiter, EndType.etClosedPolygon);

                        if (!pointInPath.IsHole)
                        {
                            //detax -2
                            //abs -1
                            clipperOffset.Execute(ref results, outsideOffset * decimalCorrectionFactor);

                            foreach (var offsetPolygon in results.Childs)
                            {
                                outsides.Add(offsetPolygon);
                            }
                        }
                        else
                        {
                            //detax 2
                            //abs 1
                            clipperOffset.Execute(ref results, insideOffset * decimalCorrectionFactor);

                            foreach (var offsetPolygon in results.Childs)
                            {
                                holes.Add(offsetPolygon);
                            }
                        }
                    }
                }

                //prevent line crossing first union the holes (removes holes intersections)
                var unionHolesPolyTree = new PolyTree();
                if (holes.Count > 1)
                {
                    var clipper = new Clipper();
                    foreach (var hole in holes)
                    {
                        clipper.AddPath(hole.Contour, PolyType.ptSubject, true);
                    }


                    clipper.Execute(ClipType.ctUnion, unionHolesPolyTree, PolyFillType.pftNonZero, PolyFillType.pftNonZero);
                }
                else if (holes.Count == 1)
                {
                    unionHolesPolyTree.AddChild(holes[0]);
                }


                //prevent line crossing second union the outsides (removes outside intersections)
                var unionOutsidesPolyTree = new PolyTree();
                if (outsides.Count > 1)
                {
                    var clipper = new Clipper();
                    foreach (var outside in outsides)
                    {
                        clipper.AddPath(outside.Contour, PolyType.ptSubject, true);
                    }


                    clipper.Execute(ClipType.ctUnion, unionOutsidesPolyTree, PolyFillType.pftNonZero, PolyFillType.pftNonZero);
                }
                else if (outsides.Count == 1)
                {
                    unionOutsidesPolyTree.AddChild(outsides[0]);
                }

                //subtract holes from outsides
                var diffPolyTree        = new PolyTree();
                var diffPolyTreeClipper = new Clipper();
                foreach (var unionPolyNode in unionOutsidesPolyTree.Childs)
                {
                    diffPolyTreeClipper.AddPath(unionPolyNode.Contour, PolyType.ptSubject, true);
                }

                foreach (var unionPolyNode in unionHolesPolyTree.Childs)
                {
                    diffPolyTreeClipper.AddPath(unionPolyNode.Contour, PolyType.ptClip, true);
                }

                diffPolyTreeClipper.Execute(ClipType.ctDifference, diffPolyTree, PolyFillType.pftNonZero);

                //    var triangle3D = new Triangle();


                //            foreach (var offsetPolygon in results.Childs)
                //            {
                //                //change order to CCW
                //                var directionIsCW = Clipper.Orientation(offsetPolygon.Contour);
                //                if (directionIsCW)
                //                {
                //                    Clipper.ReversePaths(new List<List<IntPoint>>() { offsetPolygon.Contour });
                //                }

                //                //convert to 3d triangle and determine normal
                //                for (var contourIndex = 0; contourIndex < offsetPolygon.Contour.Count; contourIndex++)
                //                {
                //                    triangle3D.Vectors[0].Position = new Vector3(offsetPolygon.Contour[contourIndex].X, offsetPolygon.Contour[contourIndex].Y, 0);

                //                    if (contourIndex == offsetPolygon.Contour.Count - 1)
                //                    {
                //                        triangle3D.Vectors[1].Position = new Vector3(offsetPolygon.Contour[0].X, offsetPolygon.Contour[0].Y, 0);
                //                        triangle3D.Vectors[2].Position = new Vector3(offsetPolygon.Contour[0].X, offsetPolygon.Contour[0].Y, 1);
                //                    }
                //                    else
                //                    {
                //                        triangle3D.Vectors[1].Position = new Vector3(offsetPolygon.Contour[contourIndex + 1].X, offsetPolygon.Contour[contourIndex + 1].Y, 0);
                //                        triangle3D.Vectors[2].Position = new Vector3(offsetPolygon.Contour[contourIndex + 1].X, offsetPolygon.Contour[contourIndex + 1].Y, 1);
                //                    }

                //                    triangle3D.Vectors[0].Position /= decimalCorrectionFactor;
                //                    triangle3D.Vectors[1].Position /= decimalCorrectionFactor;
                //                    triangle3D.Vectors[2].Position /= decimalCorrectionFactor;

                //                    triangle3D.CalcNormal();

                //                    var triangleNormal = triangle3D.Normal;
                //                    if (!pointInPath.IsHole)
                //                    {
                //                        triangleNormal = triangleNormal * -1;
                //                    }


                //                    var line = new SliceLine2D();
                //                    line.Normal = triangleNormal;

                //                    if (contourIndex == offsetPolygon.Contour.Count - 1)
                //                    {
                //                        line.p1 = new SlicePoint2D() { X = triangle3D.Vectors[0].Position.X, Y = triangle3D.Vectors[0].Position.Y};
                //                        //line.p2 = new SlicePoint2D() { X = offsetPolygon.Contour[0].X / decimalCorrectionFactor, Y = offsetPolygon.Contour[0].Y / decimalCorrectionFactor };
                //                        //

                //                        line.p2 = new SlicePoint2D() { X = triangle3D.Vectors[1].Position.X, Y = triangle3D.Vectors[1].Position.Y };
                //                    }
                //                    else
                //                    {
                //                        line.p1 = new SlicePoint2D() { X = triangle3D.Vectors[0].Position.X, Y = triangle3D.Vectors[0].Position.Y};
                //                        line.p2 = new SlicePoint2D() { X = triangle3D.Vectors[1].Position.X, Y = triangle3D.Vectors[1].Position.Y};
                //                    }

                //                    result.Add(line);

                //                }
                //            }
                //        }
                //    }
            }

            return(result);
        }
Example #9
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 #10
0
 /// <summary>
 /// Clears all paths from the ClipperOffset object, allowing new paths to be assigned.
 /// </summary>
 public void Clear()
 {
     clipperOffset.Clear();
 }
        /// <summary>
        /// Gets the Isovist polygon.
        /// </summary>
        /// <param name="vantagePoint">The vantage point.</param>
        /// <param name="viewDepth">The view depth.</param>
        /// <param name="edges">The edges.</param>
        /// <returns>BarrierPolygons.</returns>
        public BarrierPolygon IsovistPolygon(UV vantagePoint, double viewDepth, HashSet <UVLine> edges)
        {
            /*first and expand and shrink operation is performed to merge the shadowing edges*/
            double expandShrinkFactor = Math.Pow(10.0, this.PolygonalBooleanPrecision) * UnitConversion.Convert(0.075, Length_Unit_Types.FEET, UnitType);
            //offsetting the excluded area of each edge
            INTPolygons   offsetedPolygons = new INTPolygons();
            ClipperOffset clipperOffset    = new ClipperOffset();

            foreach (UVLine edgeItem in edges)
            {
                clipperOffset.AddPath(this.excludedArea(vantagePoint, viewDepth + 1, edgeItem), ClipperLib.JoinType.jtMiter, EndType.etClosedPolygon);
                INTPolygons plygns = new INTPolygons();
                clipperOffset.Execute(ref plygns, expandShrinkFactor);
                offsetedPolygons.AddRange(plygns);
                clipperOffset.Clear();
            }
            //Unioning the expanded exclusions
            INTPolygons offsetUnioned = new INTPolygons();
            Clipper     c             = new Clipper();

            c.AddPaths(offsetedPolygons, PolyType.ptSubject, true);
            c.Execute(ClipType.ctUnion, offsetUnioned, PolyFillType.pftNonZero, PolyFillType.pftNonZero);
            //shrink the polygons to retain their original size
            INTPolygons results = new INTPolygons();

            clipperOffset.Clear();
            clipperOffset.AddPaths(offsetUnioned, JoinType.jtMiter, EndType.etClosedPolygon);
            clipperOffset.Execute(ref results, -expandShrinkFactor);
            clipperOffset.Clear();
            offsetUnioned.Clear();

            /*
             * What ever is a hole in the resulting mereged polygon is the visibility polygon
             * Now we classify the polygons based on being a hole or not
             */
            //filtering out the holes that do not include the center
            INTPolygons holesNOT             = new INTPolygons();
            INTPolygons holesIncludingCenter = new INTPolygons();
            IntPoint    iCenter = ConvertUVToIntPoint(vantagePoint);

            foreach (INTPolygon item in results)
            {
                if (!Clipper.Orientation(item))
                {
                    if (Clipper.PointInPolygon(iCenter, item) == 1)
                    {
                        holesIncludingCenter.Add(item);
                    }
                }
                else
                {
                    holesNOT.Add(item);
                }
            }
            if (holesIncludingCenter.Count == 0)
            {
                //there is no hole. The shadow polygones should clip the potential field of visibility (i.e. circle) by an subtraction operation
                INTPolygon circle = createCircle(vantagePoint, viewDepth);
                //subtraction
                c.Clear();
                c.AddPath(circle, PolyType.ptSubject, true);
                c.AddPaths(holesNOT, PolyType.ptClip, true);
                INTPolygons isovistPolygon = new INTPolygons();
                c.Execute(ClipType.ctDifference, isovistPolygon);
                //searching for a polygon that includes the center
                foreach (INTPolygon item in isovistPolygon)
                {
                    if (Clipper.PointInPolygon(iCenter, item) == 1)
                    {
                        BarrierPolygon isovist = this.ConvertINTPolygonToBarrierPolygon(item);
                        results              = null;
                        c                    = null;
                        clipperOffset        = null;
                        offsetedPolygons     = null;
                        circle               = null;
                        holesNOT             = null;
                        holesIncludingCenter = null;
                        isovistPolygon       = null;
                        return(isovist);
                    }
                }
                MessageBox.Show(string.Format("Isovist not found!\nNo hole detected\n{0} polygons can be isovist", isovistPolygon.Count.ToString()));
            }
            else if (holesIncludingCenter.Count == 1)
            {
                INTPolygons isovistPolygon = holesIncludingCenter;
                foreach (INTPolygon item in isovistPolygon)
                {
                    if (Clipper.PointInPolygon(iCenter, item) == 1)
                    {
                        item.Reverse();
                        BarrierPolygon isovist = this.ConvertINTPolygonToBarrierPolygon(item);
                        results              = null;
                        c                    = null;
                        clipperOffset        = null;
                        offsetedPolygons     = null;
                        holesNOT             = null;
                        holesIncludingCenter = null;
                        isovistPolygon       = null;
                        return(isovist);
                    }
                }
                MessageBox.Show(string.Format("Isovist not found!\nOne hole detected\n{0} polygons can be isovist", isovistPolygon.Count.ToString()));
            }
            else if (holesIncludingCenter.Count > 1)
            {
                MessageBox.Show("Isovist not found!\nMore than one hole found that can include the vantage point");
            }
            return(null);
        }
Example #12
0
        public override void Calculate()
        {
            ResultPaths = new List <Polyline>();

            if (Stock == null || Stock.Count < 1 || DriveGeometry == null || DriveGeometry.Count < 1)
            {
                throw new Exception("Stock or drive geometry not set!");
            }

            BoundingBox bb = Stock[0].GetBoundingBox(Workplane);

            foreach (Mesh m in Stock)
            {
                bb = BoundingBox.Union(bb, m.GetBoundingBox(Workplane));
            }

            if (bb.IsDegenerate(0.1) > 0)
            {
                throw new Exception("Bounding Box is degenerate.");// return;
            }
            Point3d top    = bb.Center; top.Z = bb.Corner(false, false, false).Z;
            Point3d bottom = bb.Center; bottom.Z = bb.Corner(true, true, true).Z;

            double TotalDepth = top.DistanceTo(bottom);

            int     N            = (int)(Math.Ceiling(Math.Min(MaxDepth, TotalDepth) / Tool.StepDown));
            Plane   CuttingPlane = new Plane(Workplane);
            Point3d top_xform    = new Point3d(top);

            top_xform.Transform(Transform.PlaneToPlane(Plane.WorldXY, Workplane));
            CuttingPlane.Origin = top_xform;

            Tuple <CPaths, CPaths, CPaths> Polygons;

            Polygons = GeneratePolygons(CuttingPlane);

            CPaths Shadow = new CPaths(Polygons.Item1);
            double Area   = PathsArea(Shadow);

            for (int i = 0; i <= N; ++i)
            {
                // for each layer
                CuttingPlane.Origin = CuttingPlane.Origin - Workplane.ZAxis * Tool.StepDown;

                Polygons = GeneratePolygons(CuttingPlane, Shadow);
                if (Polygons == null)
                {
                    throw new Exception("Failed to generate polygons!");
                }

                double AreaNew = PathsArea(Polygons.Item1);
                if (AreaNew > Area)
                {
                    Shadow = new CPaths(Polygons.Item1);
                    Area   = AreaNew;
                }

                ClipperOffset offset = new ClipperOffset(0.25, 0.25);
                offset.AddPaths(Polygons.Item3, JoinType.jtMiter, EndType.etClosedPolygon);

                PolyTree tree = new PolyTree();
                offset.Execute(ref tree, -(Tool.Diameter / 2 + RestHorizontal) / Tolerance);

                CPaths WorkingPaths = new CPaths();

                List <Polyline> Output = new List <Polyline>();

                foreach (PolyNode pn in tree.Iterate())
                {
                    if (pn.Contour.Count > 0)
                    {
                        Output.Add(pn.Contour.ToPolyline(CuttingPlane, Tolerance, true));
                        WorkingPaths.Add(pn.Contour);
                    }
                }

                int counter = 0;
                do
                {
                    offset.Clear();
                    offset.AddPaths(WorkingPaths, JoinType.jtMiter, EndType.etClosedPolygon);
                    offset.Execute(ref tree, -Tool.StepOver / Tolerance);

                    WorkingPaths = new List <List <IntPoint> >();
                    foreach (PolyNode pn in tree.Iterate())
                    {
                        if (pn.Contour.Count > 0)
                        {
                            Output.Add(pn.Contour.ToPolyline(CuttingPlane, Tolerance, true));
                            WorkingPaths.Add(pn.Contour);
                        }
                    }
                    counter++;
                }while (tree.Total > 0 && counter < LOOP_LIMIT);

                ResultPaths.AddRange(Output);
            }

            ShadowPolylines = new List <Polyline>();
            foreach (CPath p in Shadow)
            {
                ShadowPolylines.Add(p.ToPolyline(CuttingPlane, Tolerance, true));
            }
        }
        Polygon OffsetPolygon(float offset, bool simplify, bool rounded)
        {
            // Calculate Polygon-Clipper scale.
            float maximum      = Mathf.Max(bounds.width, bounds.height) + offset * 2.0f + offset;
            float maximumScale = (float)Int32.MaxValue / maximum;
            float scale        = Mathf.Min(clipperScale, maximumScale);


            // Convert to Clipper.
            Paths paths = new Paths();

            {
                Path path = new Path();
                EnumeratePoints((Vector2 eachPoint) =>
                {
                    path.Add(new IntPoint(eachPoint.x * scale, eachPoint.y * scale));
                });
                paths.Add(path);
            }
            foreach (Polygon eachPolygon in polygons)
            {
                Path path = new Path();
                eachPolygon.EnumeratePoints((Vector2 eachPoint) =>
                {
                    path.Add(new IntPoint(eachPoint.x * scale, eachPoint.y * scale));
                });
                paths.Add(path);
            }

            // Mode.
            JoinType joinType = (rounded) ? JoinType.jtRound : JoinType.jtMiter;

            // Clipper offset.
            Paths         offsetPaths   = new Paths();
            ClipperOffset clipperOffset = new ClipperOffset();

            if (rounded)
            {
                clipperOffset.ArcTolerance = 0.25 * clipperArcTolerance;
            }                                                                                     // "The default ArcTolerance is 0.25 units." from http://www.angusj.com/delphi/clipper/documentation/Docs/Units/ClipperLib/Classes/ClipperOffset/Properties/ArcTolerance.htm
            clipperOffset.AddPaths(paths, joinType, EndType.etClosedPolygon);


            clipperOffset.Execute(ref offsetPaths, (double)offset * scale);
            clipperOffset.Clear();
            //Clipper.CleanPolygon( paths [ 0 ] );

            // Remove self intersections (if requested).
            if (simplify)
            {
                offsetPaths = Clipper.SimplifyPolygons(offsetPaths);
            }


            // Convert from Clipper.
            Polygon offsetPolygon = null;

            for (int index = 0; index < offsetPaths.Count; index++)
            {
                Path    eachSolutionPath    = offsetPaths[index];
                Polygon eachSolutionPolygon = PolygonFromClipperPath(eachSolutionPath, scale);

                if (index == 0)
                {
                    offsetPolygon = Polygon.PolygonWithPoints(eachSolutionPolygon.points);                     // Copy
                }
                else
                {
                    offsetPolygon.AddPolygon(eachSolutionPolygon);
                }
            }

            // Back to Polygon.
            return(offsetPolygon);
        }