private IList <CurveLoop> GetTransformedCurveLoopsFromSimpleProfile(IFCSimpleProfile simpleSweptArea, Transform unscaledLcs, Transform scaledLcs) { IList <CurveLoop> loops = new List <CurveLoop>(); // It is legal for simpleSweptArea.Position to be null, for example for IfcArbitraryClosedProfileDef. Transform unscaledSweptAreaPosition = (simpleSweptArea.Position == null) ? unscaledLcs : unscaledLcs.Multiply(simpleSweptArea.Position); Transform scaledSweptAreaPosition = (simpleSweptArea.Position == null) ? scaledLcs : scaledLcs.Multiply(simpleSweptArea.Position); CurveLoop currLoop = simpleSweptArea.OuterCurve; if (currLoop == null || currLoop.Count() == 0) { Importer.TheLog.LogError(simpleSweptArea.Id, "No outer curve loop for profile, ignoring.", false); return(null); } loops.Add(IFCGeometryUtil.CreateTransformed(currLoop, Id, unscaledSweptAreaPosition, scaledSweptAreaPosition)); if (simpleSweptArea.InnerCurves != null) { foreach (CurveLoop innerCurveLoop in simpleSweptArea.InnerCurves) { loops.Add(IFCGeometryUtil.CreateTransformed(innerCurveLoop, Id, unscaledSweptAreaPosition, scaledSweptAreaPosition)); } } return(loops); }
/// <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; CurveLoop trimmedDirectrix = IFCGeometryUtil.TrimCurveLoop(Id, Directrix, StartParameter, EndParameter); if (trimmedDirectrix == null) { return(null); } 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); IList <GeometryObject> 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 = SplitSweptDiskIntoValidPieces(trimmedDirectrixInWCS, profileCurveLoops, solidOptions); } else { throw ex; } } return(myObjs); }
/// <summary> /// Create geometry for an IfcHalfSpaceSolid. /// </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>A list containing one geometry for the IfcHalfSpaceSolid.</returns> protected virtual IList <GeometryObject> CreateGeometryInternal( IFCImportShapeEditScope shapeEditScope, Transform unscaledLcs, Transform scaledLcs, string guid) { IFCPlane ifcPlane = BaseSurface as IFCPlane; Plane plane = ifcPlane.Plane; XYZ origin = plane.Origin; XYZ xVec = plane.XVec; XYZ yVec = plane.YVec; // Set some huge boundaries for now. const double largeCoordinateValue = 100000; XYZ[] corners = new XYZ[4] { unscaledLcs.OfPoint((xVec * -largeCoordinateValue) + (yVec * -largeCoordinateValue) + origin), unscaledLcs.OfPoint((xVec * largeCoordinateValue) + (yVec * -largeCoordinateValue) + origin), unscaledLcs.OfPoint((xVec * largeCoordinateValue) + (yVec * largeCoordinateValue) + origin), unscaledLcs.OfPoint((xVec * -largeCoordinateValue) + (yVec * largeCoordinateValue) + origin) }; IList <CurveLoop> loops = new List <CurveLoop>(); CurveLoop loop = new CurveLoop(); for (int ii = 0; ii < 4; ii++) { if (AgreementFlag) { loop.Append(Line.CreateBound(corners[(5 - ii) % 4], corners[(4 - ii) % 4])); } else { loop.Append(Line.CreateBound(corners[ii], corners[(ii + 1) % 4])); } } loops.Add(loop); XYZ normal = unscaledLcs.OfVector(AgreementFlag ? -plane.Normal : plane.Normal); SolidOptions solidOptions = new SolidOptions(GetMaterialElementId(shapeEditScope), shapeEditScope.GraphicsStyleId); Solid baseSolid = GeometryCreationUtilities.CreateExtrusionGeometry(loops, normal, largeCoordinateValue, solidOptions); if (BaseBoundingCurve != null) { CurveLoop polygonalBoundary = BaseBoundingCurve.CurveLoop; Transform unscaledTotalTransform = unscaledLcs.Multiply(BaseBoundingCurveTransform); Transform scaledTotalTransform = scaledLcs.Multiply(BaseBoundingCurveTransform); // Make sure this bounding polygon extends below base of half-space soild. Transform moveBaseTransform = Transform.Identity; moveBaseTransform.Origin = new XYZ(0, 0, -largeCoordinateValue); unscaledTotalTransform = unscaledTotalTransform.Multiply(moveBaseTransform); scaledTotalTransform = scaledTotalTransform.Multiply(moveBaseTransform); CurveLoop transformedPolygonalBoundary = IFCGeometryUtil.CreateTransformed(polygonalBoundary, Id, unscaledTotalTransform, scaledTotalTransform); IList <CurveLoop> boundingLoops = new List <CurveLoop>(); boundingLoops.Add(transformedPolygonalBoundary); Solid boundingSolid = GeometryCreationUtilities.CreateExtrusionGeometry(boundingLoops, unscaledTotalTransform.BasisZ, 2.0 * largeCoordinateValue, solidOptions); baseSolid = IFCGeometryUtil.ExecuteSafeBooleanOperation(Id, BaseBoundingCurve.Id, baseSolid, boundingSolid, BooleanOperationsType.Intersect, null); } IList <GeometryObject> returnList = new List <GeometryObject>(); returnList.Add(baseSolid); return(returnList); }
/// <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); CurveLoop baseProfileCurve = Directrix.GetCurveLoop(); if (baseProfileCurve == null) { return(null); } CurveLoop trimmedDirectrix = IFCGeometryUtil.TrimCurveLoop(Id, baseProfileCurve, StartParameter, EndParameter); if (trimmedDirectrix == null) { return(null); } 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); IList <GeometryObject> 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="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>Zero or more created geometries.</returns> protected override IList <GeometryObject> CreateGeometryInternal( IFCImportShapeEditScope shapeEditScope, Transform lcs, Transform scaledLcs, string guid) { Transform sweptDiskPosition = (lcs == null) ? Transform.Identity : lcs; CurveLoop baseProfileCurve = Directrix.GetCurveLoop(); if (baseProfileCurve == null) { return(null); } CurveLoop trimmedDirectrix = IFCGeometryUtil.TrimCurveLoop(baseProfileCurve, StartParameter, EndParameter); if (trimmedDirectrix == null) { return(null); } CurveLoop trimmedDirectrixInLCS = IFCGeometryUtil.CreateTransformed(trimmedDirectrix, sweptDiskPosition); // Create the disk. Transform originTrf = null; double startParam = 0.0; // If the directrix isn't bound, this arbitrary parameter will do. foreach (Curve curve in trimmedDirectrixInLCS) { if (curve.IsBound) { startParam = curve.GetEndParameter(0); } originTrf = curve.ComputeDerivatives(startParam, false); break; } if (originTrf == null) { return(null); } // The X-dir of the transform of the start of the directrix will form the normal of the disk. Plane diskPlane = new Plane(originTrf.BasisX, originTrf.Origin); IList <CurveLoop> profileCurveLoops = new List <CurveLoop>(); CurveLoop diskOuterCurveLoop = new CurveLoop(); diskOuterCurveLoop.Append(Arc.Create(diskPlane, Radius, 0, Math.PI)); diskOuterCurveLoop.Append(Arc.Create(diskPlane, Radius, Math.PI, 2.0 * Math.PI)); profileCurveLoops.Add(diskOuterCurveLoop); if (InnerRadius.HasValue) { CurveLoop diskInnerCurveLoop = new CurveLoop(); diskInnerCurveLoop.Append(Arc.Create(diskPlane, InnerRadius.Value, 0, Math.PI)); diskInnerCurveLoop.Append(Arc.Create(diskPlane, InnerRadius.Value, Math.PI, 2.0 * Math.PI)); profileCurveLoops.Add(diskInnerCurveLoop); } SolidOptions solidOptions = new SolidOptions(GetMaterialElementId(shapeEditScope), shapeEditScope.GraphicsStyleId); Solid sweptDiskSolid = GeometryCreationUtilities.CreateSweptGeometry(trimmedDirectrixInLCS, 0, startParam, profileCurveLoops, solidOptions); IList <GeometryObject> myObjs = new List <GeometryObject>(); if (sweptDiskSolid != null) { myObjs.Add(sweptDiskSolid); } return(myObjs); }
/// <summary> /// Return geometry for a particular representation item. /// </summary> /// <param name="shapeEditScope">The geometry creation scope.</param> /// <param name="lcs">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 lcs, Transform scaledLcs, string guid) { Transform objectPosition = (lcs == null) ? Position : lcs.Multiply(Position); CurveLoop baseProfileCurve = Directrix.GetCurveLoop(); if (baseProfileCurve == null) { return(null); } CurveLoop trimmedDirectrix = IFCGeometryUtil.TrimCurveLoop(baseProfileCurve, StartParameter, EndParameter); if (trimmedDirectrix == null) { return(null); } CurveLoop trimmedDirectrixInLCS = IFCGeometryUtil.CreateTransformed(trimmedDirectrix, objectPosition); // Create the sweep. double startParam = 0.0; // If the directrix isn't bound, this arbitrary parameter will do. Transform originTrf = null; Curve firstCurve = trimmedDirectrixInLCS.First(); if (firstCurve.IsBound) { startParam = firstCurve.GetEndParameter(0); } originTrf = firstCurve.ComputeDerivatives(startParam, false); if (originTrf == null) { return(null); } Transform referenceSurfaceLocalTransform = ReferenceSurface.GetTransformAtPoint(originTrf.Origin); Transform referenceSurfaceTransform = objectPosition.Multiply(referenceSurfaceLocalTransform); Transform profileCurveLoopsTransform = Transform.CreateTranslation(originTrf.Origin); profileCurveLoopsTransform.BasisX = referenceSurfaceTransform.BasisZ; profileCurveLoopsTransform.BasisZ = originTrf.BasisX.Normalize(); profileCurveLoopsTransform.BasisY = profileCurveLoopsTransform.BasisZ.CrossProduct(profileCurveLoopsTransform.BasisX); ISet <IList <CurveLoop> > profileCurveLoops = GetTransformedCurveLoops(profileCurveLoopsTransform); if (profileCurveLoops == null || profileCurveLoops.Count == 0) { return(null); } SolidOptions solidOptions = new SolidOptions(GetMaterialElementId(shapeEditScope), shapeEditScope.GraphicsStyleId); IList <GeometryObject> 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); }