/// <summary> /// Creates or updates the IfcLocalPlacement associated with the current origin offset. /// </summary> /// <param name="exporterIFC">The exporter.</param> /// <param name="bbox">The bounding box.</param> /// <param name="ecData">The extrusion creation data which contains the local placement.</param> /// <param name="lpOrig">The local placement origin.</param> /// <param name="unscaledTrfOrig">The unscaled local placement origin.</param> public void CreateLocalPlacementFromOffset(ExporterIFC exporterIFC, BoundingBoxXYZ bbox, IFCExtrusionCreationData ecData, XYZ lpOrig, XYZ unscaledTrfOrig) { if (ecData == null) { return; } IFCAnyHandle localPlacement = ecData.GetLocalPlacement(); if (!IFCAnyHandleUtil.IsNullOrHasNoValue(localPlacement)) { IFCFile file = exporterIFC.GetFile(); // If the BBox passes through (0,0, 0), or no bbox, do nothing. if (bbox == null || ((bbox.Min.X < MathUtil.Eps() && bbox.Max.X > -MathUtil.Eps()) && (bbox.Min.Y < MathUtil.Eps() && bbox.Max.Y > -MathUtil.Eps()) && (bbox.Min.Z < MathUtil.Eps() && bbox.Max.Z > -MathUtil.Eps()))) { if (!ecData.ReuseLocalPlacement) { ecData.SetLocalPlacement(ExporterUtil.CopyLocalPlacement(file, localPlacement)); } return; } if (!MathUtil.IsAlmostZero(unscaledTrfOrig.DotProduct(unscaledTrfOrig))) { if (!ecData.ReuseLocalPlacement) { ecData.SetLocalPlacement(ExporterUtil.CreateLocalPlacement(file, localPlacement, lpOrig, null, null)); } else { IFCAnyHandle relativePlacement = GeometryUtil.GetRelativePlacementFromLocalPlacement(localPlacement); if (IFCAnyHandleUtil.IsNullOrHasNoValue(relativePlacement)) { IFCAnyHandle newRelativePlacement = ExporterUtil.CreateAxis(file, lpOrig, null, null); GeometryUtil.SetRelativePlacement(localPlacement, newRelativePlacement); } else { IFCAnyHandle newOriginHnd = ExporterUtil.CreateCartesianPoint(file, lpOrig); IFCAnyHandleUtil.SetAttribute(relativePlacement, "Location", newOriginHnd); } } } else if (ecData.ForceOffset) { ecData.SetLocalPlacement(ExporterUtil.CreateLocalPlacement(file, localPlacement, null)); } else if (!ecData.ReuseLocalPlacement) { ecData.SetLocalPlacement(ExporterUtil.CopyLocalPlacement(file, localPlacement)); } } }
private static IFCAnyHandle CopyRailingHandle(ExporterIFC exporterIFC, Element elem, ElementId catId, IFCAnyHandle origLocalPlacement, IFCAnyHandle origRailing) { IFCFile file = exporterIFC.GetFile(); IFCAnyHandle origRailingObjectPlacement = IFCAnyHandleUtil.GetInstanceAttribute(origRailing, "ObjectPlacement"); IFCAnyHandle railingRelativePlacement = IFCAnyHandleUtil.GetInstanceAttribute(origRailingObjectPlacement, "RelativePlacement"); IFCAnyHandle parentRelativePlacement = IFCAnyHandleUtil.GetInstanceAttribute(origLocalPlacement, "RelativePlacement"); IFCAnyHandle newRelativePlacement = null; IFCAnyHandle parentRelativeOrig = IFCAnyHandleUtil.GetInstanceAttribute(parentRelativePlacement, "Location"); if (!IFCAnyHandleUtil.IsNullOrHasNoValue(parentRelativeOrig)) { IList <double> parentVec = IFCAnyHandleUtil.GetCoordinates(parentRelativeOrig); IFCAnyHandle railingRelativeOrig = IFCAnyHandleUtil.GetInstanceAttribute(railingRelativePlacement, "Location"); if (!IFCAnyHandleUtil.IsNullOrHasNoValue(railingRelativeOrig)) { IList <double> railingVec = IFCAnyHandleUtil.GetCoordinates(railingRelativeOrig); IList <double> newMeasure = new List <double>(); newMeasure.Add(railingVec[0] - parentVec[0]); newMeasure.Add(railingVec[1] - parentVec[1]); newMeasure.Add(railingVec[2]); IFCAnyHandle locPtHnd = ExporterUtil.CreateCartesianPoint(file, newMeasure); newRelativePlacement = IFCInstanceExporter.CreateAxis2Placement3D(file, locPtHnd, null, null); } else { IList <double> railingMeasure = new List <double>(); railingMeasure.Add(-parentVec[0]); railingMeasure.Add(-parentVec[1]); railingMeasure.Add(0.0); IFCAnyHandle locPtHnd = ExporterUtil.CreateCartesianPoint(file, railingMeasure); newRelativePlacement = IFCInstanceExporter.CreateAxis2Placement3D(file, locPtHnd, null, null); } } IFCAnyHandle newLocalPlacement = IFCInstanceExporter.CreateLocalPlacement(file, origLocalPlacement, newRelativePlacement); IFCAnyHandle origRailingRep = IFCAnyHandleUtil.GetInstanceAttribute(origRailing, "Representation"); IFCAnyHandle newProdRep = ExporterUtil.CopyProductDefinitionShape(exporterIFC, elem, catId, origRailingRep); string ifcEnumTypeAsString = IFCAnyHandleUtil.GetEnumerationAttribute(origRailing, "PredefinedType"); IFCRailingType railingType = GetIFCRailingTypeFromString(ifcEnumTypeAsString); string copyGUID = GUIDUtil.CreateGUID(); IFCAnyHandle copyOwnerHistory = IFCAnyHandleUtil.GetInstanceAttribute(origRailing, "OwnerHistory"); string copyName = IFCAnyHandleUtil.GetStringAttribute(origRailing, "Name"); string copyDescription = IFCAnyHandleUtil.GetStringAttribute(origRailing, "Description"); string copyObjectType = IFCAnyHandleUtil.GetStringAttribute(origRailing, "ObjectType"); string copyElemId = IFCAnyHandleUtil.GetStringAttribute(origRailing, "Tag"); return(IFCInstanceExporter.CreateRailing(file, copyGUID, copyOwnerHistory, copyName, copyDescription, copyObjectType, newLocalPlacement, newProdRep, copyElemId, railingType)); }
public static IFCAnyHandle GetDefaultCartesianTransformationOperator3D(IFCFile file) { if (m_DefaultCartesianTransformationOperator3D == null) { XYZ orig = new XYZ(); IFCAnyHandle origHnd = ExporterUtil.CreateCartesianPoint(file, orig); m_DefaultCartesianTransformationOperator3D = IFCInstanceExporter.CreateCartesianTransformationOperator3D(file, null, null, origHnd, 1.0, null); } return(m_DefaultCartesianTransformationOperator3D); }
private static IFCAnyHandle ExportBoundingBoxBase(ExporterIFC exporterIFC, XYZ cornerXYZ, double xDim, double yDim, double zDim) { double eps = MathUtil.Eps(); if (xDim < eps || yDim < eps || zDim < eps) { return(null); } IFCFile file = exporterIFC.GetFile(); IFCAnyHandle cornerHnd = ExporterUtil.CreateCartesianPoint(file, cornerXYZ); IFCAnyHandle boundingBoxItem = IFCInstanceExporter.CreateBoundingBox(file, cornerHnd, xDim, yDim, zDim); if (IFCAnyHandleUtil.IsNullOrHasNoValue(boundingBoxItem)) { return(null); } IFCAnyHandle contextOfItems = exporterIFC.Get3DContextHandle("Box"); return(RepresentationUtil.CreateBoundingBoxRep(exporterIFC, contextOfItems, boundingBoxItem)); }
/// <summary> /// Creates a facetation of 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 list of facet handles.</returns> public static HashSet <IFCAnyHandle> CreateSimpleSweptSolidAsBRep(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 HashSet <IFCAnyHandle> facetHnds = null; if (!CanCreateSimpleSweptSolid(profileCurveLoops, normal, directrix)) { return(facetHnds); } // An extra requirement, as we can't tessellate an unbound curve. if (!directrix.IsBound) { return(facetHnds); } double originalStartParam = directrix.GetEndParameter(0); Plane axisPlane, profilePlane; CreateAxisAndProfileCurvePlanes(directrix, originalStartParam, out axisPlane, out profilePlane); IList <CurveLoop> curveLoops = null; try { // Check that curve loops are valid. curveLoops = ExporterIFCUtils.ValidateCurveLoops(profileCurveLoops, profilePlane.Normal); } catch (Exception) { return(null); } if (curveLoops == null || curveLoops.Count == 0) { return(facetHnds); } // Tessellate the curve loops. We don't add the last point, as these should all be closed curves. IList <IList <XYZ> > tessellatedOutline = new List <IList <XYZ> >(); foreach (CurveLoop curveLoop in curveLoops) { List <XYZ> tessellatedCurve = new List <XYZ>(); foreach (Curve curve in curveLoop) { if (curve is Line) { AddScaledPointToList(exporterIFC, tessellatedCurve, curve.GetEndPoint(0)); } else { IList <XYZ> curveTessellation = CreateRoughTessellation(exporterIFC, curve); tessellatedCurve.AddRange(curveTessellation); } } if (tessellatedCurve.Count != 0) { tessellatedOutline.Add(tessellatedCurve); } } IFCFile file = exporterIFC.GetFile(); IList <IList <IList <IFCAnyHandle> > > facetVertexHandles = new List <IList <IList <IFCAnyHandle> > >(); IList <IList <IFCAnyHandle> > tessellatedOutlineHandles = new List <IList <IFCAnyHandle> >(); foreach (IList <XYZ> tessellatedOutlinePolygon in tessellatedOutline) { IList <IFCAnyHandle> tessellatedOutlinePolygonHandles = new List <IFCAnyHandle>(); foreach (XYZ tessellatedOutlineXYZ in tessellatedOutlinePolygon) { tessellatedOutlinePolygonHandles.Add(ExporterUtil.CreateCartesianPoint(file, tessellatedOutlineXYZ)); } tessellatedOutlineHandles.Add(tessellatedOutlinePolygonHandles); } facetVertexHandles.Add(tessellatedOutlineHandles); // Tessellate the Directrix. This only works for bound Directrix curves. Unfortunately, we get XYZ values, which we will have to convert // back to parameter values to get the local transform. IList <double> tessellatedDirectrixParameters = CreateRoughParametricTessellation(directrix); // Create all of the other outlines by transformng the first tessellated outline to the current transform. Transform profilePlaneTrf = Transform.CreateTranslation(ExporterIFCUtils.TransformAndScalePoint(exporterIFC, profilePlane.Origin)); profilePlaneTrf.BasisX = ExporterIFCUtils.TransformAndScaleVector(exporterIFC, profilePlane.XVec); profilePlaneTrf.BasisY = ExporterIFCUtils.TransformAndScaleVector(exporterIFC, profilePlane.YVec); profilePlaneTrf.BasisZ = ExporterIFCUtils.TransformAndScaleVector(exporterIFC, profilePlane.Normal); // The inverse transform will be applied to generate the delta transform for the profile curves from the start of the directrix // to the current location. This could be optimized in the case of a Line, but current usage is really only for a single arc. // If that changes, we should revisit optimization possibilities. Transform profilePlaneTrfInverse = profilePlaneTrf.Inverse; // Create the delta transforms and the offset tessellated profiles. foreach (double parameter in tessellatedDirectrixParameters) { Transform directrixDirs = CreateProfileCurveTransform(exporterIFC, directrix, parameter); Transform deltaTransform = directrixDirs.Multiply(profilePlaneTrfInverse); IList <IList <IFCAnyHandle> > currTessellatedOutline = new List <IList <IFCAnyHandle> >(); foreach (IList <XYZ> pointLoop in tessellatedOutline) { IList <IFCAnyHandle> currTessellatedPoinLoop = new List <IFCAnyHandle>(); foreach (XYZ point in pointLoop) { XYZ transformedPoint = deltaTransform.OfPoint(point); IFCAnyHandle transformedPointHandle = ExporterUtil.CreateCartesianPoint(file, transformedPoint); currTessellatedPoinLoop.Add(transformedPointHandle); } currTessellatedOutline.Add(currTessellatedPoinLoop); } facetVertexHandles.Add(currTessellatedOutline); } // Create the side facets. facetHnds = new HashSet <IFCAnyHandle>(); int numFacets = facetVertexHandles.Count - 1; for (int ii = 0; ii < numFacets; ii++) { IList <IList <IFCAnyHandle> > firstOutline = facetVertexHandles[ii]; IList <IList <IFCAnyHandle> > secondOutline = facetVertexHandles[ii + 1]; int numLoops = firstOutline.Count; for (int jj = 0; jj < numLoops; jj++) { IList <IFCAnyHandle> firstLoop = firstOutline[jj]; IList <IFCAnyHandle> secondLoop = secondOutline[jj]; int numVertices = firstLoop.Count; for (int kk = 0; kk < numVertices; kk++) { IList <IFCAnyHandle> polyLoopHandles = new List <IFCAnyHandle>(4); polyLoopHandles.Add(secondLoop[kk]); polyLoopHandles.Add(secondLoop[(kk + 1) % numVertices]); polyLoopHandles.Add(firstLoop[(kk + 1) % numVertices]); polyLoopHandles.Add(firstLoop[kk]); IFCAnyHandle face = BodyExporter.CreateFaceFromVertexList(file, polyLoopHandles); facetHnds.Add(face); } } } // Create the end facets. for (int ii = 0; ii < 2; ii++) { int faceIndex = (ii == 0) ? 0 : facetVertexHandles.Count - 1; int numLoops = facetVertexHandles[faceIndex].Count; HashSet <IFCAnyHandle> faceBounds = new HashSet <IFCAnyHandle>(); for (int jj = 0; jj < numLoops; jj++) { IList <IFCAnyHandle> polyLoopHandles = null; if (ii == 0) { polyLoopHandles = facetVertexHandles[faceIndex][jj]; } else { int numHandles = facetVertexHandles[faceIndex][jj].Count; polyLoopHandles = new List <IFCAnyHandle>(numHandles); for (int kk = numHandles - 1; kk >= 0; kk--) { polyLoopHandles.Add(facetVertexHandles[faceIndex][jj][kk]); } } IFCAnyHandle polyLoop = IFCInstanceExporter.CreatePolyLoop(file, polyLoopHandles); IFCAnyHandle faceBound = (jj == 0) ? IFCInstanceExporter.CreateFaceOuterBound(file, polyLoop, true) : IFCInstanceExporter.CreateFaceBound(file, polyLoop, true); faceBounds.Add(faceBound); } IFCAnyHandle face = IFCInstanceExporter.CreateFace(file, faceBounds); facetHnds.Add(face); } return(facetHnds); }
/// <summary> /// Initializes the transformation in the transform setter. /// </summary> /// <param name="exporterIFC">The exporter.</param> /// <param name="geometryList">The set of geometry used to determine the bounding box.</param> /// <param name="ecData">The extrusion creation data which contains the local placement.</param> /// <returns>The transform corresponding to the movement, if any.</returns> /// <remarks>This method will eventually be obsoleted by the InitializeFromBoundingBox/CreateLocalPlacementFromOffset pair below, which delays creating or updating the local placement /// until we are certain we will use it, saving time and reducing wasted line numbers.</remarks> public Transform InitializeFromBoundingBox(ExporterIFC exporterIFC, IList <GeometryObject> geometryList, IFCExtrusionCreationData ecData) { if (ecData == null) { return(null); } Transform trf = Transform.Identity; IFCAnyHandle localPlacement = ecData.GetLocalPlacement(); if (!IFCAnyHandleUtil.IsNullOrHasNoValue(localPlacement)) { IFCFile file = exporterIFC.GetFile(); BoundingBoxXYZ bbox = GeometryUtil.GetBBoxOfGeometries(geometryList); // If the BBox passes through (0,0, 0), or no bbox, do nothing. if (bbox == null || ((bbox.Min.X < MathUtil.Eps() && bbox.Max.X > -MathUtil.Eps()) && (bbox.Min.Y < MathUtil.Eps() && bbox.Max.Y > -MathUtil.Eps()) && (bbox.Min.Z < MathUtil.Eps() && bbox.Max.Z > -MathUtil.Eps()))) { if (!ecData.ReuseLocalPlacement) { ecData.SetLocalPlacement(ExporterUtil.CopyLocalPlacement(file, localPlacement)); } return(trf); } XYZ bboxMin = bbox.Min; XYZ scaledOrig = UnitUtil.ScaleLength(bboxMin); Transform scaledTrf = GeometryUtil.GetScaledTransform(exporterIFC); XYZ lpOrig = scaledTrf.OfPoint(scaledOrig); if (!ecData.AllowVerticalOffsetOfBReps) { lpOrig = new XYZ(lpOrig.X, lpOrig.Y, 0.0); } Transform scaledTrfInv = scaledTrf.Inverse; XYZ scaledInvOrig = scaledTrfInv.OfPoint(XYZ.Zero); XYZ unscaledInvOrig = UnitUtil.UnscaleLength(scaledInvOrig); XYZ trfOrig = unscaledInvOrig - bboxMin; if (!ecData.AllowVerticalOffsetOfBReps) { trfOrig = new XYZ(trfOrig.X, trfOrig.Y, 0.0); } if (!MathUtil.IsAlmostZero(trfOrig.DotProduct(trfOrig))) { Initialize(exporterIFC, trfOrig, XYZ.BasisX, XYZ.BasisY); if (!ecData.ReuseLocalPlacement) { ecData.SetLocalPlacement(ExporterUtil.CreateLocalPlacement(file, localPlacement, lpOrig, null, null)); } else { IFCAnyHandle relativePlacement = GeometryUtil.GetRelativePlacementFromLocalPlacement(localPlacement); if (IFCAnyHandleUtil.IsNullOrHasNoValue(relativePlacement)) { IFCAnyHandle newRelativePlacement = ExporterUtil.CreateAxis(file, lpOrig, null, null); GeometryUtil.SetRelativePlacement(localPlacement, newRelativePlacement); } else { IFCAnyHandle oldOriginHnd, zDirHnd, xDirHnd; xDirHnd = IFCAnyHandleUtil.GetInstanceAttribute(relativePlacement, "RefDirection"); zDirHnd = IFCAnyHandleUtil.GetInstanceAttribute(relativePlacement, "Axis"); oldOriginHnd = IFCAnyHandleUtil.GetInstanceAttribute(relativePlacement, "Location"); bool trfSet = false; XYZ xDir = XYZ.BasisX; XYZ zDir = XYZ.BasisZ; XYZ oldCoords = XYZ.Zero; if (!IFCAnyHandleUtil.IsNullOrHasNoValue(xDirHnd)) { xDir = GeometryUtil.GetDirectionRatios(xDirHnd); trfSet = true; } if (!IFCAnyHandleUtil.IsNullOrHasNoValue(zDirHnd)) { zDir = GeometryUtil.GetDirectionRatios(zDirHnd); trfSet = true; } if (!IFCAnyHandleUtil.IsNullOrHasNoValue(oldOriginHnd)) { oldCoords = GeometryUtil.GetCoordinates(oldOriginHnd); } if (trfSet) { XYZ yDir = zDir.CrossProduct(xDir); Transform relPlacementTrf = Transform.Identity; relPlacementTrf.Origin = oldCoords; relPlacementTrf.BasisX = xDir; relPlacementTrf.BasisY = yDir; relPlacementTrf.BasisZ = zDir; lpOrig = relPlacementTrf.OfPoint(lpOrig); } else { lpOrig = oldCoords + lpOrig; } IFCAnyHandle newOriginHnd = ExporterUtil.CreateCartesianPoint(file, lpOrig); IFCAnyHandleUtil.SetAttribute(relativePlacement, "Location", newOriginHnd); } } trf.Origin = lpOrig; } else if (ecData.ForceOffset) { ecData.SetLocalPlacement(ExporterUtil.CreateLocalPlacement(file, localPlacement, null)); } else if (!ecData.ReuseLocalPlacement) { ecData.SetLocalPlacement(ExporterUtil.CopyLocalPlacement(file, localPlacement)); } } return(trf); }