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); }
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); }
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); }
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); }
/// <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)); }); }
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); } }
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)); }
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)); }
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); }
/// <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); }); } } } }
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(); } } } }
// 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); }
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); }
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); }
/// <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); }
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]); } }
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(); } } }
// 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 }
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); }
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); }
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); }
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); }
/// <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(); }
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); }
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(); }
//--------------------------------------------------------------------------- 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; }
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); }
//////////////////////////////////////////////// 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(); }