/// <summary> /// Creates a simple swept solid from a list of curve loops. /// </summary> /// <param name="exporterIFC">The exporter.</param> /// <param name="profileName">The profile name.</param> /// <param name="profileCurveLoops">The profile curve loops.</param> /// <param name="normal">The normal of the plane that the path lies on.</param> /// <param name="directrix">The path curve.</param> /// <returns>The swept solid handle.</returns> public static IFCAnyHandle CreateSimpleSweptSolid(ExporterIFC exporterIFC, string profileName, IList <CurveLoop> profileCurveLoops, XYZ normal, Curve directrix) { // see definition of IfcSurfaceCurveSweptAreaSolid from // http://www.buildingsmart-tech.org/ifc/IFC2x4/rc4/html/schema/ifcgeometricmodelresource/lexical/ifcsurfacecurvesweptareasolid.htm IFCAnyHandle simpleSweptSolidHnd = null; if (profileCurveLoops.Count == 0) { return(simpleSweptSolidHnd); } IFCFile file = exporterIFC.GetFile(); XYZ startPoint = directrix.get_EndPoint(0); XYZ profilePlaneNormal = null; XYZ profilePlaneXDir = null; XYZ profilePlaneYDir = null; IFCAnyHandle curveHandle = null; double startParam = 0, endParam = 1; Plane scaledReferencePlane = null; if (directrix is Line) { Line line = directrix as Line; startParam = 0.0; endParam = 1.0; profilePlaneNormal = line.Direction; profilePlaneYDir = normal; profilePlaneXDir = profilePlaneNormal.CrossProduct(profilePlaneYDir); XYZ linePlaneNormal = profilePlaneYDir; XYZ linePlaneXDir = profilePlaneXDir; XYZ linePlaneYDir = linePlaneNormal.CrossProduct(linePlaneXDir); XYZ linePlaneOrig = startPoint; scaledReferencePlane = GeometryUtil.CreateScaledPlane(exporterIFC, linePlaneXDir, linePlaneYDir, linePlaneOrig); curveHandle = GeometryUtil.CreateLine(exporterIFC, line, scaledReferencePlane); } else if (directrix is Arc) { Arc arc = directrix as Arc; // profilePlaneXDir is set relative to the startPoint of the directrix. This effectively resets the start parameter to 0.0, and end parameter = length of curve. startParam = 0.0; endParam = (MathUtil.PutInRange(arc.get_EndParameter(1), Math.PI, 2 * Math.PI) - MathUtil.PutInRange(arc.get_EndParameter(0), Math.PI, 2 * Math.PI)) * (180 / Math.PI); profilePlaneNormal = directrix.ComputeDerivatives(0, true).BasisX; profilePlaneXDir = (arc.Center - startPoint).Normalize(); profilePlaneYDir = profilePlaneNormal.CrossProduct(profilePlaneXDir).Normalize(); XYZ arcPlaneNormal = arc.Normal; XYZ arcPlaneXDir = profilePlaneXDir; XYZ arcPlaneYDir = arcPlaneNormal.CrossProduct(arcPlaneXDir); XYZ arcPlaneOrig = startPoint; scaledReferencePlane = GeometryUtil.CreateScaledPlane(exporterIFC, arcPlaneXDir, arcPlaneYDir, arcPlaneOrig); curveHandle = GeometryUtil.CreateArc(exporterIFC, arc, scaledReferencePlane); } else { return(simpleSweptSolidHnd); } IFCAnyHandle referencePlaneAxisHandle = ExporterUtil.CreateAxis(file, scaledReferencePlane.Origin, scaledReferencePlane.Normal, scaledReferencePlane.XVec); IFCAnyHandle referencePlaneHandle = IFCInstanceExporter.CreatePlane(file, referencePlaneAxisHandle); Plane profilePlane = new Plane(profilePlaneXDir, profilePlaneYDir, startPoint); IList <CurveLoop> curveLoops = null; try { // Check that curve loops are valid. curveLoops = ExporterIFCUtils.ValidateCurveLoops(profileCurveLoops, profilePlaneNormal); } catch (Exception) { return(null); } if (curveLoops == null || curveLoops.Count == 0) { return(simpleSweptSolidHnd); } IFCAnyHandle sweptArea = ExtrusionExporter.CreateSweptArea(exporterIFC, profileName, curveLoops, profilePlane, profilePlaneNormal); if (IFCAnyHandleUtil.IsNullOrHasNoValue(sweptArea)) { return(simpleSweptSolidHnd); } profilePlane = GeometryUtil.GetScaledPlane(exporterIFC, profilePlane); IFCAnyHandle solidAxis = ExporterUtil.CreateAxis(file, profilePlane.Origin, profilePlane.Normal, profilePlane.XVec); simpleSweptSolidHnd = IFCInstanceExporter.CreateSurfaceCurveSweptAreaSolid(file, sweptArea, solidAxis, curveHandle, startParam, endParam, referencePlaneHandle); return(simpleSweptSolidHnd); }