/// <summary> /// Return geometry for a particular representation item. /// </summary> /// <param name="shapeEditScope">The shape edit scope.</param> /// <param name="lcs">Local coordinate system for the geometry, without scale.</param> /// <param name="scaledLcs">Local coordinate system for the geometry, including scale, potentially non-uniform.</param> /// <param name="guid">The guid of an element for which represntation is being created.</param> /// <returns>The created geometry.</returns> /// <remarks>As this doesn't inherit from IfcSolidModel, this is a non-virtual CreateGeometry function.</remarks> protected IList<GeometryObject> CreateGeometry(IFCImportShapeEditScope shapeEditScope, Transform lcs, Transform scaledLcs, string guid) { if (Shells.Count == 0) return null; IList<GeometryObject> geomObjs = null; using (BuilderScope bs = shapeEditScope.InitializeBuilder(IFCShapeBuilderType.TessellatedShapeBuilder)) { TessellatedShapeBuilderScope tsBuilderScope = bs as TessellatedShapeBuilderScope; tsBuilderScope.StartCollectingFaceSet(); foreach (IFCConnectedFaceSet faceSet in Shells) faceSet.CreateShape(shapeEditScope, lcs, scaledLcs, guid); geomObjs = tsBuilderScope.CreateGeometry(guid); } if (geomObjs == null || geomObjs.Count == 0) return null; return geomObjs; }
/// <summary> /// Return geometry for a particular representation item. /// </summary> /// <param name="shapeEditScope">The shape edit scope.</param> /// <param name="lcs">Local coordinate system for the geometry, without scale.</param> /// <param name="scaledLcs">Local coordinate system for the geometry, including scale, potentially non-uniform.</param> /// <param name="guid">The guid of an element for which represntation is being created.</param> /// <returns>The created geometry.</returns> /// <remarks>As this doesn't inherit from IfcSolidModel, this is a non-virtual CreateSolid function.</remarks> protected IList<GeometryObject> CreateGeometry( IFCImportShapeEditScope shapeEditScope, Transform lcs, Transform scaledLcs, string guid) { if (Shells.Count == 0) return null; IList<GeometryObject> geomObjs = null; int numExpectedFaces = 0; foreach (IFCConnectedFaceSet faceSet in Shells) { numExpectedFaces += faceSet.Faces.Count; } // We are going to start by trying to create a Solid, even if we are passed a shell-based model, since we can frequently // do so. However, if we have even one missing face, we'll loosen the requirements and revert to mesh only. for (int pass = 0; pass < 2; pass++) { IFCImportShapeEditScope.BuildPreferenceType target = (pass == 0) ? IFCImportShapeEditScope.BuildPreferenceType.AnyGeometry : IFCImportShapeEditScope.BuildPreferenceType.AnyMesh; using (IFCImportShapeEditScope.BuildPreferenceSetter setter = new IFCImportShapeEditScope.BuildPreferenceSetter(shapeEditScope, target)) { using (BuilderScope bs = shapeEditScope.InitializeBuilder(IFCShapeBuilderType.TessellatedShapeBuilder)) { TessellatedShapeBuilderScope tsBuilderScope = shapeEditScope.BuilderScope as TessellatedShapeBuilderScope; tsBuilderScope.StartCollectingFaceSet(); foreach (IFCConnectedFaceSet faceSet in Shells) { faceSet.CreateShape(shapeEditScope, lcs, scaledLcs, guid); } // If we are on our first pass, try again. If we are on our second pass, warn and create the best geometry we can. if (tsBuilderScope.CreatedFacesCount != numExpectedFaces) { if (pass == 0) continue; Importer.TheLog.LogWarning (Id, "Processing " + tsBuilderScope.CreatedFacesCount + " valid faces out of " + numExpectedFaces + " total.", false); } geomObjs = tsBuilderScope.CreateGeometry(guid); WarnOnTooFewCreatedFaces(geomObjs, numExpectedFaces); break; } } } if (geomObjs == null || geomObjs.Count == 0) { if (numExpectedFaces != 0) { Importer.TheLog.LogError (Id, "No valid geometry found. This may be due to slivery triangles or other similar geometric issues.", false); return null; } } return geomObjs; }
/// <summary> /// Return geometry for a particular representation item. /// </summary> /// <param name="shapeEditScope">The shape edit scope.</param> /// <param name="lcs">Local coordinate system for the geometry, without scale.</param> /// <param name="scaledLcs">Local coordinate system for the geometry, including scale, potentially non-uniform.</param> /// <param name="guid">The guid of an element for which represntation is being created.</param> /// <returns>The created geometry.</returns> protected override IList<GeometryObject> CreateGeometryInternal( IFCImportShapeEditScope shapeEditScope, Transform lcs, Transform scaledLcs, string guid) { if (Outer == null || Outer.Faces.Count == 0) return null; IList<GeometryObject> geomObjs = null; bool canRevertToMesh = false; using (BuilderScope bs = shapeEditScope.InitializeBuilder(IFCShapeBuilderType.TessellatedShapeBuilder)) { TessellatedShapeBuilderScope tsBuilderScope = bs as TessellatedShapeBuilderScope; tsBuilderScope.StartCollectingFaceSet(); Outer.CreateShape(shapeEditScope, lcs, scaledLcs, guid); if (tsBuilderScope.CreatedFacesCount == Outer.Faces.Count) { geomObjs = tsBuilderScope.CreateGeometry(guid); } canRevertToMesh = tsBuilderScope.CanRevertToMesh(); } if (geomObjs == null || geomObjs.Count == 0) { if (canRevertToMesh) { using (IFCImportShapeEditScope.BuildPreferenceSetter setter = new IFCImportShapeEditScope.BuildPreferenceSetter(shapeEditScope, IFCImportShapeEditScope.BuildPreferenceType.AnyMesh)) { using (BuilderScope newBuilderScope = shapeEditScope.InitializeBuilder(IFCShapeBuilderType.TessellatedShapeBuilder)) { TessellatedShapeBuilderScope newTsBuilderScope = newBuilderScope as TessellatedShapeBuilderScope; // Let's see if we can loosen the requirements a bit, and try again. newTsBuilderScope.StartCollectingFaceSet(); Outer.CreateShape(shapeEditScope, lcs, scaledLcs, guid); // This needs to be in scope so that we keep the mesh tolerance for vertices. if (newTsBuilderScope.CreatedFacesCount != 0) { if (newTsBuilderScope.CreatedFacesCount != Outer.Faces.Count) Importer.TheLog.LogWarning (Outer.Id, "Processing " + newTsBuilderScope.CreatedFacesCount + " valid faces out of " + Outer.Faces.Count + " total.", false); geomObjs = newTsBuilderScope.CreateGeometry(guid); } } } } } if (geomObjs == null || geomObjs.Count == 0) { // Couldn't use fallback, or fallback didn't work. Importer.TheLog.LogWarning(Id, "Couldn't create any geometry.", false); return null; } return geomObjs; }
protected override void CreateShapeInternal(IFCImportShapeEditScope shapeEditScope, Transform lcs, Transform scaledLcs, string guid) { using (BuilderScope bs = shapeEditScope.InitializeBuilder(IFCShapeBuilderType.TessellatedShapeBuilder)) { base.CreateShapeInternal(shapeEditScope, lcs, scaledLcs, guid); TessellatedShapeBuilderScope tsBuilderScope = bs as TessellatedShapeBuilderScope; tsBuilderScope.StartCollectingFaceSet(); // Create triangle face set from CoordIndex. We do not support the Normals yet at this point foreach (List<int> triIndex in CoordIndex) { // This is a defensive check in an unlikely situation that the index is larger than the data if (triIndex[0] > Coordinates.CoordList.Count || triIndex[1] > Coordinates.CoordList.Count || triIndex[2] > Coordinates.CoordList.Count) { continue; } tsBuilderScope.StartCollectingFace(GetMaterialElementId(shapeEditScope)); IList<XYZ> loopVertices = new List<XYZ>(); IList<double> v1 = Coordinates.CoordList[triIndex[0] - 1]; IList<double> v2 = Coordinates.CoordList[triIndex[1] - 1]; IList<double> v3 = Coordinates.CoordList[triIndex[2] - 1]; loopVertices.Add(new XYZ(v1[0], v1[1], v1[2])); loopVertices.Add(new XYZ(v2[0], v2[1], v2[2])); loopVertices.Add(new XYZ(v3[0], v3[1], v3[2])); IList<XYZ> transformedVertices = new List<XYZ>(); foreach (XYZ vertex in loopVertices) { // Need to apply the project unit scaling here XYZ scaledVertex = applyProjectUnitScaleVertex(vertex); transformedVertices.Add(scaledLcs.OfPoint(scaledVertex)); } // Check triangle that is too narrow (2 vertices are within the tolerance IList<XYZ> validVertices; IFCGeometryUtil.CheckAnyDistanceVerticesWithinTolerance(Id, shapeEditScope, transformedVertices, out validVertices); // We are going to catch any exceptions if the loop is invalid. // We are going to hope that we can heal the parent object in the TessellatedShapeBuilder. bool bPotentiallyAbortFace = false; int count = validVertices.Count; if (validVertices.Count < 3) { Importer.TheLog.LogComment(Id, "Too few distinct loop vertices (" + count + "), ignoring.", false); bPotentiallyAbortFace = true; } else { if (!tsBuilderScope.AddLoopVertices(Id, validVertices)) bPotentiallyAbortFace = true; } if (bPotentiallyAbortFace) tsBuilderScope.AbortCurrentFace(); else tsBuilderScope.StopCollectingFace(); } IList<GeometryObject> createdGeometries = tsBuilderScope.CreateGeometry(guid); if (createdGeometries != null) { foreach (GeometryObject createdGeometry in createdGeometries) { shapeEditScope.AddGeometry(IFCSolidInfo.Create(Id, createdGeometry)); } } } }