Пример #1
0
        public static double UnoccupiedBoundaryArea(Shape boundaryShape, List <Shape> shapes, Form1 form)
        {
            Paths boundarySolution       = new Paths(1);
            Paths boundaryPaths          = new Paths(1);
            Paths shapesWithinBoundaries = new Paths(1);

            foreach (var shape in shapes)
            {
                shapesWithinBoundaries.Add(new Path(shape.GetDrawingCoordinates()));
            }

            boundaryPaths.Add(new Path(boundaryShape.GetDrawingCoordinates()));
            Utils.DrawPolygons(boundaryPaths, Color.Green, false, form);

            Clipper c = new Clipper();

            c.AddPolygons(boundaryPaths, PolyType.ptSubject);
            c.AddPolygons(shapesWithinBoundaries, PolyType.ptClip);
            c.Execute(ClipType.ctIntersection, boundarySolution,
                      PolyFillType.pftEvenOdd, PolyFillType.pftEvenOdd);

            Utils.DrawPolygons(boundarySolution, Color.Orange, true, form);
            var totalShapeArea       = Utils.PolygonSignedArea(shapesWithinBoundaries);
            var boundaryIntersection = Utils.PolygonSignedArea(boundarySolution);

            Logger.SimpleDebug("Area of shapes within boundary is " + boundaryIntersection + " out of " + totalShapeArea);
            return((totalShapeArea - boundaryIntersection) * Config.IntersectionErrorModifier);
        }
Пример #2
0
        public static List <List <IntPoint> > GetPolySolution(List <IntPoint> poly1, List <IntPoint> poly2, ClipType cType)
        {
            Clipper c = new Clipper();

            c.AddPolygons(new List <List <IntPoint> >()
            {
                poly1
            }, PolyType.ptSubject);
            c.AddPolygons(new List <List <IntPoint> >()
            {
                poly2
            }, PolyType.ptClip);
            var solution = new List <List <IntPoint> >();

            //ExecuteOperation();

            try
            {
                //Thread t =
                //new Thread(() =>
                //    {
                c.Execute(cType, solution, PolyFillType.pftPositive, PolyFillType.pftPositive);
                //    });
                //t.Start();
                //t.Join(1000);
                ////t.Abort();
            }
            catch (Exception e1)
            {
                //throw;
            }
            return(solution);
        }
Пример #3
0
        public static double SingleUnoccupiedBoundaryArea(Shape boundaryShape, Shape shape)
        {
            if (boundaryShape == null)
            {
                return(0.0);
            }
            Paths boundarySolution       = new Paths(1);
            Paths boundaryPaths          = new Paths(1);
            Paths shapesWithinBoundaries = new Paths(1);

            shapesWithinBoundaries.Add(new Path(shape.GetDrawingCoordinates()));

            boundaryPaths.Add(new Path(boundaryShape.GetDrawingCoordinates()));

            Clipper c = new Clipper();

            c.AddPolygons(boundaryPaths, PolyType.ptSubject);
            c.AddPolygons(shapesWithinBoundaries, PolyType.ptClip);
            c.Execute(ClipType.ctDifference, boundarySolution,
                      PolyFillType.pftEvenOdd, PolyFillType.pftEvenOdd);

            var totalShapeArea       = Utils.PolygonSignedArea(shapesWithinBoundaries);
            var boundaryIntersection = Utils.PolygonSignedArea(boundarySolution);

            Logger.SimpleDebug("Area of shapes within boundary is " + boundaryIntersection + " out of " + totalShapeArea);
            return((totalShapeArea - boundaryIntersection) * Config.IntersectionErrorModifier);
        }
Пример #4
0
        public static double SingleShapeIntersection(Shape shape, Shape externalShape)
        {
            if (externalShape == null)
            {
                return(0.0);
            }
            Paths subject        = new Paths(1);
            Paths collidingClips = new Paths(1);

            // Add shape to subject
            subject = new Paths(1);
            subject.Add(new Path(shape.GetDrawingCoordinates()));

            // Find all shapes with collision distance and add to temporary clib
            collidingClips = new Paths(2);
            collidingClips.Add(new Path(externalShape.GetDrawingCoordinates()));

            Paths solution = new Paths(1);

            Clipper c = new Clipper();

            c.AddPolygons(subject, PolyType.ptSubject);
            c.AddPolygons(collidingClips, PolyType.ptClip);
            c.Execute(ClipType.ctIntersection, solution,
                      PolyFillType.pftEvenOdd, PolyFillType.pftEvenOdd);

            var intersectionError = Utils.PolygonSignedArea(solution);

            Logger.SimpleDebug("Area of intersection for shape " + shape.Index + " is " + intersectionError);
            return(intersectionError * Config.IntersectionErrorModifier);
        }
Пример #5
0
            /// <summary>
            /// Calculate render and physics data.
            /// </summary>
            public void Calculate(GameWorld world)
            {
                var clipper = new Clipper();
                List <List <IntPoint> > output = new List <List <IntPoint> >();

                // Calculate difference
                clipper.AddPolygons(Polygons, PolyType.ptSubject);
                clipper.AddPolygons(Cavities, PolyType.ptClip);
                clipper.AddPolygons(Damage, PolyType.ptClip);
                clipper.Execute(ClipType.ctDifference, output, PolyFillType.pftNonZero, PolyFillType.pftNonZero);

                Hulls.Clear();
                output.ForEach(o =>
                {
                    Vector2[] points = new Vector2[o.Count];
                    int index        = 0;
                    o.ForEach(p => points[index++] = new Vector2(p.X, p.Y));
                    Hulls.Add(new Penumbra.Hull(points));
                });

                // Triangulate background for rendering
                {
                    var triangulation = TerrainHelper.Triangulate(Polygons);
                    TriangulatedBackgroundVertices = new VertexPositionColor[triangulation.Count * 3];
                    int index = 0;
                    for (int i = 0; i < triangulation.Count; ++i)
                    {
                        for (int b = 0; b < 3; ++b)
                        {
                            TriangulatedBackgroundVertices[index++] = new VertexPositionColor(
                                new Vector3(triangulation[i][b].X, triangulation[i][b].Y, 0), world.Planet.BackgroundSoilTint);
                        }
                    }
                }

                // Triangulate foreground for rendering
                {
                    var triangulation = TerrainHelper.Triangulate(output);
                    TriangulatedForegroundVertices = new VertexPositionColor[triangulation.Count * 3];
                    int index = 0;
                    for (int i = 0; i < triangulation.Count; ++i)
                    {
                        for (int b = 0; b < 3; ++b)
                        {
                            TriangulatedForegroundVertices[index++] = new VertexPositionColor(
                                new Vector3(triangulation[i][b].X, triangulation[i][b].Y, 0), world.Planet.SoilTint);
                        }
                    }
                }

                // Convert to Farseer data
                PhysicsOutput.Clear();
                output.ForEach(p =>
                {
                    PhysicsOutput.Add(TerrainHelper.PolygonToVertices(p));
                });
            }
Пример #6
0
        public void FixPolygonWindings()
        {
            Polygons solution2 = new Polygons();

            /*
             * if (false)
             * {
             *  for (int i = 0; i < DisplayShapes.Count; i++)
             *  {
             *      Polygons clips = new Polygons();
             *
             *      clips.Add(DisplayShapes[i].toPolygon());
             *      Clipper cp = new Clipper();
             *      cp.AddPolygons(solution2, PolyType.ptSubject);
             *      cp.AddPolygons(clips, PolyType.ptClip);
             *
             *      cp.Execute(ClipType.ctXor, solution2, PolyFillType.pftEvenOdd, PolyFillType.pftEvenOdd);
             *  }
             * }
             * else
             */
            {
                Polygons clips = new Polygons();
                for (int i = 0; i < DisplayShapes.Count; i++)
                {
                    clips.Add(DisplayShapes[i].toPolygon());
                }
                Clipper cp = new Clipper();
                cp.AddPolygons(solution2, PolyType.ptSubject);
                cp.AddPolygons(clips, PolyType.ptClip);

                cp.Execute(ClipType.ctXor, solution2, PolyFillType.pftEvenOdd, PolyFillType.pftEvenOdd);
            }


            OutlineShapes.Clear();

            for (int i = 0; i < solution2.Count; i++)
            {
                int ID = i;
                if (State != null)
                {
                    ID = State.LastShapeID++;
                }
                PolyLine PL = new PolyLine(ID);
                PL.fromPolygon(solution2[i]);

                // if (Clipper.Orientation(solution2[i]) == false)
                // {
                //    //     PL.Vertices.Reverse();
                // }

                PL.MyColor = Color.FromArgb(255, 200, 128, 0);
                OutlineShapes.Add(PL);
            }
        }
Пример #7
0
        internal static GraphicsPath Clip(List <List <IntPoint> > clippingPath, List <List <IntPoint> > distortionPoints)
        {
            var c = new Clipper();

            c.AddPolygons(distortionPoints, PolyType.ptSubject);
            c.AddPolygons(clippingPath, PolyType.ptClip);
            var polygons = new List <List <IntPoint> >();

            c.Execute(ClipType.ctIntersection, polygons, PolyFillType.pftEvenOdd, PolyFillType.pftEvenOdd);

            return(ConvertClipperToGraphicsPath(polygons));
        }
Пример #8
0
        public static GraphicsPath unionTwo(ref GraphicsPath p1, ref GraphicsPath p2)
        {
            List <List <IntPoint> > polygonB = ConvertToClipperPolygons(p1);
            var polygons = new List <List <IntPoint> >();
            List <List <IntPoint> > polygonA = ConvertToClipperPolygons(p2);

            var c = new Clipper();

            c.AddPolygons(polygonB, PolyType.ptSubject);
            c.AddPolygons(polygonA, PolyType.ptClip);
            c.Execute(ClipType.ctUnion, polygons, PolyFillType.pftEvenOdd, PolyFillType.pftEvenOdd);

            return(ConvertClipperToGraphicsPath(polygons));
        }
Пример #9
0
    private void RemoveCircle(Vector2 center, float radius, int count = 40)
    {
        List <IntPoint> poly = new List <IntPoint>();

        float delta = Mathf.PI * 2 / count;

        for (int i = 0; i < count; i++)
        {
            float x = center.x + Mathf.Cos(delta * i) * radius;
            float y = center.y + Mathf.Sin(delta * i) * radius;
            poly.Add(Convert(x, y));
        }

        Clipper clipper = new Clipper(Clipper.ioStrictlySimple);

        clipper.AddPolygons(m_polys, PolyType.ptSubject);
        clipper.AddPolygon(poly, PolyType.ptClip);
        clipper.Execute(ClipType.ctDifference, m_polyTree);

        Clipper.PolyTreeToPolygons(m_polyTree, m_polys);
        Clipper.SimplifyPolygons(m_polys);

        List <DelaunayTriangle> triangles = GenerateTriangles();

        GenerateMesh(triangles);
    }
Пример #10
0
        /// <summary>
        /// Applies the damage to affected chunks.
        /// </summary>
        /// <param name="damage">Damage.</param>
        private void ApplyDamage(List <IntPoint> damage)
        {
            long minX = long.MaxValue, minY = long.MaxValue,
                 maxX = long.MinValue, maxY = long.MinValue;

            for (int i = 0; i < damage.Count; ++i)
            {
                if (damage[i].X < minX)
                {
                    minX = damage[i].X;
                }
                if (damage[i].X > maxX)
                {
                    maxX = damage[i].X;
                }

                if (damage[i].Y < minY)
                {
                    minY = damage[i].Y;
                }
                if (damage[i].Y > maxY)
                {
                    maxY = damage[i].Y;
                }
            }

            minX = Helper.NegDivision(minX, Chunk.SIZE);
            maxX = Helper.NegDivision(maxX, Chunk.SIZE);
            minY = Helper.NegDivision(minY, Chunk.SIZE);
            maxY = Helper.NegDivision(maxY, Chunk.SIZE);

            var clipper = new Clipper();

            for (int y = (int)minY; y <= maxY; ++y)
            {
                for (int x = (int)minX; x <= maxX; ++x)
                {
                    var chunk = GetChunk(TerrainHelper.PackCoordinates(x, y));

                    clipper.Clear();
                    clipper.AddPolygon(new List <IntPoint>()
                    {
                        new IntPoint(chunk.Left, chunk.Top),
                        new IntPoint(chunk.Left + Chunk.SIZE, chunk.Top),
                        new IntPoint(chunk.Left + Chunk.SIZE, chunk.Top + Chunk.SIZE),
                        new IntPoint(chunk.Left, chunk.Top + Chunk.SIZE)
                    }, PolyType.ptSubject);
                    clipper.AddPolygon(damage, PolyType.ptClip);
                    clipper.AddPolygons(chunk.Damage, PolyType.ptClip);
                    clipper.Execute(ClipType.ctIntersection, chunk.Damage,
                                    PolyFillType.pftNonZero, PolyFillType.pftNonZero);

                    chunk.Recalculate = true;
                    if (ActiveChunks.Contains(chunk))
                    {
                        Task.Run(() => { PlaceChunk(chunk); });
                    }
                }
            }
        }
Пример #11
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();
                        }
                    }
                }
            }
Пример #12
0
        // polygons treatment
        private Polygons getPolygonsInRegion(int i, int j, double delta)
        {
            //converting the boundingbox of the region to a polygon
            Polygon clip = this.BoundingBoxToPolygon(this.ReagionsBoundingBoxes[i, j]);
            //initial polygons denote part of the subregions that are located within the region
            Polygons initialPolygons = new Polygons();
            Clipper  c = new Clipper();

            //c.StrictlySimple = true; // jeremy
            c.AddPolygons(this.IntRoads, PolyType.ptSubject);
            c.AddPolygon(clip, PolyType.ptClip);
            c.Execute(ClipType.ctIntersection, initialPolygons, PolyFillType.pftEvenOdd, PolyFillType.pftEvenOdd);
            // negative Clip is the roads inside the region clipping the region
            Polygons negativeClip = new Polygons();
            Clipper  negative     = new Clipper();

            //negative.StrictlySimple = true; // jeremy
            negative.AddPolygons(initialPolygons, PolyType.ptClip);
            negative.AddPolygon(clip, PolyType.ptSubject);
            negative.Execute(ClipType.ctIntersection, negativeClip, PolyFillType.pftEvenOdd, PolyFillType.pftEvenOdd);
            //shrinking the negative clip to remove common edges
            Polygons negativeShrank = Clipper.OffsetPolygons(negativeClip, -1 * Math.Pow(10, this.Exponent - 1), ClipperLib.JoinType.jtMiter);
            // expanding the negative shrink the negative clip to remove common edges
            Polygons negativeShrankExpand         = Clipper.OffsetPolygons(negativeShrank, Math.Pow(10, this.Exponent - 1) + 3, ClipperLib.JoinType.jtMiter);
            Polygons negativeShrankExpandNegative = new Polygons();
            Clipper  negativeAgain = new Clipper();

            //negativeAgain.StrictlySimple = true; // jeremy
            negativeAgain.AddPolygons(negativeShrankExpand, PolyType.ptSubject);
            negativeAgain.AddPolygon(clip, PolyType.ptClip);
            negativeAgain.Execute(ClipType.ctIntersection, negativeShrankExpandNegative, PolyFillType.pftEvenOdd, PolyFillType.pftEvenOdd);

            return(negativeShrankExpandNegative);
        }
Пример #13
0
        public static double TotalShapeIntersection(List <Shape> shapes, Form1 form)
        {
            var   collidedShapes = new List <(int, int)>();
            Paths subject        = new Paths(1);
            Paths collidingClips = new Paths(1);
            var   totalError     = 0.0;

            foreach (var shape in shapes)
            {
                // Add shape to subject
                subject = new Paths(1);
                subject.Add(new Path(shape.GetDrawingCoordinates()));

                // Find all shapes with collision distance and add to temporary clib
                collidingClips = new Paths(2);
                foreach (var externalShape in shapes)
                {
                    if (shape.IsNotSelf(externalShape) && shape.CollidesWith(externalShape))
                    {
                        var rankedIndexTuple =
                            (Math.Min(shape.Index, externalShape.Index), Math.Max(shape.Index, externalShape.Index));

                        if (!collidedShapes.Contains(rankedIndexTuple))
                        {
                            collidedShapes.Add(rankedIndexTuple);
                            collidingClips.Add(new Path(externalShape.GetDrawingCoordinates()));
                        }
                    }
                }

                Paths solution = new Paths(1);

                // TODO: Create a function to execute intersection
                Clipper c = new Clipper();
                c.AddPolygons(subject, PolyType.ptSubject);
                c.AddPolygons(collidingClips, PolyType.ptClip);
                c.Execute(ClipType.ctIntersection, solution,
                          PolyFillType.pftEvenOdd, PolyFillType.pftEvenOdd);

                Utils.DrawPolygons(solution, Color.Red, true, form);
                var intersectionError = Utils.PolygonSignedArea(solution);
                Logger.SimpleDebug("Area of intersection for shape " + shape.Index + " is " + intersectionError);
                totalError += intersectionError;
            }
            return(totalError * Config.IntersectionErrorModifier);
        }
Пример #14
0
        public static bool IsPolyOperation(List <List <IntPoint> > polys1, List <List <IntPoint> > polys2, ClipType cType)
        {
            Clipper c = new Clipper();

            c.AddPolygons(polys1, PolyType.ptSubject);
            c.AddPolygons(polys2, PolyType.ptClip);
            var solution = new List <List <IntPoint> >();

            try
            {
                c.Execute(cType, solution, PolyFillType.pftPositive, PolyFillType.pftPositive);
            }
            catch (Exception)
            {
            }
            return(solution.Count != 0);
        }
Пример #15
0
        /// <summary>
        /// 使用Clipper将阻挡裁剪出来
        /// </summary>
        private static List <List <IntPoint> > ClipPolygons(List <List <IntPoint> > walkablePolygons, List <List <IntPoint> > blockedPolygons)
        {
            //合并可走区域
            List <List <IntPoint> > result = new List <List <IntPoint> >();
            Clipper clipper = new Clipper();

            clipper.AddPolygons(walkablePolygons, PolyType.ptClip);
            clipper.Execute(ClipType.ctUnion, result, PolyFillType.pftNonZero, PolyFillType.pftNonZero);

            clipper.Clear();

            //去掉不可走区域
            clipper.AddPolygons(result, PolyType.ptSubject);
            clipper.AddPolygons(blockedPolygons, PolyType.ptClip);
            clipper.Execute(ClipType.ctDifference, result);

            return(result);
        }
Пример #16
0
    public List <IntPoint> AroundWall(Vector2 containPoint, float offset)
    {
        //将相邻的障碍物轮廓合并在一起
        List <List <IntPoint> > unions = new List <List <IntPoint> >();
        Clipper clipper = new Clipper();

        for (int i = 0; i < m_walls.Count; i++)
        {
            clipper.AddPolygons(m_walls[i].m_polygons, PolyType.ptSubject);
        }

        if (!clipper.Execute(ClipType.ctUnion, unions))
        {
            Debug.LogError("无法合并顶点");
            return(null);
        }

        //过滤出特定的那个轮廓
        List <IntPoint> contour = null;

        for (int i = 0; i < unions.Count; i++)
        {
            if (ClipperUtils.IsPointOnPolygonEdge(containPoint, unions[i]))
            {
                contour = unions[i];
                break;
            }
        }
        if (contour == null)
        {
            Debug.LogError("没找到包含特定点的障碍轮廓");
            return(null);
        }

        //对轮廓进行偏移
        List <List <IntPoint> > result = new List <List <IntPoint> >()
        {
            contour
        };

        result = Clipper.OffsetPolygons(result, offset * ClipperUtils.k_precision);
        if (result.Count > 1)
        {
            Debug.LogError("轮廓偏移后产生多个轮廓了?");
            return(result[0]);
        }
        else if (result.Count == 0)
        {
            Debug.LogError("轮廓偏移后不产生轮廓了?");
            return(null);
        }
        else
        {
            return(result[0]);
        }
    }
Пример #17
0
        void calculateRegionPath(ClipType clipType)
        {
            Clipper c = new Clipper();

            var subjects = solution;
            //subjects.Add (solution);

            var clips = new Paths();

            foreach (var path in regionList[regionList.Count - 1].regionPath)
            {
                clips.Add(path);
            }


            c.AddPolygons(subjects, PolyType.ptSubject);
            c.AddPolygons(clips, PolyType.ptClip);

            solution.Clear();

            bool succeeded = c.Execute(clipType, solution, SUBJ_FILL_TYPE, CLIP_FILL_TYPE);

            if (succeeded)
            {
                PathsToInternalPath(solution);

                // Not sure what this is returning
//				var bounds = c.GetBounds ();
//				regionBounds.X = bounds.left / scale;
//				regionBounds.Y = bounds.top / scale;
//				regionBounds.Width = (bounds.right - bounds.left) / scale;
//				regionBounds.Height = (bounds.bottom - bounds.top) / scale;

                if (regionPath.IsEmpty)
                {
                    regionBounds = RectangleF.Empty;
                }
                else
                {
                    regionBounds = regionPath.BoundingBox.ToRectangleF();
                }
            }
        }
Пример #18
0
        // Union Polylines
        private Polygons XOR(List <Polygon> polygons)
        {
            Polygons results = new Polygons();
            Clipper  c       = new Clipper();

            c.AddPolygons(polygons, PolyType.ptSubject);
            //c.StrictlySimple = true;
            c.Execute(ClipType.ctXor, results, PolyFillType.pftEvenOdd, PolyFillType.pftEvenOdd);
            return(Clipper.SimplifyPolygons(results));
        }
        IMoveableSection GetCutPolygon(List <Point2D> CuttingRectanglePoints)
        {
            #region GPC
            ////Cutting polygon
            //Polygon CuttingPoly = new Polygon();
            //CuttingPoly.AddContour(CuttingRectanglePoints, false);


            ////Original polygon
            //Polygon OriginalPoly = new Polygon();
            //OriginalPoly.AddContour(Vertices, false);

            //Polygon result = OriginalPoly.Clip(GpcOperation.Intersection, CuttingPoly);
            //GenericShape shape = new GenericShape(result);
            //return shape;
            #endregion

            #region Clipper
            Paths subj     = GetPolyPaths(Vertices);
            Paths clip     = GetPolyPaths(CuttingRectanglePoints);
            Paths solution = new Paths();

            Clipper c = new Clipper();
            c.AddPolygons(subj, PolyType.ptSubject);
            c.AddPolygons(clip, PolyType.ptClip);
            c.Execute(ClipType.ctIntersection, solution,
                      PolyFillType.pftEvenOdd, PolyFillType.pftEvenOdd);

            if (solution.Count == 0)
            {
                return(null);
            }
            else
            {
                PolygonShape shape = new PolygonShape(solution, true);
                return(shape);
            }



            #endregion
        }
Пример #20
0
        public static List <List <IntPoint> > GetPolySolution(List <IntPoint> poly, List <List <IntPoint> > polys, ClipType cType)
        {
            Clipper c = new Clipper();

            c.AddPolygons(new List <List <IntPoint> >()
            {
                poly
            }, PolyType.ptSubject);
            c.AddPolygons(polys, PolyType.ptClip);
            var solution = new List <List <IntPoint> >();

            try
            {
                c.Execute(cType, solution, PolyFillType.pftPositive, PolyFillType.pftPositive);
            }
            catch (Exception)
            {
            }
            return(solution);
        }
Пример #21
0
    private void InitMesh()
    {
        Clipper clipper = new Clipper(Clipper.ioStrictlySimple);

        clipper.AddPolygons(m_polys, PolyType.ptSubject);
        clipper.Execute(ClipType.ctDifference, m_polyTree);
        Clipper.SimplifyPolygons(m_polys);
        List <DelaunayTriangle> triangles = GenerateTriangles();

        GenerateMesh(triangles);
    }
Пример #22
0
        public static List <List <IntPoint> > GetPolyUnions(List <List <IntPoint> > polys)
        {
            Clipper c = new Clipper();

            c.AddPolygons(polys, PolyType.ptClip);
            var solution = new List <List <IntPoint> >();

            try
            {
                c.Execute(ClipType.ctUnion, solution, PolyFillType.pftPositive, PolyFillType.pftPositive);
            }
            catch (Exception)
            {
            }
            return(solution);
        }
Пример #23
0
        static public PolyTree FindDistictObjectBounds(ImageBuffer image)
        {
            MarchingSquaresByte marchingSquaresData = new MarchingSquaresByte(image, 5, 0);

            marchingSquaresData.CreateLineSegments();
            Polygons lineLoops = marchingSquaresData.CreateLineLoops(1);

            if (lineLoops.Count == 1)
            {
                return(null);
            }

            // create a bounding polygon to clip against
            IntPoint min = new IntPoint(long.MaxValue, long.MaxValue);
            IntPoint max = new IntPoint(long.MinValue, long.MinValue);

            foreach (Polygon polygon in lineLoops)
            {
                foreach (IntPoint point in polygon)
                {
                    min.X = Math.Min(point.X - 10, min.X);
                    min.Y = Math.Min(point.Y - 10, min.Y);
                    max.X = Math.Max(point.X + 10, max.X);
                    max.Y = Math.Max(point.Y + 10, max.Y);
                }
            }

            Polygon boundingPoly = new Polygon();

            boundingPoly.Add(min);
            boundingPoly.Add(new IntPoint(min.X, max.Y));
            boundingPoly.Add(max);
            boundingPoly.Add(new IntPoint(max.X, min.Y));

            // now clip the polygons to get the inside and outside polys
            Clipper clipper = new Clipper();

            clipper.AddPolygons(lineLoops, PolyType.ptSubject);
            clipper.AddPolygon(boundingPoly, PolyType.ptClip);

            PolyTree polyTreeForPlate = new PolyTree();

            clipper.Execute(ClipType.ctIntersection, polyTreeForPlate);

            return(polyTreeForPlate);
        }
Пример #24
0
        /// <summary>
        /// Inverts the selection.
        /// </summary>
        /// <param name="surface">
        /// Surface for the selection path.
        /// </param>
        /// <param name='imageSize'>
        /// The size of the document.
        /// </param>
        public void Invert(Surface surface, Gdk.Size imageSize)
        {
            List <List <IntPoint> > resultingPolygons = new List <List <IntPoint> > ();

            var documentPolygon = CreateRectanglePolygon(new Rectangle(0, 0, imageSize.Width, imageSize.Height));

            // Create a rectangle that is the size of the entire image,
            // and subtract all of the polygons in the current selection from it.
            SelectionClipper.AddPolygon(documentPolygon, PolyType.ptSubject);
            SelectionClipper.AddPolygons(SelectionPolygons, PolyType.ptClip);
            SelectionClipper.Execute(ClipType.ctDifference, resultingPolygons);

            SelectionClipper.Clear();

            SelectionPolygons = resultingPolygons;
            MarkDirty();
        }
Пример #25
0
        public void RectangularFillBetweenPolygons(ClipPaths paths, double cuttingdepth, double rapiddepth, double ystep, double x1, double x2, double y1, double y2, double stepdown)
        {
            ClipPaths clips = paths;
       //     ClipPaths paths = new ClipPaths();
            ClipperLib.Clipper cp = new Clipper();
            //cp.add
            cp.AddPolygons(paths, PolyType.ptClip);

            for(double y = y1;y<y2;y+= ystep  * 2)
            {
                ClipPath p = new ClipPath();
                p.Add(new IntPoint() { X = (int)(x1 * 100000), Y = (int)(y * 100000) });
                p.Add(new IntPoint() { X = (int)(x2 * 100000), Y = (int)(y * 100000) });
                p.Add(new IntPoint() { X = (int)(x2 * 100000), Y = (int)((y+ystep) * 100000) });
                p.Add(new IntPoint() { X = (int)(x1 * 100000), Y = (int)((y + ystep) * 100000) });
                cp.AddPolygon(p, PolyType.ptSubject);

            }
            ClipPaths res = new ClipPaths();
            cp.Execute(ClipType.ctDifference, res);
            AddClipperPolygonsToCarve(res, cuttingdepth, rapiddepth, stepdown);
        }
Пример #26
0
        public void redraw()
        {
            canvas.Children.Clear();

            if (rooms.Count == 0 && decoration.Count == 0)
            {
                return;
            }

            c.Clear();
            Polygons outline = new Polygons();

            c.AddPolygons(rooms, PolyType.ptSubject);
            c.AddPolygons(decoration, PolyType.ptSubject);
            c.Execute(ClipType.ctUnion, outline, PolyFillType.pftNonZero, PolyFillType.pftNonZero);
            outline = Clipper.OffsetPolygons(outline, 10, JoinType.jtMiter);

            // Bevel inside corners of the outline
            foreach (Polygon p in outline)
            {
                // Skip holes
                if (!Clipper.Orientation(p))
                {
                    continue;
                }

                // Find the inside corners
                List <bool> corners = new List <bool>();
                for (int j = 0; j < p.Count; ++j)
                {
                    int i = (j + p.Count - 1) % p.Count;
                    int k = (j + 1) % p.Count;

                    IntPoint e1 = new IntPoint(p[j].X - p[i].X, p[j].Y - p[i].Y);
                    IntPoint e2 = new IntPoint(p[j].X - p[k].X, p[j].Y - p[k].Y);

                    int a = (int)(e1.X * e2.Y - e2.X * e1.Y);

                    corners.Add(a > 0);
                }

                // Bevel them to the midpoints of the original lines
                for (int j = 0; j < p.Count; ++j)
                {
                    int i = (j + p.Count - 1) % p.Count;
                    int k = (j + 1) % p.Count;

                    if (corners[j])
                    {
                        if (!corners[i])
                        {
                            corners.Insert(j, true);
                            p.Insert(j, new IntPoint((p[i].X + p[j].X) / 2, (p[i].Y + p[j].Y) / 2));

                            ++j; ++k;
                        }

                        p[j] = new IntPoint((p[j].X + p[k].X) / 2, (p[j].Y + p[k].Y) / 2);
                    }
                }
            }

            foreach (Polygon p in rooms)
            {
                canvas.Children.Add(ToSystemPolygon(p));
            }

            foreach (Polygon p in outline)
            {
                canvas.Children.Add(ToSystemPolygon(p, Brushes.Yellow));
            }

            UpdateLayout();
        }
Пример #27
0
        //---------------------------------------------------------------------------

        private void DrawBitmap(bool justClip = false)
        {
            if (!justClip)
            {
                if (rbTest2.Checked)
                {
                    GenerateAustPlusRandomEllipses((int)nudCount.Value);
                }
                else
                {
                    GenerateRandomPolygon((int)nudCount.Value);
                }
            }

            Cursor.Current = Cursors.WaitCursor;
            Graphics newgraphic;

            newgraphic = Graphics.FromImage(mybitmap);
            newgraphic.SmoothingMode = SmoothingMode.AntiAlias;
            newgraphic.Clear(Color.White);

            GraphicsPath path = new GraphicsPath();

            if (rbNonZero.Checked)
            {
                path.FillMode = FillMode.Winding;
            }

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

            newgraphic.FillPath(myBrush, path);
            newgraphic.DrawPath(myPen, path);
            path.Reset();

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

            //do the clipping ...
            if ((clips.Count > 0 || subjects.Count > 0) && !rbNone.Checked)
            {
                Polygons solution2 = new Polygons();
                Clipper  c         = new Clipper();
                c.AddPolygons(subjects, PolyType.ptSubject);
                c.AddPolygons(clips, PolyType.ptClip);
                exSolution.Clear();
                solution.Clear();
                bool succeeded = c.Execute(GetClipType(), solution, GetPolyFillType(), GetPolyFillType());
                if (succeeded)
                {
                    myBrush.Color = Color.Black;
                    path.Reset();

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

                    //or for something fancy ...
                    if (nudOffset.Value != 0)
                    {
                        solution2 = Clipper.OffsetPolygons(solution, (double)nudOffset.Value * scale, JoinType.jtMiter);
                    }
                    else
                    {
                        solution2 = new Polygons(solution);
                    }
                    foreach (Polygon pg in solution2)
                    {
                        PointF[] pts = PolygonToPointFArray(pg, scale);
                        if (pts.Count() > 2)
                        {
                            path.AddPolygon(pts);
                        }
                        pts = null;
                    }
                    myBrush.Color = Color.FromArgb(127, 0x66, 0xEF, 0x7F);
                    myPen.Color   = Color.FromArgb(255, 0, 0x33, 0);
                    myPen.Width   = 1.0f;
                    newgraphic.FillPath(myBrush, path);
                    newgraphic.DrawPath(myPen, path);

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

                    StringFormat lftStringFormat = new StringFormat();
                    lftStringFormat.Alignment     = StringAlignment.Near;
                    lftStringFormat.LineAlignment = StringAlignment.Near;
                    StringFormat rtStringFormat = new StringFormat();
                    rtStringFormat.Alignment     = StringAlignment.Far;
                    rtStringFormat.LineAlignment = StringAlignment.Near;
                    Rectangle rec = new Rectangle(pictureBox1.ClientSize.Width - 108,
                                                  pictureBox1.ClientSize.Height - 116, 104, 106);
                    newgraphic.FillRectangle(new SolidBrush(Color.FromArgb(196, Color.WhiteSmoke)), rec);
                    newgraphic.DrawRectangle(myPen, rec);
                    rec.Inflate(new Size(-2, 0));
                    newgraphic.DrawString("Areas", f, b, rec, rtStringFormat);
                    rec.Offset(new Point(0, 14));
                    newgraphic.DrawString("subj: ", f, b, rec, lftStringFormat);
                    newgraphic.DrawString((subj_area / 100000).ToString("0,0"), f, b, rec, rtStringFormat);
                    rec.Offset(new Point(0, 12));
                    newgraphic.DrawString("clip: ", f, b, rec, lftStringFormat);
                    newgraphic.DrawString((clip_area / 100000).ToString("0,0"), f, b, rec, rtStringFormat);
                    rec.Offset(new Point(0, 12));
                    newgraphic.DrawString("intersect: ", f, b, rec, lftStringFormat);
                    newgraphic.DrawString((int_area / 100000).ToString("0,0"), f, b, rec, rtStringFormat);
                    rec.Offset(new Point(0, 12));
                    newgraphic.DrawString("---------", f, b, rec, rtStringFormat);
                    rec.Offset(new Point(0, 10));
                    newgraphic.DrawString("s + c - i: ", f, b, rec, lftStringFormat);
                    newgraphic.DrawString(((subj_area + clip_area - int_area) / 100000).ToString("0,0"), f, b, rec, rtStringFormat);
                    rec.Offset(new Point(0, 10));
                    newgraphic.DrawString("---------", f, b, rec, rtStringFormat);
                    rec.Offset(new Point(0, 10));
                    newgraphic.DrawString("union: ", f, b, rec, lftStringFormat);
                    newgraphic.DrawString((union_area / 100000).ToString("0,0"), f, b, rec, rtStringFormat);
                    rec.Offset(new Point(0, 10));
                    newgraphic.DrawString("---------", f, b, rec, rtStringFormat);
                } //end if succeeded
            }     //end if something to clip

            pictureBox1.Image = mybitmap;
            newgraphic.Dispose();
            Cursor.Current = Cursors.Default;
        }
Пример #28
0
        public List <PolyLine> CreatePolyLineSet(double X, double Y, int ShapeID, double rotation, double scale, GerberParserState.MirrorMode mirrored)
        {
            List <PolyLine> Res = new List <PolyLine>();

            if (Parts.Count > 0)
            {
                List <PolyLine> ResPre    = new List <PolyLine>();
                List <PolyLine> ResPreNeg = new List <PolyLine>();

                foreach (var a in Parts.Where(x => x.Polarity == true))
                {
                    ResPre.AddRange(a.CreatePolyLineSet(0, 0, ShapeID, 0, 1, GerberParserState.MirrorMode.NoMirror));
                }
                foreach (var a in Parts.Where(x => x.Polarity == false))
                {
                    ResPreNeg.AddRange(a.CreatePolyLineSet(0, 0, ShapeID, 0, 1, GerberParserState.MirrorMode.NoMirror));
                }
                Polygons Combined = new Polygons();
                Polygons Solution = new Polygons();


                Polygons clips = new Polygons();


                if (ResPreNeg.Count == 0)
                {
                    foreach (var c in ResPre)
                    {
                        //                    c.CheckIfHole();
                        //clips.Add(c.toPolygon());
                        //cp.AddPolygons(clips, PolyType.ptClip);
                        //cp.Execute(ClipType.ctUnion, Combined, PolyFillType.pftNonZero, PolyFillType.pftEvenOdd);

                        Solution.Add(c.toPolygon());
                    }
                    foreach (var p in Solution)
                    {
                        PolyLine PL = new PolyLine(ShapeID);
                        PL.fromPolygon(p);
                        Res.Add(PL);
                    }
                }
                else
                {
                    foreach (var c in ResPreNeg)
                    {
                        //                    c.CheckIfHole();
                        //clips.Add(c.toPolygon());
                        //cp.AddPolygons(clips, PolyType.ptClip);
                        //cp.Execute(ClipType.ctUnion, Combined, PolyFillType.pftNonZero, PolyFillType.pftEvenOdd);

                        clips.Add(c.toPolygon());
                    }

                    foreach (var c in ResPre)
                    {
                        //                    c.CheckIfHole();
                        //clips.Add(c.toPolygon());
                        //cp.AddPolygons(clips, PolyType.ptClip);
                        //cp.Execute(ClipType.ctUnion, Combined, PolyFillType.pftNonZero, PolyFillType.pftEvenOdd);

                        Combined.Add(c.toPolygon());
                    }

                    Clipper cp = new Clipper();
                    cp.AddPolygons(Combined, PolyType.ptClip);
                    cp.AddPolygons(clips, PolyType.ptSubject);

                    cp.Execute(ClipType.ctDifference, Solution, PolyFillType.pftNonZero, PolyFillType.pftNonZero);


                    foreach (var p in Solution)
                    {
                        PolyLine PL = new PolyLine(ShapeID);
                        PL.fromPolygon(p);
                        Res.Add(PL);
                    }
                }
            }
            else
            {
                if (Shape.Count() > 0)
                {
                    var PL = new PolyLine(ShapeID);
                    for (int i = 0; i < Shape.Count(); i++)
                    {
                        PL.Add(Shape.Vertices[i].X, Shape.Vertices[i].Y);
                    }
                    PL.Add(Shape.Vertices[0].X, Shape.Vertices[0].Y);
                    PL.Close();
                    Res.Add(PL);
                }
                else
                {
                    if (Gerber.ShowProgress)
                    {
                        Console.WriteLine("creating empty shape?? {0} {1}", MacroName, ShapeType);
                    }
                }
            }
            if (rotation != 0 || scale != 1 || mirrored != GerberParserState.MirrorMode.NoMirror)
            {
                double CA = Math.Cos((rotation * Math.PI * 2) / 360.0);
                double SA = Math.Sin((rotation * Math.PI * 2) / 360.0);

                double xscale = scale;
                double yscale = scale;
                switch (mirrored)
                {
                case GerberParserState.MirrorMode.X: xscale = -xscale; break;

                case GerberParserState.MirrorMode.XY: xscale = -xscale; yscale = -yscale; break;

                case GerberParserState.MirrorMode.Y: yscale = -yscale; break;
                }
                foreach (var a in Res)
                {
                    foreach (var p in a.Vertices)
                    {
                        double Xin = p.X;
                        double Yin = p.Y;

                        double nX = Xin * CA - Yin * SA;
                        double nY = Xin * SA + Yin * CA;


                        p.X = nX * xscale;
                        p.Y = nY * yscale;
                    }
                }
            }

            foreach (var a in Res)
            {
                foreach (var p in a.Vertices)
                {
                    p.X += X;
                    p.Y += Y;
                }
            }
            return(Res);
        }
Пример #29
0
        ////////////////////////////////////////////////

        static void Main(string[] args)
        {
            ////quick test with random polygons ...
            //Polygons ss = new Polygons(1), cc = new Polygons(1), sss = new Polygons();
            //Random r = new Random((int)DateTime.Now.Ticks);
            //int scale = 1000000000; //tests 128bit math
            //ss.Add(MakeRandomPolygon(r, 400, 350, 9, scale));
            //cc.Add(MakeRandomPolygon(r, 400, 350, 9, scale));
            //Clipper cpr = new Clipper();
            //cpr.AddPolygons(ss, PolyType.ptSubject);
            //cpr.AddPolygons(cc, PolyType.ptClip);
            //cpr.Execute(ClipType.ctUnion, sss, PolyFillType.pftNonZero, PolyFillType.pftNonZero);
            //sss = Clipper.OffsetPolygons(sss, -5.0*scale, JoinType.jtMiter, 4);
            //SVGBuilder svg1 = new SVGBuilder();
            //svg1.style.brushClr = Color.FromArgb(0x20, 0, 0, 0x9c);
            //svg1.style.penClr = Color.FromArgb(0xd3, 0xd3, 0xda);
            //svg1.AddPolygons(ss);
            //svg1.style.brushClr = Color.FromArgb(0x20, 0x9c, 0, 0);
            //svg1.style.penClr = Color.FromArgb(0xff, 0xa0, 0x7a);
            //svg1.AddPolygons(cc);
            //svg1.style.brushClr = Color.FromArgb(0xAA, 0x80, 0xff, 0x9c);
            //svg1.style.penClr = Color.FromArgb(0, 0x33, 0);
            //svg1.AddPolygons(sss);
            //svg1.SaveToFile("solution.svg", 1.0/scale);
            //return;

            if (args.Length < 5)
            {
                string appname = System.Environment.GetCommandLineArgs()[0];
                appname = Path.GetFileName(appname);
                Console.WriteLine("");
                Console.WriteLine("Usage:");
                Console.WriteLine("  {0} CLIPTYPE s_file c_file INPUT_DEC_PLACES SVG_SCALE [S_FILL, C_FILL]", appname);
                Console.WriteLine("  where ...");
                Console.WriteLine("  CLIPTYPE = INTERSECTION|UNION|DIFFERENCE|XOR");
                Console.WriteLine("  FILLMODE = NONZERO|EVENODD");
                Console.WriteLine("  INPUT_DEC_PLACES = signific. decimal places for subject & clip coords.");
                Console.WriteLine("  SVG_SCALE = scale of SVG image as power of 10. (Fractions are accepted.)");
                Console.WriteLine("  both S_FILL and C_FILL are optional. The default is EVENODD.");
                Console.WriteLine("Example:");
                Console.WriteLine("  Intersect polygons, rnd to 4 dec places, SVG is 1/100 normal size ...");
                Console.WriteLine("  {0} INTERSECTION subj.txt clip.txt 0 0 NONZERO NONZERO", appname);
                return;
            }

            ClipType ct;

            switch (args[0].ToUpper())
            {
            case "INTERSECTION": ct = ClipType.ctIntersection; break;

            case "UNION": ct = ClipType.ctUnion; break;

            case "DIFFERENCE": ct = ClipType.ctDifference; break;

            case "XOR": ct = ClipType.ctXor; break;

            default: Console.WriteLine("Error: invalid operation - {0}", args[0]); return;
            }

            string subjFilename = args[1];
            string clipFilename = args[2];

            if (!File.Exists(subjFilename))
            {
                Console.WriteLine("Error: file - {0} - does not exist.", subjFilename);
                return;
            }
            if (!File.Exists(clipFilename))
            {
                Console.WriteLine("Error: file - {0} - does not exist.", clipFilename);
                return;
            }

            int decimal_places = 0;

            if (!Int32.TryParse(args[3], out decimal_places))
            {
                Console.WriteLine("Error: invalid number of decimal places - {0}", args[3]);
                return;
            }
            if (decimal_places > 8)
            {
                decimal_places = 8;
            }
            else if (decimal_places < 0)
            {
                decimal_places = 0;
            }

            double svg_scale = 0;

            if (!double.TryParse(args[4], out svg_scale))
            {
                Console.WriteLine("Error: invalid value for SVG_SCALE - {0}", args[4]);
                return;
            }
            if (svg_scale < -18)
            {
                svg_scale = -18;
            }
            else if (svg_scale > 18)
            {
                svg_scale = 18;
            }
            svg_scale = Math.Pow(10, svg_scale - decimal_places);//nb: also compensate for decimal places


            PolyFillType pftSubj = PolyFillType.pftEvenOdd;
            PolyFillType pftClip = PolyFillType.pftEvenOdd;

            if (args.Length > 6)
            {
                switch (args[5].ToUpper())
                {
                case "EVENODD": pftSubj = PolyFillType.pftEvenOdd; break;

                case "NONZERO": pftSubj = PolyFillType.pftNonZero; break;

                default: Console.WriteLine("Error: invalid cliptype - {0}", args[5]); return;
                }
                switch (args[6].ToUpper())
                {
                case "EVENODD": pftClip = PolyFillType.pftEvenOdd; break;

                case "NONZERO": pftClip = PolyFillType.pftNonZero; break;

                default: Console.WriteLine("Error: invalid cliptype - {0}", args[6]); return;
                }
            }

            Polygons subjs = new Polygons();
            Polygons clips = new Polygons();

            if (!LoadFromFile(subjFilename, subjs, decimal_places))
            {
                Console.WriteLine("Error processing subject polygons file - {0} ", subjFilename);
                OutputFileFormat();
                return;
            }
            if (!LoadFromFile(clipFilename, clips, decimal_places))
            {
                Console.WriteLine("Error processing clip polygons file - {0} ", clipFilename);
                OutputFileFormat();
                return;
            }

            Console.WriteLine("wait ...");
            Clipper cp = new Clipper();

            cp.AddPolygons(subjs, PolyType.ptSubject);
            cp.AddPolygons(clips, PolyType.ptClip);

            Polygons solution = new Polygons();

            //Polygons solution = new Polygons();
            if (cp.Execute(ct, solution, pftSubj, pftClip))
            {
                SaveToFile("solution.txt", solution, decimal_places);

                //solution = Clipper.OffsetPolygons(solution, -4, JoinType.jtRound);

                SVGBuilder svg = new SVGBuilder();
                svg.style.brushClr = Color.FromArgb(0x20, 0, 0, 0x9c);
                svg.style.penClr   = Color.FromArgb(0xd3, 0xd3, 0xda);
                svg.AddPolygons(subjs);
                svg.style.brushClr = Color.FromArgb(0x20, 0x9c, 0, 0);
                svg.style.penClr   = Color.FromArgb(0xff, 0xa0, 0x7a);
                svg.AddPolygons(clips);
                svg.style.brushClr = Color.FromArgb(0xAA, 0x80, 0xff, 0x9c);
                svg.style.penClr   = Color.FromArgb(0, 0x33, 0);
                svg.AddPolygons(solution);
                svg.SaveToFile("solution.svg", svg_scale);

                Console.WriteLine("finished!");
            }
            else
            {
                Console.WriteLine("failed!");
            }
        }
        private void ComboBoxOnSelectionChanged(object sender, SelectionChangedEventArgs selectionChangedEventArgs)
        {
            // INIT THE SIMULATION
            InitSimulation();

            // INTERMEDIATE AREAS FROM ROOMS/SPACES
            var storey = (sender as ComboBox).SelectedItem as IfcBuildingStorey;

            foreach (var space in storey.Spaces)
            {
                // var points = DeriveGeometry(space);
                // var points = DeriveGeometry2D(space);

                var points = CastPoints(GeometryHandler.GetFootPrint(space, context));

                if (points == null)
                {
                    continue;
                }

                sim.layouts[0].scenario.AddArea(space.Name, points, PedSimXMLWriter.areaType.Intermediate);
            }

            // INTERMEDIATE AREAS FROM DOORS
            List <List <point> > doorOpeningElements = new List <List <point> >();

            var doors = xModel.Instances.OfType <IfcRelFillsElement>();

            foreach (var item in doors)
            {
                if (item.RelatedBuildingElement.GetType().ToString().Contains("Door"))
                {
                    var points = CastPoints(GeometryHandler.GetFootPrint(item.RelatingOpeningElement, context));
                    // var points = DeriveGeometry2D(item.RelatingOpeningElement);
                    if (points == null)
                    {
                        continue;
                    }
                    doorOpeningElements.Add(points);
                    sim.layouts[0].scenario.AddArea(item.Name, points, PedSimXMLWriter.areaType.Intermediate);
                }
            }

            // COMPUTE THE ORIGIN AREAS FOR EACH ROOM/SPACE
            // foreach (var space in storey.Spaces)
            // {
            //     var points = DeriveGeometry2D(space);
            // }

            // Get the openings ...
            // List<IfcProduct> doors = new List<IfcProduct>();
            // List<List<point>> doorPolygons = new List<List<point>>();
            // foreach (var item in storey.ContainsElements.ElementAt(0).RelatedElements)
            // {
            //     if (item.GetType().ToString().Contains(@"Door"))
            //     {
            //         // var relVoids = xModel.Instances.OfType<IfcRelFillsElement>();
            //         // foreach (var relVoid in relVoids)
            //         // {
            //         //     if (relVoid.RelatedBuildingElement == item)
            //         //     {
            //         //         var points = DeriveGeometry(relVoid.RelatingOpeningElement);
            //         //         sim.layouts[0].scenario.AddArea(relVoid.RelatingOpeningElement.Name, points, PedSimXMLWriter.areaType.Intermediate);
            //         //     }
            //         // }
            //         // (item as IfcDoor).FillsVoids.
            //         doors.Add(item);
            //     }
            // }
            // foreach (var door in doors)
            // {
            //     var points = DeriveGeometry(door);
            //     doorPolygons.Add(points);
            //     sim.layouts[0].scenario.AddArea(door.Name, points, PedSimXMLWriter.areaType.Intermediate);
            // }

            // GET THE COLUMNS AS OBSTACLES
            // List<IfcProduct> columns = new List<IfcProduct>();
            //
            // foreach (var item in storey.ContainsElements.ElementAt(0).RelatedElements)
            // {
            //     if (item.GetType().ToString().Contains("Column"))
            //     {
            //         columns.Add(item);
            //     }
            // }

            // foreach (var column in columns)
            // {
            //     var columnPoints = DeriveGeometry2D(column);
            //     sim.layouts[0].scenario.AddSolidObstacle(column.Name, columnPoints);
            // }

            // GET THE WALLS AS OBSTACLES
            List <IfcProduct> walls = new List <IfcProduct>();

            foreach (var item in storey.ContainsElements.ElementAt(0).RelatedElements)
            {
                if (item.GetType().ToString().Contains("Wall"))
                {
                    walls.Add(item);
                }
            }

            foreach (var wall in walls)
            {
                // var wallPoints = DeriveGeometry2D(wall);
                var wallPoints = CastPoints(GeometryHandler.GetFootPrint(wall, context));
                // Clipping - Walls are clipped by openings
                int multiplyFactor = 90;

                // WallPolygon
                List <List <IntPoint> > subj = new List <List <IntPoint> >();
                subj.Add(new List <IntPoint>());

                foreach (var item in wallPoints)
                {
                    subj[0].Add(new IntPoint((long)(item.x * multiplyFactor), (long)(item.y * multiplyFactor)));
                }
                // subj[0].Distinct();

                // Clipping Opening Area from doors
                List <List <IntPoint> > clip = new List <List <IntPoint> >();
                int i = 0;
                foreach (var opening in doorOpeningElements)
                {
                    clip.Add(new List <IntPoint>());
                    foreach (var item in opening)
                    {
                        clip[i].Add(new IntPoint((long)(item.x * multiplyFactor), (long)(item.y * multiplyFactor)));
                    }
                    i++;
                }

                var solution = new List <List <IntPoint> >();
                var c        = new Clipper();
                // c.ReverseSolution = true;

                c.AddPolygons(subj, PolyType.ptSubject);
                c.AddPolygons(clip, PolyType.ptClip);

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

                foreach (var solutionItem in solution)
                {
                    List <point> sol = new List <point>();
                    foreach (var coord in  solutionItem)
                    {
                        sol.Add(new point {
                            x = ((double)coord.X) / multiplyFactor, y = ((double)coord.Y) / multiplyFactor
                        });
                    }

                    var convexSol = CreateConvexHull(sol);

                    sim.layouts[0].scenario.AddSolidObstacle(wall.Name, convexSol);
                }
                if (solution.Count == 0)
                {
                    sim.layouts[0].scenario.AddSolidObstacle(wall.Name, wallPoints);
                }
            }

            // SET MIN & MAX
            sim.layouts[0].scenario.maxX = MaxX;
            sim.layouts[0].scenario.minX = MinX;
            sim.layouts[0].scenario.maxY = MaxY;
            sim.layouts[0].scenario.minY = MinY;

            // SERIALIZE
            SerializeSimulation();
        }