/// <summary> /// Cuts the out front polygon. /// </summary> /// <param name="polyPoints">The poly points.</param> /// <param name="vwiwc">The Vertical Index Classification.</param> /// <param name="points">The points.</param> private static void CutOutFrontPolygon(List <Vector3DIndexClassification> polyPoints, Vector3DIndexClassification vwiwc, List <Vector3D> points) { points.Clear(); var curVW = vwiwc; while (true) { curVW.AlreadyCuttedFront = true; points.Add(curVW.Vector); var curVWPair = polyPoints[curVW.CuttingFrontPairIndex]; if (curVW.CuttingFrontPoint) { if (!curVWPair.AlreadyCuttedFront) { curVW = curVWPair; } else { var curVWPrev = polyPoints[BspTreeBuilder.GetNext(curVW.Index - 1, polyPoints.Count)]; var curVWNext = polyPoints[BspTreeBuilder.GetNext(curVW.Index + 1, polyPoints.Count)]; if ((curVWPrev.Result == ClassifyPointResult.OnFront) && !curVWPrev.AlreadyCuttedFront) { curVW = curVWPrev; } else if ((curVWNext.Result == ClassifyPointResult.OnFront) && !curVWNext.AlreadyCuttedFront) { curVW = curVWNext; } else { return; } } } else { var curPrev = polyPoints[BspTreeBuilder.GetNext(curVW.Index - 1, polyPoints.Count)]; var curNext = polyPoints[BspTreeBuilder.GetNext(curVW.Index + 1, polyPoints.Count)]; if ((curPrev.Result != ClassifyPointResult.OnBack) && !curPrev.AlreadyCuttedFront) { curVW = curPrev; } else if ((curNext.Result != ClassifyPointResult.OnBack) && !curNext.AlreadyCuttedFront) { curVW = curNext; } else { return; } } } }
/// <summary> /// Split the polygon. /// </summary> /// <param name="poly">The Polygon</param> /// <param name="part">The Part</param> /// <param name="backPoly">The Back Polygon</param> /// <param name="frontPoly">The Front Polygon</param> private static void SplitPolygon(Polygon3D poly, Polygon3D part, out Polygon3D[] backPoly, out Polygon3D[] frontPoly) { var backP = new List <Polygon3D>(); var frontP = new List <Polygon3D>(); // this code looks for points which lie on the part plane and divide polygon into two parts if (poly.Points != null) { var polyPoints = new List <Vector3DIndexClassification>(); var backPartPoints = new List <Vector3DIndexClassification>(); var frontPartPoints = new List <Vector3DIndexClassification>(); var outpts = new List <Vector3D>(); var inpts = new List <Vector3D>(); var count = poly.Points.Length; for (var i = 0; i < count; i++) { var ptB = poly.Points[i]; var ptC = poly.Points[BspTreeBuilder.GetNext(i + 1, count)]; var sideB = ClassifyPoint(ptB, part); var sideC = ClassifyPoint(ptC, part); var vwiwcB = new Vector3DIndexClassification(ptB, polyPoints.Count, sideB); polyPoints.Add(vwiwcB); if ((sideB != sideC) && (sideB != ClassifyPointResult.OnPlane) && (sideC != ClassifyPointResult.OnPlane)) { var v = ptB - ptC; var dir = part.Normal * (-part.D) - ptC; var sv = dir & part.Normal; var sect = sv / (part.Normal & v); var ptP = ptC + v * sect; var vwiwc = new Vector3DIndexClassification( ptP, polyPoints.Count, ClassifyPointResult.OnPlane); polyPoints.Add(vwiwc); backPartPoints.Add(vwiwc); frontPartPoints.Add(vwiwc); } else if (sideB == ClassifyPointResult.OnPlane) { var ptA = poly.Points[BspTreeBuilder.GetNext(i - 1, count)]; var sideA = ClassifyPoint(ptA, part); if ((sideA == sideC)) { continue; } if ((sideA != ClassifyPointResult.OnPlane) && (sideC != ClassifyPointResult.OnPlane)) { backPartPoints.Add(vwiwcB); frontPartPoints.Add(vwiwcB); } else if (sideA == ClassifyPointResult.OnPlane) { switch (sideC) { case ClassifyPointResult.OnBack: backPartPoints.Add(vwiwcB); break; case ClassifyPointResult.OnFront: frontPartPoints.Add(vwiwcB); break; } } else if (sideC == ClassifyPointResult.OnPlane) { switch (sideA) { case ClassifyPointResult.OnBack: backPartPoints.Add(vwiwcB); break; case ClassifyPointResult.OnFront: frontPartPoints.Add(vwiwcB); break; } } } } if ((frontPartPoints.Count != 0) || (backPartPoints.Count != 0)) { for (var i = 0; i < backPartPoints.Count - 1; i += 2) { var vwiwc1 = backPartPoints[i]; var vwiwc2 = backPartPoints[i + 1]; vwiwc1.CuttingBackPoint = true; vwiwc2.CuttingBackPoint = true; vwiwc1.CuttingBackPairIndex = vwiwc2.Index; vwiwc2.CuttingBackPairIndex = vwiwc1.Index; } for (var i = 0; i < frontPartPoints.Count - 1; i += 2) { var vwiwc1 = frontPartPoints[i]; var vwiwc2 = frontPartPoints[i + 1]; vwiwc1.CuttingFrontPoint = true; vwiwc2.CuttingFrontPoint = true; vwiwc1.CuttingFrontPairIndex = vwiwc2.Index; vwiwc2.CuttingFrontPairIndex = vwiwc1.Index; } for (var i = 0; i < backPartPoints.Count - 1; i++) { var vwiwc = backPartPoints[i]; if (vwiwc.AlreadyCuttedBack) { continue; } BspTreeBuilder.CutOutBackPolygon(polyPoints, vwiwc, outpts); if (outpts.Count > 2) { var points = outpts.ToArray(); var polygon = new Polygon3D(points, poly); polygon.CalcNormal(points[0], points[1], points[2]); polygon.CalcNormal(); backP.Add(polygon); } } for (var i = 0; i < frontPartPoints.Count - 1; i++) { var vwiwc = frontPartPoints[i]; if (vwiwc.AlreadyCuttedFront) { continue; } BspTreeBuilder.CutOutFrontPolygon(polyPoints, vwiwc, inpts); if (inpts.Count > 2) { var points = inpts.ToArray(); var polygon = new Polygon3D(points, poly); polygon.CalcNormal(points[0], points[1], points[2]); polygon.CalcNormal(); frontP.Add(polygon); } } } } else { backP.Add(poly); frontP.Add(poly); } backPoly = backP.ToArray(); frontPoly = frontP.ToArray(); }
/// <summary> /// Builds the specified collection of polygons. /// </summary> /// <param name="arlist">The collection of polygons.</param> /// <returns>Returns the built <see cref="BspNode"/>.</returns> public BspNode Build(List <Polygon3D> arlist) { if (arlist.Count < 1) { return(null); } var bspNode = new BspNode(); var plane = arlist[0]; bspNode.Plane = plane; var arleft = new List <Polygon3D>(arlist.Count); var arright = new List <Polygon3D>(arlist.Count); for (int i = 1, len = arlist.Count; i < len; i++) { var pln = arlist[i]; if (pln == plane) { continue; } var r = ClassifyPolygon(plane, pln); switch (r) { case ClassifyPolyResult.OnPlane: case ClassifyPolyResult.ToRight: arright.Add(pln); break; case ClassifyPolyResult.ToLeft: arleft.Add(pln); break; case ClassifyPolyResult.Unknown: if (pln is Line3D || pln is UIElement3D) { arleft.Add(pln); } else if (pln is PolyLine3D) { arright.Add(pln); } else { Polygon3D[] ps1, ps2; BspTreeBuilder.SplitPolygon(pln, plane, out ps1, out ps2); arleft.AddRange(ps1); arright.AddRange(ps2); } break; } } if (arleft.Count > 0) { bspNode.Back = this.Build(arleft); } if (arright.Count > 0) { bspNode.Front = this.Build(arright); } return(bspNode); }