public static void renderTree(ClipperLib.PolyNode node, List <Vector3> verts, List <Vector3> norms, List <Vector2> uvs, List <int> faces, ref int idx) { Poly2Tri.Polygon p = new Poly2Tri.Polygon(node.Contour.ConvertAll <Poly2Tri.PolygonPoint>(PP)); //p.RemoveDuplicateNeighborPoints(); //p.MergeParallelEdges(1e-3); foreach (ClipperLib.PolyNode child in node.Childs) { if (child.IsHole) { Poly2Tri.Polygon h = new Poly2Tri.Polygon(child.Contour.ConvertAll <Poly2Tri.PolygonPoint>(PP)); h.RemoveDuplicateNeighborPoints(); h.MergeParallelEdges(1e-3); p.AddHole(h); } else { renderTree(child, verts, norms, uvs, faces, ref idx); } } Poly2Tri.DTSweepContext ctx = new Poly2Tri.DTSweepContext(); ctx.PrepareTriangulation(p); Poly2Tri.DTSweep.Triangulate(ctx); foreach (Poly2Tri.DelaunayTriangle dt in p.Triangles) { faces.Add(idx); uvs.Add(UV(dt.Points[2])); norms.Add(Vector3.back); verts.Add(V3(dt.Points[2])); idx++; faces.Add(idx); uvs.Add(UV(dt.Points[1])); norms.Add(Vector3.back); verts.Add(V3(dt.Points[1])); idx++; faces.Add(idx); uvs.Add(UV(dt.Points[0])); norms.Add(Vector3.back); verts.Add(V3(dt.Points[0])); idx++; } }
internal void AddChild(PolyNode Child) { int cnt = m_Childs.Count; m_Childs.Add(Child); Child.m_Parent = this; Child.m_Index = cnt; }
//------------------------------------------------------------------------------ public void AddPath(List<IntPoint> path, JoinType joinType, EndType endType) { int highI = path.Count - 1; if (highI < 0) return; PolyNode newNode = new PolyNode(); newNode.m_jointype = joinType; newNode.m_endtype = endType; //strip duplicate points from path and also get index to the lowest point ... if (endType == EndType.etClosedLine || endType == EndType.etClosedPolygon) while (highI > 0 && path[0] == path[highI]) highI--; newNode.m_polygon.Capacity = highI + 1; newNode.m_polygon.Add(path[0]); int j = 0, k = 0; for (int i = 1; i <= highI; i++) if (newNode.m_polygon[j] != path[i]) { j++; newNode.m_polygon.Add(path[i]); if (path[i].Y > newNode.m_polygon[k].Y || (path[i].Y == newNode.m_polygon[k].Y && path[i].X < newNode.m_polygon[k].X)) k = j; } if (endType == EndType.etClosedPolygon && j < 2) return; m_polyNodes.AddChild(newNode); //if this path's lowest pt is lower than all the others then update m_lowest if (endType != EndType.etClosedPolygon) return; if (m_lowest.X < 0) m_lowest = new IntPoint(m_polyNodes.ChildCount - 1, k); else { IntPoint ip = m_polyNodes.Childs[(int)m_lowest.X].m_polygon[(int)m_lowest.Y]; if (newNode.m_polygon[k].Y > ip.Y || (newNode.m_polygon[k].Y == ip.Y && newNode.m_polygon[k].X < ip.X)) m_lowest = new IntPoint(m_polyNodes.ChildCount - 1, k); } }
public List<DelaunayTriangle> TriangulateComplex( PolyTree polyTree, bool ignoreFills = false, bool ignoreHoles = true) { PolyNode rootNode; if (polyTree.Total == 0) { Console.WriteLine(0); rootNode = new PolyNode(); } else { rootNode = polyTree.GetFirst().Parent; } // Equivalent to rootNode.Contour = bounds; var contourField = rootNode.GetType().GetField("m_polygon", BindingFlags.Instance | BindingFlags.NonPublic); if (contourField == null) { throw new Exception("Could not find field contour backing field."); } contourField.SetValue(rootNode, kTriangulatorBounds); var result = new List<DelaunayTriangle>(); int i = 0; for (var currentNode = rootNode; currentNode != null; currentNode = currentNode.GetNext()) { if ((ignoreHoles && currentNode.IsHole) || (ignoreFills && !currentNode.IsHole)) continue; var polyline = DownscalePolygon(currentNode.Contour); var finalPolygon = new Polygon(polyline); foreach (var child in currentNode.Childs) { var shrunkContour = EdgeShrink(child.Contour); var holePoints = DownscalePolygon(shrunkContour); var holePoly = new Polygon(holePoints); finalPolygon.AddHole(holePoly); } P2T.Triangulate(finalPolygon); result.AddRange(finalPolygon.Triangles); } return result; }
//------------------------------------------------------------------------------ public void AddPath(List <IntPoint> path, JoinType joinType, EndType endType) { int highI = path.Count - 1; if (highI < 0) { return; } PolyNode newNode = new PolyNode(); newNode.m_jointype = joinType; newNode.m_endtype = endType; //strip duplicate points from path and also get index to the lowest point ... if (endType == EndType.etClosedLine || endType == EndType.etClosedPolygon) { while (highI > 0 && path[0] == path[highI]) { highI--; } } newNode.m_polygon.Capacity = highI + 1; newNode.m_polygon.Add(path[0]); int j = 0, k = 0; for (int i = 1; i <= highI; i++) { if (newNode.m_polygon[j] != path[i]) { j++; newNode.m_polygon.Add(path[i]); if (path[i].Y > newNode.m_polygon[k].Y || (path[i].Y == newNode.m_polygon[k].Y && path[i].X < newNode.m_polygon[k].X)) { k = j; } } } if (endType == EndType.etClosedPolygon && j < 2) { return; } m_polyNodes.AddChild(newNode); //if this path's lowest pt is lower than all the others then update m_lowest if (endType != EndType.etClosedPolygon) { return; } if (m_lowest.X < 0) { m_lowest = new IntPoint(m_polyNodes.ChildCount - 1, k); } else { IntPoint ip = m_polyNodes.Childs[(int)m_lowest.X].m_polygon[(int)m_lowest.Y]; if (newNode.m_polygon[k].Y > ip.Y || (newNode.m_polygon[k].Y == ip.Y && newNode.m_polygon[k].X < ip.X)) { m_lowest = new IntPoint(m_polyNodes.ChildCount - 1, k); } } }
//------------------------------------------------------------------------------ private void DoOffset(double delta) { m_destPolys = new List <List <IntPoint> >(); m_delta = delta; //if Zero offset, just copy any CLOSED polygons to m_p and return ... if (ClipperBase.near_zero(delta)) { m_destPolys.Capacity = m_polyNodes.ChildCount; for (int i = 0; i < m_polyNodes.ChildCount; i++) { PolyNode node = m_polyNodes.Childs[i]; if (node.m_endtype == EndType.etClosedPolygon) { m_destPolys.Add(node.m_polygon); } } return; } //see offset_triginometry3.svg in the documentation folder ... if (MiterLimit > 2) { m_miterLim = 2 / (MiterLimit * MiterLimit); } else { m_miterLim = 0.5; } double y; if (ArcTolerance <= 0.0) { y = def_arc_tolerance; } else if (ArcTolerance > Math.Abs(delta) * def_arc_tolerance) { y = Math.Abs(delta) * def_arc_tolerance; } else { y = ArcTolerance; } //see offset_triginometry2.svg in the documentation folder ... double steps = Math.PI / Math.Acos(1 - y / Math.Abs(delta)); m_sin = Math.Sin(two_pi / steps); m_cos = Math.Cos(two_pi / steps); m_StepsPerRad = steps / two_pi; if (delta < 0.0) { m_sin = -m_sin; } m_destPolys.Capacity = m_polyNodes.ChildCount * 2; for (int i = 0; i < m_polyNodes.ChildCount; i++) { PolyNode node = m_polyNodes.Childs[i]; m_srcPoly = node.m_polygon; int len = m_srcPoly.Count; if (len == 0 || (delta <= 0 && (len < 3 || node.m_endtype != EndType.etClosedPolygon))) { continue; } m_destPoly = new List <IntPoint>(); if (len == 1) { if (node.m_jointype == JoinType.jtRound) { double X = 1.0, Y = 0.0; for (int j = 1; j <= steps; j++) { m_destPoly.Add(new IntPoint( Round(m_srcPoly[0].X + X * delta), Round(m_srcPoly[0].Y + Y * delta))); double X2 = X; X = X * m_cos - m_sin * Y; Y = X2 * m_sin + Y * m_cos; } } else { double X = -1.0, Y = -1.0; for (int j = 0; j < 4; ++j) { m_destPoly.Add(new IntPoint( Round(m_srcPoly[0].X + X * delta), Round(m_srcPoly[0].Y + Y * delta))); if (X < 0) { X = 1; } else if (Y < 0) { Y = 1; } else { X = -1; } } } m_destPolys.Add(m_destPoly); continue; } //build m_normals ... m_normals.Clear(); m_normals.Capacity = len; for (int j = 0; j < len - 1; j++) { m_normals.Add(GetUnitNormal(m_srcPoly[j], m_srcPoly[j + 1])); } if (node.m_endtype == EndType.etClosedLine || node.m_endtype == EndType.etClosedPolygon) { m_normals.Add(GetUnitNormal(m_srcPoly[len - 1], m_srcPoly[0])); } else { m_normals.Add(new DoublePoint(m_normals[len - 2])); } if (node.m_endtype == EndType.etClosedPolygon) { int k = len - 1; for (int j = 0; j < len; j++) { OffsetPoint(j, ref k, node.m_jointype); } m_destPolys.Add(m_destPoly); } else if (node.m_endtype == EndType.etClosedLine) { int k = len - 1; for (int j = 0; j < len; j++) { OffsetPoint(j, ref k, node.m_jointype); } m_destPolys.Add(m_destPoly); m_destPoly = new List <IntPoint>(); //re-build m_normals ... DoublePoint n = m_normals[len - 1]; for (int j = len - 1; j > 0; j--) { m_normals[j] = new DoublePoint(-m_normals[j - 1].X, -m_normals[j - 1].Y); } m_normals[0] = new DoublePoint(-n.X, -n.Y); k = 0; for (int j = len - 1; j >= 0; j--) { OffsetPoint(j, ref k, node.m_jointype); } m_destPolys.Add(m_destPoly); } else { int k = 0; for (int j = 1; j < len - 1; ++j) { OffsetPoint(j, ref k, node.m_jointype); } IntPoint pt1; if (node.m_endtype == EndType.etOpenButt) { int j = len - 1; pt1 = new IntPoint((int)Round(m_srcPoly[j].X + m_normals[j].X * delta), (int)Round(m_srcPoly[j].Y + m_normals[j].Y * delta)); m_destPoly.Add(pt1); pt1 = new IntPoint((int)Round(m_srcPoly[j].X - m_normals[j].X * delta), (int)Round(m_srcPoly[j].Y - m_normals[j].Y * delta)); m_destPoly.Add(pt1); } else { int j = len - 1; k = len - 2; m_sinA = 0; m_normals[j] = new DoublePoint(-m_normals[j].X, -m_normals[j].Y); if (node.m_endtype == EndType.etOpenSquare) { DoSquare(j, k); } else { DoRound(j, k); } } //re-build m_normals ... for (int j = len - 1; j > 0; j--) { m_normals[j] = new DoublePoint(-m_normals[j - 1].X, -m_normals[j - 1].Y); } m_normals[0] = new DoublePoint(-m_normals[1].X, -m_normals[1].Y); k = len - 1; for (int j = k - 1; j > 0; --j) { OffsetPoint(j, ref k, node.m_jointype); } if (node.m_endtype == EndType.etOpenButt) { pt1 = new IntPoint((int)Round(m_srcPoly[0].X - m_normals[0].X * delta), (int)Round(m_srcPoly[0].Y - m_normals[0].Y * delta)); m_destPoly.Add(pt1); pt1 = new IntPoint((int)Round(m_srcPoly[0].X + m_normals[0].X * delta), (int)Round(m_srcPoly[0].Y + m_normals[0].Y * delta)); m_destPoly.Add(pt1); } else { k = 1; m_sinA = 0; if (node.m_endtype == EndType.etOpenSquare) { DoSquare(0, 1); } else { DoRound(0, 1); } } m_destPolys.Add(m_destPoly); } } }
//------------------------------------------------------------------------------ private void BuildResult2(PolyTree polytree) { polytree.Clear(); //add each output polygon/contour to polytree ... polytree.m_AllPolys.Capacity = m_PolyOuts.Count; for (int i = 0; i < m_PolyOuts.Count; i++) { OutRec outRec = m_PolyOuts[i]; int cnt = PointCount(outRec.Pts); if ((outRec.IsOpen && cnt < 2) || (!outRec.IsOpen && cnt < 3)) continue; FixHoleLinkage(outRec); PolyNode pn = new PolyNode(); polytree.m_AllPolys.Add(pn); outRec.PolyNode = pn; pn.m_polygon.Capacity = cnt; OutPt op = outRec.Pts.Prev; for (int j = 0; j < cnt; j++) { pn.m_polygon.Add(op.Pt); op = op.Prev; } } //fixup PolyNode links etc ... polytree.m_Childs.Capacity = m_PolyOuts.Count; for (int i = 0; i < m_PolyOuts.Count; i++) { OutRec outRec = m_PolyOuts[i]; if (outRec.PolyNode == null) continue; else if (outRec.IsOpen) { outRec.PolyNode.IsOpen = true; polytree.AddChild(outRec.PolyNode); } else if (outRec.FirstLeft != null && outRec.FirstLeft.PolyNode != null) outRec.FirstLeft.PolyNode.AddChild(outRec.PolyNode); else polytree.AddChild(outRec.PolyNode); } }
private void DoOffset(double delta) { m_destPolys = new List <List <IntPoint> >(); m_delta = delta; if (ClipperBase.near_zero(delta)) { m_destPolys.Capacity = m_polyNodes.ChildCount; for (int i = 0; i < m_polyNodes.ChildCount; i++) { PolyNode polyNode = m_polyNodes.Childs[i]; if (polyNode.m_endtype == EndType.etClosedPolygon) { m_destPolys.Add(polyNode.m_polygon); } } } else { if (MiterLimit > 2.0) { m_miterLim = 2.0 / (MiterLimit * MiterLimit); } else { m_miterLim = 0.5; } double num = (ArcTolerance <= 0.0) ? 0.25 : ((!(ArcTolerance > Math.Abs(delta) * 0.25)) ? ArcTolerance : (Math.Abs(delta) * 0.25)); double num2 = 3.1415926535897931 / Math.Acos(1.0 - num / Math.Abs(delta)); m_sin = Math.Sin(6.2831853071795862 / num2); m_cos = Math.Cos(6.2831853071795862 / num2); m_StepsPerRad = num2 / 6.2831853071795862; if (delta < 0.0) { m_sin = 0.0 - m_sin; } m_destPolys.Capacity = m_polyNodes.ChildCount * 2; for (int j = 0; j < m_polyNodes.ChildCount; j++) { PolyNode polyNode2 = m_polyNodes.Childs[j]; m_srcPoly = polyNode2.m_polygon; int count = m_srcPoly.Count; if (count != 0 && (!(delta <= 0.0) || (count >= 3 && polyNode2.m_endtype == EndType.etClosedPolygon))) { m_destPoly = new List <IntPoint>(); if (count == 1) { if (polyNode2.m_jointype == JoinType.jtRound) { double num3 = 1.0; double num4 = 0.0; for (int k = 1; (double)k <= num2; k++) { m_destPoly.Add(new IntPoint(Round((double)m_srcPoly[0].X + num3 * delta), Round((double)m_srcPoly[0].Y + num4 * delta))); double num5 = num3; num3 = num3 * m_cos - m_sin * num4; num4 = num5 * m_sin + num4 * m_cos; } } else { double num6 = -1.0; double num7 = -1.0; for (int l = 0; l < 4; l++) { m_destPoly.Add(new IntPoint(Round((double)m_srcPoly[0].X + num6 * delta), Round((double)m_srcPoly[0].Y + num7 * delta))); if (num6 < 0.0) { num6 = 1.0; } else if (num7 < 0.0) { num7 = 1.0; } else { num6 = -1.0; } } } m_destPolys.Add(m_destPoly); } else { m_normals.Clear(); m_normals.Capacity = count; for (int m = 0; m < count - 1; m++) { m_normals.Add(GetUnitNormal(m_srcPoly[m], m_srcPoly[m + 1])); } if (polyNode2.m_endtype == EndType.etClosedLine || polyNode2.m_endtype == EndType.etClosedPolygon) { m_normals.Add(GetUnitNormal(m_srcPoly[count - 1], m_srcPoly[0])); } else { m_normals.Add(new DoublePoint(m_normals[count - 2])); } if (polyNode2.m_endtype == EndType.etClosedPolygon) { int k2 = count - 1; for (int n = 0; n < count; n++) { OffsetPoint(n, ref k2, polyNode2.m_jointype); } m_destPolys.Add(m_destPoly); } else if (polyNode2.m_endtype == EndType.etClosedLine) { int k3 = count - 1; for (int num8 = 0; num8 < count; num8++) { OffsetPoint(num8, ref k3, polyNode2.m_jointype); } m_destPolys.Add(m_destPoly); m_destPoly = new List <IntPoint>(); DoublePoint doublePoint = m_normals[count - 1]; for (int num9 = count - 1; num9 > 0; num9--) { m_normals[num9] = new DoublePoint(0.0 - m_normals[num9 - 1].X, 0.0 - m_normals[num9 - 1].Y); } m_normals[0] = new DoublePoint(0.0 - doublePoint.X, 0.0 - doublePoint.Y); k3 = 0; for (int num10 = count - 1; num10 >= 0; num10--) { OffsetPoint(num10, ref k3, polyNode2.m_jointype); } m_destPolys.Add(m_destPoly); } else { int k4 = 0; for (int num11 = 1; num11 < count - 1; num11++) { OffsetPoint(num11, ref k4, polyNode2.m_jointype); } if (polyNode2.m_endtype == EndType.etOpenButt) { int index = count - 1; IntPoint item = new IntPoint(Round((double)m_srcPoly[index].X + m_normals[index].X * delta), Round((double)m_srcPoly[index].Y + m_normals[index].Y * delta)); m_destPoly.Add(item); item = new IntPoint(Round((double)m_srcPoly[index].X - m_normals[index].X * delta), Round((double)m_srcPoly[index].Y - m_normals[index].Y * delta)); m_destPoly.Add(item); } else { int num12 = count - 1; k4 = count - 2; m_sinA = 0.0; m_normals[num12] = new DoublePoint(0.0 - m_normals[num12].X, 0.0 - m_normals[num12].Y); if (polyNode2.m_endtype == EndType.etOpenSquare) { DoSquare(num12, k4); } else { DoRound(num12, k4); } } for (int num13 = count - 1; num13 > 0; num13--) { m_normals[num13] = new DoublePoint(0.0 - m_normals[num13 - 1].X, 0.0 - m_normals[num13 - 1].Y); } m_normals[0] = new DoublePoint(0.0 - m_normals[1].X, 0.0 - m_normals[1].Y); k4 = count - 1; for (int num14 = k4 - 1; num14 > 0; num14--) { OffsetPoint(num14, ref k4, polyNode2.m_jointype); } if (polyNode2.m_endtype == EndType.etOpenButt) { IntPoint item = new IntPoint(Round((double)m_srcPoly[0].X - m_normals[0].X * delta), Round((double)m_srcPoly[0].Y - m_normals[0].Y * delta)); m_destPoly.Add(item); item = new IntPoint(Round((double)m_srcPoly[0].X + m_normals[0].X * delta), Round((double)m_srcPoly[0].Y + m_normals[0].Y * delta)); m_destPoly.Add(item); } else { k4 = 1; m_sinA = 0.0; if (polyNode2.m_endtype == EndType.etOpenSquare) { DoSquare(0, 1); } else { DoRound(0, 1); } } m_destPolys.Add(m_destPoly); } } } } } }
private void RecursiveDrawPolytree(PolyNode tree, Color drawColor,Matrix4x4 matrix) { if (tree == null) return; DrawPointListLine(tree.Contour, drawColor, matrix, true); foreach (PolyNode cTree in tree.Childs) { RecursiveDrawPolytree(cTree, drawColor, matrix); } }
//------------------------------------------------------------------------------ public static void AddPolyNodeToPolygons(PolyNode polynode, Polygons polygons) { if (polynode.Contour.Count > 0) polygons.Add(polynode.Contour); foreach (PolyNode pn in polynode.Childs) AddPolyNodeToPolygons(pn, polygons); }
void SearchTree(InputGeometry inputGeometry, ref int pointIndex, PolyNode node) { foreach (PolyNode childNode in node.Childs) { int startIndex = pointIndex; foreach (ControlPoint point in childNode.Contour) { inputGeometry.AddPoint(point.X, point.Y); if (pointIndex > startIndex) inputGeometry.AddSegment(pointIndex - 1, pointIndex); pointIndex++; } inputGeometry.AddSegment(pointIndex - 1, startIndex); if (childNode.IsHole) { for (int i = 0, j = childNode.Contour.Count - 1, k = childNode.Contour.Count - 2; i < childNode.Contour.Count; k = j, j = i, i++) { ControlPoint a1 = childNode.Contour[k]; ControlPoint a2 = childNode.Contour[j]; ControlPoint a3 = childNode.Contour[i]; if (ControlPoint.VectorProduct(a2 - a1, a3 - a1) < 0) { ControlPoint c = ((a1 + a3) / 2) - a2; double x = 2; ControlPoint hole; do { x /= 2; hole = a2 + (c * x); } while (!IsInside(childNode, hole)); inputGeometry.AddHole(hole.X, hole.Y); break; } } } SearchTree(inputGeometry, ref pointIndex, childNode); } }
bool IsInside(PolyNode node, ControlPoint point) { foreach (PolyNode childNode in node.Childs) if (Contains(childNode.Contour, point)) return false; return Contains(node.Contour, point); }
static void SearchTree(InputGeometry inputGeometry, ref int pointIndex, PolyNode node) { foreach (PolyNode childNode in node.Childs) { int startIndex = pointIndex; foreach (Vector2 point in childNode.Contour) { inputGeometry.AddPoint(point.X, point.Y); if (pointIndex > startIndex) inputGeometry.AddSegment(pointIndex - 1, pointIndex); pointIndex++; } inputGeometry.AddSegment(pointIndex - 1, startIndex); if (childNode.IsHole) { for (int i = 0, j = childNode.Contour.Count - 1, k = childNode.Contour.Count - 2; i < childNode.Contour.Count; k = j, j = i, i++) { Vector2 a1 = childNode.Contour[k]; Vector2 a2 = childNode.Contour[j]; Vector2 a3 = childNode.Contour[i]; if (Vector2.VectorProduct(a2 - a1, a3 - a1) < 0) { Vector2 c = (a1 + a3) / 2; Vector2 d = a2 - c; float x = c.Length * 2; Vector2 hole; do { x /= 2; hole = c + (1 - x) * d; } while (!IsInside(childNode, hole)); x /= 512; hole = c + (1 - x) * d; inputGeometry.AddHole(hole.X, hole.Y); break; } } } SearchTree(inputGeometry, ref pointIndex, childNode); } }
static bool IsInside(PolyNode node, Vector2 point) { foreach (PolyNode childNode in node.Childs) { var polygon = new Polygon(childNode.Contour); if (polygon.Contains(point)) return false; } return new Polygon(node.Contour).Contains(point); }
static void TransformRecursiveley(PolyNode node, Matrix2x3 matrix) { foreach (PolyNode childNode in node.Childs) { childNode.Contour = matrix.ApplyTo(childNode.Contour).ToList(); TransformRecursiveley(childNode, matrix); } }
//------------------------------------------------------------------------------ internal static void AddPolyNodeToPaths(PolyNode polynode, NodeType nt, Paths paths) { bool match = true; switch (nt) { case NodeType.ntOpen: return; case NodeType.ntClosed: match = !polynode.IsOpen; break; default: break; } if (polynode.Contour.Count > 0 && match) paths.Add(polynode.Contour); foreach (PolyNode pn in polynode.Childs) AddPolyNodeToPaths(pn, nt, paths); }
//------------------------------------------------------------------------------ private void BuildResult2(PolyTree polytree) { polytree.Clear(); //add each output polygon/contour to polytree ... polytree.m_AllPolys.Capacity = m_PolyOuts.Count; for (int i = 0; i < m_PolyOuts.Count; i++) { OutRec outRec = m_PolyOuts[i]; int cnt = PointCount(outRec.pts); if (cnt < 3) continue; FixHoleLinkage(outRec); PolyNode pn = new PolyNode(); polytree.m_AllPolys.Add(pn); outRec.polyNode = pn; pn.m_polygon.Capacity = cnt; OutPt op = outRec.pts; for (int j = 0; j < cnt; j++) { pn.m_polygon.Add(op.pt); op = op.prev; } } //fixup PolyNode links etc ... polytree.m_Childs.Capacity = m_PolyOuts.Count; for (int i = 0; i < m_PolyOuts.Count; i++) { OutRec outRec = m_PolyOuts[i]; if (outRec.polyNode == null) continue; if (outRec.FirstLeft == null) polytree.AddChild(outRec.polyNode); else outRec.FirstLeft.polyNode.AddChild(outRec.polyNode); } }
private void DoOffset(double delta) { m_destPolys = new List <List <IntPoint> >(); m_delta = delta; if (ClipperBase.near_zero(delta)) { m_destPolys.Capacity = m_polyNodes.ChildCount; for (int i = 0; i < m_polyNodes.ChildCount; i++) { PolyNode polyNode = m_polyNodes.Childs[i]; if (polyNode.m_endtype == EndType.etClosedPolygon) { m_destPolys.Add(polyNode.m_polygon); } } return; } if (MiterLimit > 2.0) { m_miterLim = 2.0 / (MiterLimit * MiterLimit); } else { m_miterLim = 0.5; } double num = (ArcTolerance <= 0.0) ? 0.25 : ((!(ArcTolerance > Math.Abs(delta) * 0.25)) ? ArcTolerance : (Math.Abs(delta) * 0.25)); double num2 = 3.1415926535897931 / Math.Acos(1.0 - num / Math.Abs(delta)); m_sin = Math.Sin(6.2831853071795862 / num2); m_cos = Math.Cos(6.2831853071795862 / num2); m_StepsPerRad = num2 / 6.2831853071795862; if (delta < 0.0) { m_sin = 0.0 - m_sin; } m_destPolys.Capacity = m_polyNodes.ChildCount * 2; IntPoint item = default(IntPoint); for (int j = 0; j < m_polyNodes.ChildCount; j++) { PolyNode polyNode2 = m_polyNodes.Childs[j]; m_srcPoly = polyNode2.m_polygon; int count = m_srcPoly.Count; if (count == 0 || (delta <= 0.0 && (count < 3 || polyNode2.m_endtype != 0))) { continue; } m_destPoly = new List <IntPoint>(); if (count == 1) { if (polyNode2.m_jointype == JoinType.jtRound) { double num3 = 1.0; double num4 = 0.0; for (int k = 1; (double)k <= num2; k++) { List <IntPoint> destPoly = m_destPoly; IntPoint intPoint = m_srcPoly[0]; long x = Round((double)intPoint.X + num3 * delta); IntPoint intPoint2 = m_srcPoly[0]; destPoly.Add(new IntPoint(x, Round((double)intPoint2.Y + num4 * delta))); double num5 = num3; num3 = num3 * m_cos - m_sin * num4; num4 = num5 * m_sin + num4 * m_cos; } } else { double num6 = -1.0; double num7 = -1.0; for (int l = 0; l < 4; l++) { List <IntPoint> destPoly2 = m_destPoly; IntPoint intPoint3 = m_srcPoly[0]; long x2 = Round((double)intPoint3.X + num6 * delta); IntPoint intPoint4 = m_srcPoly[0]; destPoly2.Add(new IntPoint(x2, Round((double)intPoint4.Y + num7 * delta))); if (num6 < 0.0) { num6 = 1.0; } else if (num7 < 0.0) { num7 = 1.0; } else { num6 = -1.0; } } } m_destPolys.Add(m_destPoly); continue; } m_normals.Clear(); m_normals.Capacity = count; for (int m = 0; m < count - 1; m++) { m_normals.Add(GetUnitNormal(m_srcPoly[m], m_srcPoly[m + 1])); } if (polyNode2.m_endtype == EndType.etClosedLine || polyNode2.m_endtype == EndType.etClosedPolygon) { m_normals.Add(GetUnitNormal(m_srcPoly[count - 1], m_srcPoly[0])); } else { m_normals.Add(new DoublePoint(m_normals[count - 2])); } if (polyNode2.m_endtype == EndType.etClosedPolygon) { int k2 = count - 1; for (int n = 0; n < count; n++) { OffsetPoint(n, ref k2, polyNode2.m_jointype); } m_destPolys.Add(m_destPoly); continue; } if (polyNode2.m_endtype == EndType.etClosedLine) { int k3 = count - 1; for (int num8 = 0; num8 < count; num8++) { OffsetPoint(num8, ref k3, polyNode2.m_jointype); } m_destPolys.Add(m_destPoly); m_destPoly = new List <IntPoint>(); DoublePoint doublePoint = m_normals[count - 1]; for (int num9 = count - 1; num9 > 0; num9--) { List <DoublePoint> normals = m_normals; int index = num9; DoublePoint doublePoint2 = m_normals[num9 - 1]; double x3 = 0.0 - doublePoint2.X; DoublePoint doublePoint3 = m_normals[num9 - 1]; normals[index] = new DoublePoint(x3, 0.0 - doublePoint3.Y); } m_normals[0] = new DoublePoint(0.0 - doublePoint.X, 0.0 - doublePoint.Y); k3 = 0; for (int num10 = count - 1; num10 >= 0; num10--) { OffsetPoint(num10, ref k3, polyNode2.m_jointype); } m_destPolys.Add(m_destPoly); continue; } int k4 = 0; for (int num11 = 1; num11 < count - 1; num11++) { OffsetPoint(num11, ref k4, polyNode2.m_jointype); } if (polyNode2.m_endtype == EndType.etOpenButt) { int index2 = count - 1; IntPoint intPoint5 = m_srcPoly[index2]; double num12 = intPoint5.X; DoublePoint doublePoint4 = m_normals[index2]; long x4 = Round(num12 + doublePoint4.X * delta); IntPoint intPoint6 = m_srcPoly[index2]; double num13 = intPoint6.Y; DoublePoint doublePoint5 = m_normals[index2]; item = new IntPoint(x4, Round(num13 + doublePoint5.Y * delta)); m_destPoly.Add(item); IntPoint intPoint7 = m_srcPoly[index2]; double num14 = intPoint7.X; DoublePoint doublePoint6 = m_normals[index2]; long x5 = Round(num14 - doublePoint6.X * delta); IntPoint intPoint8 = m_srcPoly[index2]; double num15 = intPoint8.Y; DoublePoint doublePoint7 = m_normals[index2]; item = new IntPoint(x5, Round(num15 - doublePoint7.Y * delta)); m_destPoly.Add(item); } else { int num16 = count - 1; k4 = count - 2; m_sinA = 0.0; List <DoublePoint> normals2 = m_normals; int index3 = num16; DoublePoint doublePoint8 = m_normals[num16]; double x6 = 0.0 - doublePoint8.X; DoublePoint doublePoint9 = m_normals[num16]; normals2[index3] = new DoublePoint(x6, 0.0 - doublePoint9.Y); if (polyNode2.m_endtype == EndType.etOpenSquare) { DoSquare(num16, k4); } else { DoRound(num16, k4); } } for (int num17 = count - 1; num17 > 0; num17--) { List <DoublePoint> normals3 = m_normals; int index4 = num17; DoublePoint doublePoint10 = m_normals[num17 - 1]; double x7 = 0.0 - doublePoint10.X; DoublePoint doublePoint11 = m_normals[num17 - 1]; normals3[index4] = new DoublePoint(x7, 0.0 - doublePoint11.Y); } List <DoublePoint> normals4 = m_normals; DoublePoint doublePoint12 = m_normals[1]; double x8 = 0.0 - doublePoint12.X; DoublePoint doublePoint13 = m_normals[1]; normals4[0] = new DoublePoint(x8, 0.0 - doublePoint13.Y); k4 = count - 1; for (int num18 = k4 - 1; num18 > 0; num18--) { OffsetPoint(num18, ref k4, polyNode2.m_jointype); } if (polyNode2.m_endtype == EndType.etOpenButt) { IntPoint intPoint9 = m_srcPoly[0]; double num19 = intPoint9.X; DoublePoint doublePoint14 = m_normals[0]; long x9 = Round(num19 - doublePoint14.X * delta); IntPoint intPoint10 = m_srcPoly[0]; double num20 = intPoint10.Y; DoublePoint doublePoint15 = m_normals[0]; item = new IntPoint(x9, Round(num20 - doublePoint15.Y * delta)); m_destPoly.Add(item); IntPoint intPoint11 = m_srcPoly[0]; double num21 = intPoint11.X; DoublePoint doublePoint16 = m_normals[0]; long x10 = Round(num21 + doublePoint16.X * delta); IntPoint intPoint12 = m_srcPoly[0]; double num22 = intPoint12.Y; DoublePoint doublePoint17 = m_normals[0]; item = new IntPoint(x10, Round(num22 + doublePoint17.Y * delta)); m_destPoly.Add(item); } else { k4 = 1; m_sinA = 0.0; if (polyNode2.m_endtype == EndType.etOpenSquare) { DoSquare(0, 1); } else { DoRound(0, 1); } } m_destPolys.Add(m_destPoly); } }
private static void ProcessPolyTreeNodeIntoSeparatIslands(this Polygons polygonsIn, PolyNode node, List<Polygons> ret) { for (int n = 0; n < node.ChildCount; n++) { PolyNode child = node.Childs[n]; Polygons polygons = new Polygons(); polygons.Add(child.Contour); for (int i = 0; i < child.ChildCount; i++) { polygons.Add(child.Childs[i].Contour); polygonsIn.ProcessPolyTreeNodeIntoSeparatIslands(child.Childs[i], ret); } ret.Add(polygons); } }
public void AddPath(List <IntPoint> path, JoinType joinType, EndType endType) { int num = path.Count - 1; if (num < 0) { return; } PolyNode polyNode = new PolyNode(); polyNode.m_jointype = joinType; polyNode.m_endtype = endType; if (endType == EndType.etClosedLine || endType == EndType.etClosedPolygon) { while (num > 0 && path[0] == path[num]) { num--; } } polyNode.m_polygon.Capacity = num + 1; polyNode.m_polygon.Add(path[0]); int num2 = 0; int num3 = 0; for (int i = 1; i <= num; i++) { if (!(polyNode.m_polygon[num2] != path[i])) { continue; } num2++; polyNode.m_polygon.Add(path[i]); IntPoint intPoint = path[i]; long y = intPoint.Y; IntPoint intPoint2 = polyNode.m_polygon[num3]; if (y <= intPoint2.Y) { IntPoint intPoint3 = path[i]; long y2 = intPoint3.Y; IntPoint intPoint4 = polyNode.m_polygon[num3]; if (y2 != intPoint4.Y) { continue; } IntPoint intPoint5 = path[i]; long x = intPoint5.X; IntPoint intPoint6 = polyNode.m_polygon[num3]; if (x >= intPoint6.X) { continue; } } num3 = num2; } if ((endType == EndType.etClosedPolygon && num2 < 2) || (endType != 0 && num2 < 0)) { return; } m_polyNodes.AddChild(polyNode); if (endType != 0) { return; } if (m_lowest.X < 0) { m_lowest = new IntPoint(0L, num3); return; } IntPoint intPoint7 = m_polyNodes.Childs[(int)m_lowest.X].m_polygon[(int)m_lowest.Y]; IntPoint intPoint8 = polyNode.m_polygon[num3]; if (intPoint8.Y <= intPoint7.Y) { IntPoint intPoint9 = polyNode.m_polygon[num3]; if (intPoint9.Y != intPoint7.Y) { return; } IntPoint intPoint10 = polyNode.m_polygon[num3]; if (intPoint10.X >= intPoint7.X) { return; } } m_lowest = new IntPoint(m_polyNodes.ChildCount - 1, num3); }
static private void GetAreasRecursive(PolyNode polyTreeForPlate, Polygons discreteAreas) { if (!polyTreeForPlate.IsHole) { discreteAreas.Add(polyTreeForPlate.Contour); } foreach (PolyNode child in polyTreeForPlate.Childs) { GetAreasRecursive(child, discreteAreas); } }
private static List<Polygon> CreatePolygon(PolyNode polyNode) { List<Polygon> polyList = new List<Polygon>(); Debug.Assert(polyNode.IsOpen == false); Debug.Assert(polyNode.IsHole == false); Polygon polygon = GetPolygon(polyNode.Contour); for (int i = 0; i < polyNode.Childs.Count; i++) { if (polyNode.Childs[i].IsHole) { polygon.AddHole(GetPolygon(polyNode.Childs[i].Contour)); } else { polyList.AddRange(CreatePolygon(polyNode.Childs[i])); } } if (Triangulate(polygon)) { polyList.Add(polygon); } return polyList; }