protected List <GeometryObject> CreateConformalGeometryIfPossible( IFCImportShapeEditScope shapeEditScope, Transform unscaledLcs) { Transform unscaledSweptDiskPosition = (unscaledLcs == null) ? Transform.Identity : unscaledLcs; IList <CurveLoop> trimmedDirectrices = IFCGeometryUtil.TrimCurveLoops(Id, Directrix, StartParameter, EndParameter); if (trimmedDirectrices == null) { return(null); } List <GeometryObject> myObjs = null; bool isIdentity = unscaledSweptDiskPosition.IsIdentity; foreach (CurveLoop trimmedDirectrix in trimmedDirectrices) { // Create the disk. Curve firstCurve = null; foreach (Curve curve in trimmedDirectrix) { firstCurve = curve; break; } double startParam = 0.0; IList <CurveLoop> profileCurveLoops = CreateProfileCurveLoopsForDirectrix(firstCurve, out startParam); if (profileCurveLoops == null) { return(null); } SolidOptions solidOptions = new SolidOptions(GetMaterialElementId(shapeEditScope), shapeEditScope.GraphicsStyleId); myObjs = new List <GeometryObject>(); try { Solid sweptDiskSolid = GeometryCreationUtilities.CreateSweptGeometry(trimmedDirectrix, 0, startParam, profileCurveLoops, solidOptions); if (!isIdentity) { sweptDiskSolid = SolidUtils.CreateTransformed(sweptDiskSolid, unscaledSweptDiskPosition); } if (sweptDiskSolid != null) { myObjs.Add(sweptDiskSolid); } } catch { return(null); } } return(myObjs); }
/// <summary> /// Return geometry for a particular representation item. /// </summary> /// <param name="shapeEditScope">The geometry creation scope.</param> /// <param name="unscaledLcs">The unscaled local coordinate system for the geometry, if the scaled version isn't supported downstream.</param> /// <param name="scaledLcs">The scaled (true) local coordinate system for the geometry.</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 unscaledLcs, Transform scaledLcs, string guid) { Transform unscaledObjectPosition = (unscaledLcs == null) ? Position : unscaledLcs.Multiply(Position); Transform scaledObjectPosition = (scaledLcs == null) ? Position : scaledLcs.Multiply(Position); IList <CurveLoop> trimmedDirectrices = IFCGeometryUtil.TrimCurveLoops(Id, Directrix, StartParameter, EndParameter); if (trimmedDirectrices == null) { return(null); } IList <GeometryObject> myObjs = null; foreach (CurveLoop trimmedDirectrix in trimmedDirectrices) { double startParam = 0.0; // If the directrix isn't bound, this arbitrary parameter will do. Transform originTrf0 = null; Curve firstCurve0 = trimmedDirectrix.First(); if (firstCurve0.IsBound) { startParam = firstCurve0.GetEndParameter(0); } originTrf0 = firstCurve0.ComputeDerivatives(startParam, false); if (originTrf0 == null) { return(null); } // Note: the computation of the reference Surface Local Transform must be done before the directrix is transform to LCS (because the ref surface isn't) // and therefore the origin is at the start of the curve should be the start of the directrix that lies on the surface. // This is needed to transform the swept area that must be perpendicular to the start of the directrix curve Transform referenceSurfaceLocalTransform = ReferenceSurface.GetTransformAtPoint(originTrf0.Origin); CurveLoop trimmedDirectrixInLCS = IFCGeometryUtil.CreateTransformed(trimmedDirectrix, Id, unscaledObjectPosition, scaledObjectPosition); // Create the sweep. Transform originTrf = null; Curve firstCurve = trimmedDirectrixInLCS.First(); //if (firstCurve.IsBound) // startParam = firstCurve.GetEndParameter(0); originTrf = firstCurve.ComputeDerivatives(startParam, false); Transform unscaledReferenceSurfaceTransform = unscaledObjectPosition.Multiply(referenceSurfaceLocalTransform); Transform scaledReferenceSurfaceTransform = scaledObjectPosition.Multiply(referenceSurfaceLocalTransform); Transform profileCurveLoopsTransform = Transform.CreateTranslation(originTrf.Origin); profileCurveLoopsTransform.BasisX = scaledReferenceSurfaceTransform.BasisZ; profileCurveLoopsTransform.BasisZ = originTrf.BasisX.Normalize(); profileCurveLoopsTransform.BasisY = profileCurveLoopsTransform.BasisZ.CrossProduct(profileCurveLoopsTransform.BasisX); ISet <IList <CurveLoop> > profileCurveLoops = GetTransformedCurveLoops(profileCurveLoopsTransform, profileCurveLoopsTransform); if (profileCurveLoops == null || profileCurveLoops.Count == 0) { return(null); } SolidOptions solidOptions = new SolidOptions(GetMaterialElementId(shapeEditScope), shapeEditScope.GraphicsStyleId); myObjs = new List <GeometryObject>(); foreach (IList <CurveLoop> loops in profileCurveLoops) { GeometryObject myObj = GeometryCreationUtilities.CreateSweptGeometry(trimmedDirectrixInLCS, 0, startParam, loops, solidOptions); if (myObj != null) { myObjs.Add(myObj); } } } return(myObjs); }
/// <summary> /// Return geometry for a particular representation item. /// </summary> /// <param name="shapeEditScope">The geometry creation scope.</param> /// <param name="unscaledLcs">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>Zero or more created geometries.</returns> protected override IList <GeometryObject> CreateGeometryInternal( IFCImportShapeEditScope shapeEditScope, Transform unscaledLcs, Transform scaledLcs, string guid) { List <GeometryObject> myObjs = null; if (scaledLcs == null || scaledLcs.IsConformal && MathUtil.IsAlmostEqual(scaledLcs.Scale, 1.0)) { myObjs = CreateConformalGeometryIfPossible(shapeEditScope, unscaledLcs); if (myObjs != null) { return(myObjs); } } Transform unscaledSweptDiskPosition = (unscaledLcs == null) ? Transform.Identity : unscaledLcs; Transform scaledSweptDiskPosition = (scaledLcs == null) ? Transform.Identity : scaledLcs; IList <CurveLoop> trimmedDirectrices = IFCGeometryUtil.TrimCurveLoops(Id, Directrix, StartParameter, EndParameter); if (trimmedDirectrices == null) { return(null); } foreach (CurveLoop trimmedDirectrix in trimmedDirectrices) { CurveLoop trimmedDirectrixInWCS = IFCGeometryUtil.CreateTransformed(trimmedDirectrix, Id, unscaledSweptDiskPosition, scaledSweptDiskPosition); // Create the disk. Curve firstCurve = null; foreach (Curve curve in trimmedDirectrixInWCS) { firstCurve = curve; break; } double startParam = 0.0; IList <CurveLoop> profileCurveLoops = CreateProfileCurveLoopsForDirectrix(firstCurve, out startParam); if (profileCurveLoops == null) { return(null); } SolidOptions solidOptions = new SolidOptions(GetMaterialElementId(shapeEditScope), shapeEditScope.GraphicsStyleId); myObjs = new List <GeometryObject>(); try { Solid sweptDiskSolid = GeometryCreationUtilities.CreateSweptGeometry(trimmedDirectrixInWCS, 0, startParam, profileCurveLoops, solidOptions); if (sweptDiskSolid != null) { myObjs.Add(sweptDiskSolid); } } catch (Exception ex) { // If we can't create a solid, we will attempt to split the Solid into valid pieces (that will likely have some overlap). if (ex.Message.Contains("self-intersections") || ex.Message.Contains("Failed to create")) { (IList <GeometryObject>, bool)solidSegments = SplitSweptDiskIntoValidPieces(trimmedDirectrixInWCS, profileCurveLoops, solidOptions); if (solidSegments.Item1 != null) { myObjs.AddRange(solidSegments.Item1); } // If Item2 is true, that means that the backup SplitSweptDiskIntoValidPieces routine was // able to create (probably slightly self-intersecting) geometry for all of the pieces // of the directrix. If it is false, then there was some part of the directrix that we // couldn't create geometry for. Log a warning in the first case and an error in the // second. if (solidSegments.Item2) { Importer.TheLog.LogWarning(Id, "The IfcSweptDiskSolid definition does not define a valid solid, likely due to self-intersections or other such problems; the profile probably extends too far toward the inner curvature of the sweep path. Creating the minimum number of solids possible to represent the geometry.", false); } else { Importer.TheLog.LogError(Id, "The IfcSweptDiskSolid definition does not define a valid solid, likely due to self-intersections or other such problems; the profile probably extends too far toward the inner curvature of the sweep path. Creating as much of the geometry as possible.", false); } } else { throw ex; } } } return(myObjs); }
/// <summary> /// Return geometry for a particular representation item. /// </summary> /// <param name="shapeEditScope">The geometry creation scope.</param> /// <param name="unscaledLcs">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>Zero or more created geometries.</returns> protected override IList <GeometryObject> CreateGeometryInternal( IFCImportShapeEditScope shapeEditScope, Transform unscaledLcs, Transform scaledLcs, string guid) { Transform unscaledSweptDiskPosition = (unscaledLcs == null) ? Transform.Identity : unscaledLcs; Transform scaledSweptDiskPosition = (scaledLcs == null) ? Transform.Identity : scaledLcs; IList <CurveLoop> trimmedDirectrices = IFCGeometryUtil.TrimCurveLoops(Id, Directrix, StartParameter, EndParameter); if (trimmedDirectrices == null) { return(null); } List <GeometryObject> myObjs = null; foreach (CurveLoop trimmedDirectrix in trimmedDirectrices) { CurveLoop trimmedDirectrixInWCS = IFCGeometryUtil.CreateTransformed(trimmedDirectrix, Id, unscaledSweptDiskPosition, scaledSweptDiskPosition); // Create the disk. Curve firstCurve = null; foreach (Curve curve in trimmedDirectrixInWCS) { firstCurve = curve; break; } double startParam = 0.0; IList <CurveLoop> profileCurveLoops = CreateProfileCurveLoopsForDirectrix(firstCurve, out startParam); if (profileCurveLoops == null) { return(null); } SolidOptions solidOptions = new SolidOptions(GetMaterialElementId(shapeEditScope), shapeEditScope.GraphicsStyleId); myObjs = new List <GeometryObject>(); try { Solid sweptDiskSolid = GeometryCreationUtilities.CreateSweptGeometry(trimmedDirectrixInWCS, 0, startParam, profileCurveLoops, solidOptions); if (sweptDiskSolid != null) { myObjs.Add(sweptDiskSolid); } } catch (Exception ex) { // If we can't create a solid, we will attempt to split the Solid into valid pieces (that will likely have some overlap). if (ex.Message.Contains("self-intersections")) { Importer.TheLog.LogWarning(Id, "The IfcSweptDiskSolid definition does not define a valid solid, likely due to self-intersections or other such problems; the profile probably extends too far toward the inner curvature of the sweep path. Creating the minimum number of solids possible to represent the geometry.", false); myObjs.AddRange(SplitSweptDiskIntoValidPieces(trimmedDirectrixInWCS, profileCurveLoops, solidOptions)); } else { throw ex; } } } return(myObjs); }