private void AddFaceToTessellatedShapeBuilder(TessellatedFace theFace) { TessellatedShapeBuilder.AddFace(theFace); TessellatedFaceBoundary.Clear(); FaceMaterialId = ElementId.InvalidElementId; CreatedFacesCount++; }
/// <summary> /// Start collecting edges for a face to create a BRep solid. /// </summary> /// <param name="materialId">The material id of the face.</param> /// <param name="canTriangulate">Whether we can delay processing bad boundary data.</param> public void StartCollectingFace(ElementId materialId, bool canTriangulate) { if (TessellatedShapeBuilder == null) { throw new InvalidOperationException("StartCollectingFaceSet has not been called."); } if (TessellatedFaceBoundary == null) { TessellatedFaceBoundary = new List <IList <XYZ> >(); } else { TessellatedFaceBoundary.Clear(); } if (TessellatedFaceVertices == null) { TessellatedFaceVertices = new IFCFuzzyXYZSet(GetVertexTolerance()); } DelayedFaceBoundary = null; CanProcessDelayedFaceBoundary = canTriangulate; FaceMaterialId = materialId; }
/// <summary> /// Remove the current invalid face from the list of faces to create a BRep solid. /// </summary> override public void AbortCurrentFace() { if (TessellatedFaceBoundary != null) { TessellatedFaceBoundary.Clear(); } FaceMaterialId = ElementId.InvalidElementId; }
private void AddFaceToTessellatedShapeBuilder(TessellatedFace theFace, bool extraFace) { TessellatedShapeBuilder.AddFace(theFace); TessellatedFaceBoundary.Clear(); FaceMaterialId = ElementId.InvalidElementId; if (extraFace) { ExtraCreatedFacesCount++; } else { CreatedFacesCount++; } }
/// <summary> /// Stop collecting faces to create a BRep solid. /// </summary> public void StopCollectingFaceSet() { if (TessellatedShapeBuilder == null) { throw new InvalidOperationException("StartCollectingFaceSet has not been called."); } TessellatedShapeBuilder.CloseConnectedFaceSet(); if (TessellatedFaceBoundary != null) { TessellatedFaceBoundary.Clear(); } if (TessellatedFaceVertices != null) { TessellatedFaceVertices.Clear(); } FaceMaterialId = ElementId.InvalidElementId; }
/// <summary> /// Start collecting faces to create a BRep solid. /// </summary> public void StartCollectingFaceSet() { if (TessellatedShapeBuilder == null) { TessellatedShapeBuilder = new TessellatedShapeBuilder(); } TessellatedShapeBuilder.OpenConnectedFaceSet(false); ResetCreatedFacesCount(); if (TessellatedFaceVertices != null) { TessellatedFaceVertices.Clear(); } if (TessellatedFaceBoundary != null) { TessellatedFaceBoundary.Clear(); } FaceMaterialId = ElementId.InvalidElementId; }
/// <summary> /// Add one loop of vertices that will define a boundary loop of the current face. /// </summary> /// <param name="id">The id of the IFCEntity, for error reporting.</param> /// <param name="loopVertices">The list of vertices.</param> /// <returns>True if the operation succeeded, false oherwise.</returns> public bool AddLoopVertices(int id, List <XYZ> loopVertices) { int vertexCount = (loopVertices == null) ? 0 : loopVertices.Count; if (vertexCount < 3) { Importer.TheLog.LogComment(id, "Too few distinct loop vertices, ignoring.", false); return(false); } List <XYZ> adjustedLoopVertices = null; IList <Tuple <int, int> > interiorLoops = null; int numOuterCreated = 0; bool succeeded = false; for (int pass = 0; pass < 2 && !succeeded; pass++) { // If we have AnyGeometry as a target, we are using Solid tolerances on a first pass. // If that would fail, try again using Mesh tolerances. if (pass == 1 && !RevertToMeshIfPossible()) { break; } succeeded = true; // numOuterCreated is the size of the main "outer" loop after removing duplicates // and self-intersecting loops. In all valid cases, numOuterCreated = numTotalCreated. numOuterCreated = 0; // The total number of non-duplicate loops. This can differ if we are trying to create // a solid vs. a mesh. int numTotalCreated = 0; // The vertices of the main (presumably outer) loop. adjustedLoopVertices = new List <XYZ>(); // The list of vertices of the self-intersecting loops. // Note that we will check that the self-interecting loops do not themselves self-intersect. interiorLoops = new List <Tuple <int, int> >(); int lastInteriorLoopIndex = -1; IDictionary <XYZ, int> createdVertices = new SortedDictionary <XYZ, int>(new IFCXYZFuzzyComparer(GetVertexTolerance())); for (int ii = 0; ii < vertexCount; ii++) { XYZ loopVertex = loopVertices[ii]; int createdVertexIndex = -1; if (createdVertices.TryGetValue(loopVertex, out createdVertexIndex)) { // We will allow the first and last point to be equivalent, or the current and last point. Otherwise we will throw. if (((createdVertexIndex == 0) && (ii == vertexCount - 1)) || (createdVertexIndex == numTotalCreated - 1)) { continue; } // If we have a real self-intersection, mark the loop created by the intersection // for removal later. if (loopVertex.DistanceTo(loopVertices[createdVertexIndex]) < MathUtil.SmallGap()) { if (lastInteriorLoopIndex > createdVertexIndex) { // The interior loops overlap; this is probably too much to try to fix. succeeded = false; break; } // Sorted in reverse order so we can more easily create the interior loops later. int numToRemove = ii - createdVertexIndex; interiorLoops.Insert(0, Tuple.Create(createdVertexIndex, numToRemove)); lastInteriorLoopIndex = ii; numOuterCreated -= numToRemove; continue; } // Note that if pass == 1, CanRevertToMesh will be false. if (!CanRevertToMesh()) { Importer.TheLog.LogWarning(id, "Loop is self-intersecting, truncating.", false); } succeeded = false; break; } XYZ adjustedXYZ = TessellatedFaceVertices.FindOrAdd(loopVertex); adjustedLoopVertices.Add(adjustedXYZ); createdVertices[adjustedXYZ] = numTotalCreated; numTotalCreated++; numOuterCreated++; } if (numOuterCreated < 3) { succeeded = false; } } // Checking start and end points should be covered above. if (numOuterCreated < 3) { Importer.TheLog.LogComment(id, "Loop has less than 3 distinct vertices, ignoring.", false); return(false); } // Remove the interior loops from the loop boundary, in reverse order, and add them // to the tessellated face boundary. foreach (Tuple <int, int> interiorLoop in interiorLoops) { int startIndex = interiorLoop.Item1; int count = interiorLoop.Item2; if (count >= 3) { TessellatedFaceBoundary.Add(loopVertices.GetRange(startIndex, count)); } adjustedLoopVertices.RemoveRange(startIndex, count); } if (interiorLoops.Count > 0) { Importer.TheLog.LogWarning(id, "Loop is self-intersecting, fixing.", false); } TessellatedFaceBoundary.Add(adjustedLoopVertices); return(true); }