public Shell Result() { // the fillets edges fall into one of three categories: // - lengthwayTangential: edges that are tangential to other faces, i.e. they round the other faces // - crossway: edges that connect fillets // - filletEnd: here the fillets end or are otherwise broken up HashSet <Face> lengthwayTangential = new HashSet <Face>(); // the two faces that this fillet rounds HashSet <Edge> crossway = new HashSet <Edge>(); // connection to the following or previous fillet HashSet <Edge> lengthway = new HashSet <Edge>(); // connection between fillet and rounded face HashSet <Edge> filletEnd = new HashSet <Edge>(); // an edge which is the end of a fillet Dictionary <Edge, Face> forking = new Dictionary <Edge, Face>(); // a spherical face, where the fillets fork foreach (Face face in fillets) { if (face.Surface is ISurfaceOfArcExtrusion extrusion) { foreach (Edge edge in face.AllEdgesIterated()) { Face otherFace = edge.OtherFace(face); if (edge.IsTangentialEdge() && edge.Curve2D(face).DirectionAt(0.5).IsMoreHorizontal != extrusion.ExtrusionDirectionIsV) { lengthwayTangential.Add(otherFace); lengthway.Add(edge); } else if (fillets.Contains(otherFace)) { crossway.Add(edge); } else { filletEnd.Add(edge); } } } else if (face.Surface is SphericalSurface) { foreach (Edge edge in face.AllEdgesIterated()) { Face otherFace = edge.OtherFace(face); if (fillets.Contains(otherFace)) { crossway.Add(edge); } } } } Dictionary <Edge, Vertex> crosswayToVertex = new Dictionary <Edge, Vertex>(); Dictionary <Vertex, Vertex> verticesToReplace = new Dictionary <Vertex, Vertex>(); foreach (Edge edg in Extensions.Combine <Edge>(crossway, filletEnd)) { HashSet <Face> involved = edg.Vertex1.InvolvedFaces; involved.UnionWith(edg.Vertex2.InvolvedFaces); involved.ExceptWith(fillets); HashSet <Edge> involvedCrosswayEdges = new HashSet <Edge>(); involvedCrosswayEdges.Add(edg); if (involved.Count < 3) { // maybe the edge is part of a spherical face Face sph = null; if (edg.PrimaryFace.Surface is SphericalSurface && fillets.Contains(edg.PrimaryFace)) { sph = edg.PrimaryFace; } else if (edg.SecondaryFace.Surface is SphericalSurface && fillets.Contains(edg.SecondaryFace)) { sph = edg.SecondaryFace; } if (sph != null) { foreach (Edge spedge in sph.AllEdges) { if (spedge != edg && fillets.Contains(spedge.OtherFace(sph))) { involvedCrosswayEdges.Add(spedge); involved.UnionWith(spedge.Vertex1.InvolvedFaces); involved.UnionWith(spedge.Vertex2.InvolvedFaces); } } } involved.ExceptWith(fillets); } if (involved.Count >= 3) // which should be the case { Face[] ia = involved.ToArray(); GeoPoint ip = edg.Curve3D.PointAt(0.5); if (Surfaces.IntersectThreeSurfaces(ia[0].Surface, ia[0].Domain, ia[1].Surface, ia[1].Domain, ia[2].Surface, ia[2].Domain, ref ip, out GeoPoint2D uv0, out GeoPoint2D uv1, out GeoPoint2D uv2)) { // there should be an intersection point close to the middle of the crossway edge Vertex v = new Vertex(ip); foreach (Edge edge in involvedCrosswayEdges) { crosswayToVertex[edge] = v; verticesToReplace[edge.Vertex1] = v; verticesToReplace[edge.Vertex2] = v; } } else { // maybe two surfaces are identical with different domains: find a common edge ip = edg.Curve3D.PointAt(0.5); bool found = false; for (int i = 0; i < involved.Count - 1; i++) { for (int j = i + 1; j < involved.Count; j++) { IEnumerable <Edge> commonEdges = new HashSet <Edge>(ia[i].AllEdges).Intersect(ia[j].AllEdges); foreach (Edge e in commonEdges) { if (e.IsConnected(edg)) { for (int k = 0; k < involved.Count; k++) { if (k != i && k != j) { ia[k].Surface.Intersect(e.Curve3D, ia[k].Domain, out GeoPoint[] ips, out GeoPoint2D[] uvOnK, out double[] uOnCurve);