/// <summary> /// Modification of set subtract for vector space. /// </summary> /// <param name="pos"></param> /// <param name="neg"></param> /// <param name="intersec"></param> /// <returns></returns> public static List <CSGShape> VectorSetSubtract(List <CSGShape> pos, CSGShape neg, List <CSGShape> intersec = null) { //Look to set subtract algorithm for explinations //The primary difference between this algorithm, and the set subtract algorithm, is that this algorithm passes on correct r values to the output List <CSGShape> outputList = new List <CSGShape>(); Stack <CSGShape> workingStack = new Stack <CSGShape>(pos); while (workingStack.Count > 0) { CSGShape current = workingStack.Pop(); int offendingIndex; var status = CSGPhysics.CalcCollision2D(neg, current, out offendingIndex); if (status == CSGPhysics.CollisionType.BEnclosedInA) { if (intersec != null) { current.rValue += neg.rValue; intersec.Add(current); } } else if (status != CSGPhysics.CollisionType.NotColliding) { IPoly inside, outside; Divide(current, out inside, out outside, neg.GetPoint(offendingIndex), neg.GetSurfaceNormal(offendingIndex), (x, y) => x.Clone(y)); workingStack.Push(new CSGShape(inside, current.rValue)); workingStack.Push(new CSGShape(outside, current.rValue)); } else { outputList.Add(current); } } return(outputList); }
/// <summary> /// Preforms the set subtract operation with multiple pos and a single neg. /// </summary> /// <param name="pos"></param> /// <param name="neg"></param> /// <param name="constructor"></param> /// <returns></returns> public static List <IPoly> SetSubtract(IEnumerable <IPoly> pos, IPoly neg, Func <IPoly, IEnumerable <Vector3>, IPoly> constructor) { //set subtract algorithm //this version works for only 1 negative poly, and is the basis for multiple polys //append all positive polys to a working stack //pop polys from the working stack and compare them to the neg poly //if they intersect, split them, and push them on the working stack //if they are enclosed, remove them from the working list //if they aren't instersecting append them to the output stack //continue until working stack is empty //Initialization List <IPoly> outputList = new List <IPoly>(); Stack <IPoly> workingStack = new Stack <IPoly>(pos); //working stack loop while (workingStack.Count > 0) { //initialization IPoly current = workingStack.Pop(); int offendingIndex; //detect collision status var status = CSGPhysics.CalcCollision2D(neg, current, out offendingIndex); //enclosed, just throw away polygon if (status == CSGPhysics.CollisionType.BEnclosedInA) { continue; } //if colliding, divide the polygon and push them on the working stack else if (status != CSGPhysics.CollisionType.NotColliding) { IPoly inside, outside; Divide(current, out inside, out outside, neg.GetPoint(offendingIndex), neg.GetSurfaceNormal(offendingIndex), constructor); workingStack.Push(inside); workingStack.Push(outside); } //if not colliding, append to output list else { outputList.Add(current); } } return(outputList); }