public override IEnumerator <Triangle> GetEnumerator() { PartClassification classes = Classify(this.Original, this.OriginalMesh2); foreach (var tri in classes.BInsideA.Concat(classes.AInsideB)) { yield return(tri); } }
// Classify parts of a solid as inside or outside another protected static PartClassification Classify(IMesh a, IMesh b) { // 0. Initialize intersection list List <List <Line3> > acuts = new List <List <Line3> >(); List <List <Line3> > bcuts = new List <List <Line3> >(); foreach (Triangle atri in a) { acuts.Add(new List <Line3>()); } foreach (Triangle btri in b) { bcuts.Add(new List <Line3>()); } // 1. Determine intersection lines O(N^2) Line3 hit; // Iterate over Solid A int k = 0; foreach (Triangle atri in a) { // Create cut list for this triangle in A List <Line3> atriCuts = acuts[k++]; int j = 0; // Iterate over Solid b foreach (Triangle btri in b) { // Create cut list for this triangle in B List <Line3> btriCuts = bcuts[j++]; // Check if A & B intersect at these triangles if (atri.Intersection(btri, out hit)) { // Add line as a cut line for both triangles atriCuts.Add(hit); btriCuts.Add(hit); } } } // 2. Split a mesh based on intersection lines O(2N) List <Triangle> SplitA = new List <Triangle>(); List <Triangle> SplitB = new List <Triangle>(); int i = 0; foreach (Triangle tri in a) { SplitA.AddRange(Cut(tri, acuts[i++])); } i = 0; foreach (Triangle tri in b) { SplitB.AddRange(Cut(tri, bcuts[i++])); } // 3. Classify triangles as AInsideB, AOutsideB, BInsideA, BOutsideA O(2N) // - you can use raycast (any dir) to determine if inside (odd hits) vs outside (even hits) PartClassification parts = new PartClassification(); foreach (Triangle tri in SplitA) { Ray ray = new Ray(tri.Centre, tri.Normal); if (ray.CastAll(b).Count % 2 == 0) { // Even - Outside parts.AOutsideB.Add(tri); } else { // Odd - Inside parts.AInsideB.Add(tri); } } foreach (Triangle tri in SplitB) { Ray ray = new Ray(tri.Centre, tri.Normal); if (ray.CastAll(a).Count % 2 == 0) { // Even - Outside parts.BOutsideA.Add(tri); } else { // Odd - Inside parts.BInsideA.Add(tri); } } // 4. Return classifications return(parts); }