private static void RotateElementInPosition(XYZ placementPoint, Connector conOnFamilyToConnect, Connector start, Connector end, Element element) { #region Geometric manipulation //http://thebuildingcoder.typepad.com/blog/2012/05/create-a-pipe-cap.html XYZ dir = (start.Origin - end.Origin); // rotate the cap if necessary // rotate about Z first XYZ pipeHorizontalDirection = new XYZ(dir.X, dir.Y, 0.0).Normalize(); //XYZ pipeHorizontalDirection = new XYZ(dir.X, dir.Y, 0.0); XYZ connectorDirection = -conOnFamilyToConnect.CoordinateSystem.BasisZ; double zRotationAngle = pipeHorizontalDirection.AngleTo(connectorDirection); Transform trf = Transform.CreateRotationAtPoint(XYZ.BasisZ, zRotationAngle, placementPoint); XYZ testRotation = trf.OfVector(connectorDirection).Normalize(); if (Math.Abs(testRotation.DotProduct(pipeHorizontalDirection) - 1) > 0.00001) { zRotationAngle = -zRotationAngle; } Line axis = Line.CreateBound(placementPoint, placementPoint + XYZ.BasisZ); ElementTransformUtils.RotateElement(element.Document, element.Id, axis, zRotationAngle); //Parameter comments = element.get_Parameter(BuiltInParameter.ALL_MODEL_INSTANCE_COMMENTS); //comments.Set("Horizontal only"); // Need to rotate vertically? if (Math.Abs(dir.DotProduct(XYZ.BasisZ)) > 0.000001) { // if pipe is straight up and down, // kludge it my way else if (dir.X.Round(3) == 0 && dir.Y.Round(3) == 0 && dir.Z.Round(3) != 0) { XYZ yaxis = new XYZ(0.0, 1.0, 0.0); double rotationAngle = dir.AngleTo(yaxis); //<-- value in radians if (dir.Z > 0) { rotationAngle = -rotationAngle; //<-- Here is the culprit: Equals(1) was wrong! } axis = Line.CreateBound(placementPoint, new XYZ(placementPoint.X, placementPoint.Y + 5, placementPoint.Z)); ElementTransformUtils.RotateElement(element.Document, element.Id, axis, rotationAngle); //comments.Set("Vertical!"); } else { #region sloped pipes double rotationAngle = dir.AngleTo(pipeHorizontalDirection); XYZ normal = pipeHorizontalDirection.CrossProduct(XYZ.BasisZ); trf = Transform.CreateRotationAtPoint(normal, rotationAngle, placementPoint); testRotation = trf.OfVector(dir).Normalize(); if (Math.Abs(testRotation.DotProduct(pipeHorizontalDirection) - 1) < 0.00001) { rotationAngle = -rotationAngle; } axis = Line.CreateBound(placementPoint, placementPoint + normal); ElementTransformUtils.RotateElement(element.Document, element.Id, axis, rotationAngle); //comments.Set("Sloped"); #endregion } } #endregion }
public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements) { Document doc = commandData.Application.ActiveUIDocument.Document; UIDocument uidoc = commandData.Application.ActiveUIDocument; Selection selection = uidoc.Selection; XYZ point1 = new XYZ(500, 600, 700); XYZ point2 = new XYZ(3500, 3800, 1500); Curve curve = Line.CreateBound(point1, point2); XYZ point_in_3d_start; XYZ point_in_3d_end; //拾取第一个点 if (SetWorkPlaneAndPickObject(uidoc, out point_in_3d_start)) { TaskDialog.Show("3D Point Selected", "3D point picked on the plane" + " defined by the selected face: " + "X: " + point_in_3d_start.X.ToString() + ", Y: " + point_in_3d_start.Y.ToString() + ", Z: " + point_in_3d_start.Z.ToString()); } else { message = "3D point selection failed"; return(Result.Failed); } //拾取第二个点 if (SetWorkPlaneAndPickObject(uidoc, out point_in_3d_end)) { TaskDialog.Show("3D Point Selected", "3D point picked on the plane" + " defined by the selected face: " + "X: " + point_in_3d_end.X.ToString() + ", Y: " + point_in_3d_end.Y.ToString() + ", Z: " + point_in_3d_end.Z.ToString()); } else { message = "3D point selection failed"; return(Result.Failed); } using (Transaction trans1 = new Transaction(doc)) { trans1.Start("开始绘制三维线段"); Line curve_3d = Line.CreateBound(point_in_3d_start, point_in_3d_end); XYZ direction = curve_3d.Direction; XYZ normal_direc = direction.CrossProduct(XYZ.BasisZ); Plane normal_plane = new Plane(normal_direc, point_in_3d_start); SketchPlane sketchPlane = SketchPlane.Create(doc, normal_plane); ModelCurve modelCurve = doc.Create.NewModelCurve(curve_3d, sketchPlane); trans1.Commit(); } return(Result.Succeeded); }
public Result Execute( ExternalCommandData commandData, ref string message, ElementSet elements) { UIApplication uiapp = commandData.Application; UIDocument uidoc = uiapp.ActiveUIDocument; Application app = uiapp.Application; Document doc = uidoc.Document; //WALLS FACES List <PlanarFace> wallFaces = new List <PlanarFace>(); //WALLS Reference wallRef = uidoc.Selection.PickObject(ObjectType.Element, "Select a Wall"); Element wall = doc.GetElement(wallRef); LocationCurve lc = wall.Location as LocationCurve; Line wallLine = lc.Curve as Line; XYZ perpDir = wallLine.Direction.CrossProduct(XYZ.BasisZ); Options opt = new Options(); opt.ComputeReferences = true; opt.IncludeNonVisibleObjects = false; opt.View = doc.ActiveView; GeometryElement geomElem = doc.GetElement(wallRef).get_Geometry(opt); foreach (GeometryObject geomObj in geomElem) { Solid geomSolid = geomObj as Solid; foreach (Face geomFace in geomSolid.Faces) { XYZ faceNormal = geomFace.ComputeNormal(new UV(0.5, 0.5)); //select only the vertical faces if (faceNormal.CrossProduct(perpDir).IsAlmostEqualTo(XYZ.Zero)) { PlanarFace pf = geomFace as PlanarFace; wallFaces.Add(pf); } } } //GET MESH Reference meshRef = uidoc.Selection.PickObject(ObjectType.Element, "Select Mesh"); Element e = doc.GetElement(meshRef); GeometryElement geomElemSurvey = e.get_Geometry(opt); Mesh geomMesh = null; foreach (GeometryObject geomObj in geomElemSurvey) { try { GeometryInstance gi = geomObj as GeometryInstance; foreach (GeometryObject element in gi.GetInstanceGeometry()) { geomMesh = element as Mesh; } } catch { geomMesh = geomObj as Mesh; } } using (Transaction t = new Transaction(doc, "Find intersection")) { t.Start(); List <XYZ> intPts = new List <XYZ>(); for (int i = 0; i < geomMesh.NumTriangles; i++) { MeshTriangle triangle = geomMesh.get_Triangle(i); XYZ vertex1 = triangle.get_Vertex(0); XYZ vertex2 = triangle.get_Vertex(1); XYZ vertex3 = triangle.get_Vertex(2); Line[] edgeList = new Line[3]; try { Line[] edges = new Line[] { Line.CreateBound(vertex1, vertex2), Line.CreateBound(vertex1, vertex3), Line.CreateBound(vertex2, vertex3) }; for (int k = 0; k < edgeList.Length; k++) { edgeList[k] = edges[k]; } } catch { } // Plane facePlane = Plane.CreateByThreePoints(vertex1, vertex2, vertex3); // SketchPlane sp = SketchPlane.Create(doc, facePlane); // doc.Create.NewModelCurve(edge12, sp); // doc.Create.NewModelCurve(edge13, sp); // doc.Create.NewModelCurve(edge23, sp); foreach (PlanarFace pf in wallFaces) { XYZ[] pts = new XYZ[2]; int count = 0; if (edgeList[0] != null) { foreach (Line edge in edgeList) { IntersectionResultArray intersections = null; SetComparisonResult scr = pf.Intersect(edge, out intersections); if (scr == SetComparisonResult.Overlap && intersections.Size == 1) { for (int j = 0; j < intersections.Size; j++) { //TaskDialog.Show("r", intersections.get_Item(i)); } //TaskDialog.Show("r", intersections.Size.ToString()); IntersectionResult iResult = intersections.get_Item(0); intPts.Add(iResult.XYZPoint); pts[count] = iResult.XYZPoint; count = 1; if (pts.Length == 2 && pts[1] != null) { // TaskDialog.Show("r", String.Format("{0}\n{1}",pts[0], pts[1])); try { Plane wallPlane = Plane.CreateByNormalAndOrigin(pf.FaceNormal, pf.Origin); SketchPlane spWall = SketchPlane.Create(doc, wallPlane); doc.Create.NewModelCurve(Line.CreateBound(pts[0], pts[1]), spWall); } catch { } } } } } } } t.Commit(); } return(Result.Succeeded); }
public ModelCurve MakeLine(Document doc, XYZ ptA, XYZ ptB) { Autodesk.Revit.ApplicationServices.Application app = doc.Application; // Create plane by the points Line line = app.Create.NewLine(ptA, ptB, true); XYZ norm = ptA.CrossProduct(ptB); double length = norm.GetLength(); if (length == 0) norm = XYZ.BasisZ; Plane plane = app.Create.NewPlane(norm, ptB); SketchPlane skplane = doc.FamilyCreate.NewSketchPlane(plane); // Create line here ModelCurve modelcurve = doc.FamilyCreate.NewModelCurve(line, skplane); return modelcurve; }
/// <summary> /// Calculate a transform from zero or more axis vectors, according to the IFC2x3 schema definition. /// </summary> /// <param name="axis1">The X axis, or null.</param> /// <param name="axis2">The Y axis, or null.</param> /// <param name="axis3">The Z axis, or null.</param> /// <param name="orig">The origin.</param> /// <param name="dim">The dimensionality of the arguments (either 2 or 3). If dim is 2, then axis3 will be ignored, as will /// the Z component of axis1 and axis2.</param> /// <param name="id">The id of the IfcCartesianTransformOperator entity, used for error reporting.</param> /// <returns>The transform.</returns> /// <remarks>This is an adaption of the IfcBaseAxis function in the IFC2x3_TC1.exp file that defines /// how the basis vectors should be calculated for IfcCartesianTransformOperator.</remarks> private Transform CreateTransformUsingIfcBaseAxisCalculation(XYZ axis1, XYZ axis2, XYZ axis3, XYZ orig, int dim, int id) { XYZ xAxis = null; XYZ yAxis = null; XYZ zAxis = null; if (dim == 3) { // Only do the calculations below if any of the vectors are missing, or the 3 vectors aren't orthonormal. // The input vectors should already be normalized. if (axis1 == null || axis2 == null || axis3 == null || !MathUtil.VectorsAreOrthogonal(axis1, axis2) || !MathUtil.VectorsAreOrthogonal(axis1, axis3) || !MathUtil.VectorsAreOrthogonal(axis2, axis3)) { // Note that the IFC schema definition does not take into account the case where the zAxis isn't defined, and the xAxis is +/-Z. zAxis = (axis3 == null) ? XYZ.BasisZ : axis3.Normalize(); xAxis = CalculateXAxisFromZAxis(zAxis, axis1, id); if (xAxis == null) { // This may be because axis1 and axis3 are both set to the same vector, or axis3 was unset and axis1 was set to +/-Z. Correct this below. Importer.TheLog.LogWarning(id, "The IFC schema definition would generate an incorrect X basis vector in this case. Correcting.", false); if (axis3 == null) { if (axis1 == null) { Importer.TheLog.LogError(id, "Invalid basis vectors. Can't correct, aborting.", true); } xAxis = axis1; zAxis = XYZ.BasisY; } else { xAxis = XYZ.BasisX; } } yAxis = zAxis.CrossProduct(xAxis); // Note that according to the IFC schema, the axis2 argument is effectively ignored. We'll check it for consistency. if (axis2 != null) { if (MathUtil.VectorsAreParallel2(yAxis, axis2) != 1) { Importer.TheLog.LogWarning(id, "Inconsistent basis vectors based on the IFC schema definition may cause a difference in orientation for related objects.", false); } } } else { xAxis = axis1; yAxis = axis2; zAxis = axis3; } } else if (dim == 2) { if (axis1 != null && !MathUtil.IsAlmostZero(xAxis.Z)) { Importer.TheLog.LogWarning(id, "Invalid X basis vector, ignoring.", true); } if (axis2 != null && !MathUtil.IsAlmostZero(yAxis.Z)) { Importer.TheLog.LogWarning(id, "Invalid Y basis vector, ignoring.", true); } zAxis = XYZ.BasisZ; if (axis1 != null) { xAxis = axis1.Normalize(); yAxis = new XYZ(-xAxis.Y, xAxis.X, 0.0); if (axis2 != null) { double dot = axis2.DotProduct(yAxis); if (dot < 0.0) { yAxis = -yAxis; } } } else if (axis2 != null) { yAxis = axis2.Normalize(); xAxis = new XYZ(yAxis.Y, -yAxis.X, 0.0); } else { xAxis = XYZ.BasisX; yAxis = XYZ.BasisY; } } else { Importer.TheLog.LogError(id, "Can't handle dimensionality of " + dim + " in calculating basis vector.", true); } Transform transform = Transform.CreateTranslation(orig); transform.BasisX = xAxis; transform.BasisY = yAxis; transform.BasisZ = zAxis; return(transform); }
Transform GetTransformToZ( XYZ v ) { Transform t; double a = XYZ.BasisZ.AngleTo( v ); if( Util.IsZero( a ) ) { t = Transform.Identity; } else { XYZ axis = Util.IsEqual( a, Math.PI ) ? XYZ.BasisX : v.CrossProduct( XYZ.BasisZ ); //t = Transform.get_Rotation( XYZ.Zero, axis, a ); // 2013 t = Transform.CreateRotation( axis, a ); // 2014 } return t; }
private XYZ GetValidXVectorFromLoop(CurveLoop curveLoop, XYZ zVec, XYZ origin) { foreach (Curve curve in curveLoop) { IList<XYZ> pointsToCheck = new List<XYZ>(); // If unbound, must be cyclic. if (!curve.IsBound) { pointsToCheck.Add(curve.Evaluate(0, false)); pointsToCheck.Add(curve.Evaluate(Math.PI / 2.0, false)); pointsToCheck.Add(curve.Evaluate(Math.PI, false)); } else { pointsToCheck.Add(curve.Evaluate(0, true)); pointsToCheck.Add(curve.Evaluate(1.0, true)); if (curve.IsCyclic) pointsToCheck.Add(curve.Evaluate(0.5, true)); } foreach (XYZ pointToCheck in pointsToCheck) { XYZ possibleVec = (pointToCheck - origin); XYZ yVec = zVec.CrossProduct(possibleVec).Normalize(); if (yVec.IsZeroLength()) continue; return yVec.CrossProduct(zVec); } } return null; }
protected override void Process(IFCAnyHandle ifcVirtualGridIntersection) { base.Process(ifcVirtualGridIntersection); IList <IFCAnyHandle> intersectingAxes = IFCAnyHandleUtil.GetAggregateInstanceAttribute <List <IFCAnyHandle> >(ifcVirtualGridIntersection, "IntersectingAxes"); if (intersectingAxes == null || intersectingAxes.Count != 2 || IFCAnyHandleUtil.IsNullOrHasNoValue(intersectingAxes[0]) || IFCAnyHandleUtil.IsNullOrHasNoValue(intersectingAxes[1])) { Importer.TheLog.LogError(ifcVirtualGridIntersection.StepId, "Missing or invalid intersecting axes.", false); return; } IFCGridAxis firstAxis = IFCGridAxis.ProcessIFCGridAxis(intersectingAxes[0]); if (firstAxis == null) { return; } IFCGridAxis secondAxis = IFCGridAxis.ProcessIFCGridAxis(intersectingAxes[1]); if (secondAxis == null) { return; } OffsetDistances = IFCAnyHandleUtil.GetAggregateDoubleAttribute <List <double> >(ifcVirtualGridIntersection, "OffsetDistances"); double[] offsetDistances = new double[3]; int offsetDistanceCount = (OffsetDistances != null) ? OffsetDistances.Count : 0; for (int ii = 0; ii < 3; ii++) { offsetDistances[ii] = (offsetDistanceCount > ii) ? OffsetDistances[ii] : 0; } Curve firstCurve = firstAxis.GetAxisCurveForGridPlacement(); if (firstCurve == null) { return; } Curve secondCurve = secondAxis.GetAxisCurveForGridPlacement(); if (secondCurve == null) { return; } // We need to figure out the reference vector to do the offset, but we can't get // the reference vector without getting the tangent at the intersection point. // We will use a heuristic in GetReferenceVector to guess based on the curve types. XYZ referenceVector = GetReferenceVector(firstCurve); Curve firstOffsetCurve = (!MathUtil.IsAlmostZero(offsetDistances[0])) ? firstCurve.CreateOffset(offsetDistances[0], referenceVector) : firstCurve; Curve secondOffsetCurve = (!MathUtil.IsAlmostZero(offsetDistances[1])) ? secondCurve.CreateOffset(offsetDistances[1], referenceVector) : secondCurve; IntersectionResultArray resultArray; SetComparisonResult result = firstOffsetCurve.Intersect(secondOffsetCurve, out resultArray); if (result != SetComparisonResult.Overlap || resultArray == null || resultArray.Size == 0) { return; } IntersectionResult intersectionPoint = resultArray.get_Item(0); XYZ origin = intersectionPoint.XYZPoint + offsetDistances[2] * referenceVector; Transform derivatives = firstCurve.ComputeDerivatives(intersectionPoint.UVPoint.U, false); LocalCoordinateSystem = Transform.CreateTranslation(origin); LocalCoordinateSystem.BasisX = derivatives.BasisX; LocalCoordinateSystem.BasisY = referenceVector.CrossProduct(derivatives.BasisX); LocalCoordinateSystem.BasisZ = referenceVector; }
public void OnPolymesh(PolymeshTopology polymesh) { Debug.WriteLine(string.Format( " OnPolymesh: {0} points, {1} facets, {2} normals {3}", polymesh.NumberOfPoints, polymesh.NumberOfFacets, polymesh.NumberOfNormals, polymesh.DistributionOfNormals)); IList <XYZ> pts = polymesh.GetPoints(); IList <XYZ> normals = polymesh.GetNormals(); Transform t = CurrentTransform; int nVertices = pts.Count; List <int> vertexCoordsMm = new List <int>( 3 * nVertices); foreach (XYZ p in pts) { // Translate the entire element geometry // to the bounding box midpoint and scale // to metric millimetres. XYZ q = t.OfPoint(p) - _pmid; vertexCoordsMm.Add(Util.FootToMm(p.X)); vertexCoordsMm.Add(Util.FootToMm(p.Y)); vertexCoordsMm.Add(Util.FootToMm(p.Z)); } int i = 0; int[] triangleIndices = new int[3]; XYZ[] triangleCorners = new XYZ[3]; foreach (PolymeshFacet facet in polymesh.GetFacets()) { Debug.WriteLine(string.Format( " {0}: {1} {2} {3}", i++, facet.V1, facet.V2, facet.V3)); IList <int> vertices = facet.GetVertices(); for (int j = 0; j < 3; ++j) { int k = vertices[j]; triangleIndices[j] = k; triangleCorners[j] = pts[k]; } // Calculate constant triangle facet normal. XYZ v = triangleCorners[1] - triangleCorners[0]; XYZ w = triangleCorners[2] - triangleCorners[0]; XYZ triangleNormal = v .CrossProduct(w) .Normalize(); for (int j = 0; j < 3; ++j) { int nFaceVertices = _faceVertices.Count; Debug.Assert(nFaceVertices.Equals(_faceNormals.Count), "expected equal number of face vertex and normal coordinates"); _faceIndices.Add(nFaceVertices / 3); int i3 = triangleIndices[j] * 3; // Rotate the X, Y and Z directions, // since the Z direction points upward // in Revit as opposed to sideways or // outwards or forwards in WebGL. _faceVertices.Add(vertexCoordsMm[i3 + 1]); _faceVertices.Add(vertexCoordsMm[i3 + 2]); _faceVertices.Add(vertexCoordsMm[i3]); if (CmdElemGeom.RetainCurvedSurfaceFacets) { _faceNormals.Add(triangleNormal.Y); _faceNormals.Add(triangleNormal.Z); _faceNormals.Add(triangleNormal.X); } else { XYZ normal = normals[triangleIndices[j]]; _faceNormals.Add(normal.Y); _faceNormals.Add(normal.Z); _faceNormals.Add(normal.X); } } } }
private Result pipeSection(Document doc, Pipe pipe) { LocationCurve lc = pipe.Location as LocationCurve; Curve curve = lc.Curve as Curve; if (null == curve) { TaskDialog.Show("...", "Unable to retrieve pipe location line."); return(Result.Failed); } // Determine view family type to use ViewFamilyType vft = new FilteredElementCollector(doc) .OfClass(typeof(ViewFamilyType)) .Cast <ViewFamilyType>() .FirstOrDefault <ViewFamilyType>(x => ViewFamily.Section == x.ViewFamily); // Determine section box XYZ p = curve.GetEndPoint(0); XYZ q = curve.GetEndPoint(1); XYZ v = q - p; XYZ v2 = new XYZ(v.X, v.Y, 0); BoundingBoxXYZ bb = pipe.get_BoundingBox(null); double minZ = bb.Min.Z; double maxZ = bb.Max.Z; double avg = (maxZ - minZ) / 2; double w = v.GetLength(); double h = maxZ - minZ; double d = pipe.Diameter; double offset = 0.1 * w; XYZ min = new XYZ(-w / 2 - side, -avg - above, -offset); XYZ max = new XYZ(w / 2 + side, avg + above, 3); XYZ ductdir = v2.Normalize(); XYZ up = XYZ.BasisZ; XYZ viewdir = ductdir.CrossProduct(up); XYZ midpoint = p + 0.5 * v; Transform t = Transform.Identity; t.Origin = midpoint; t.BasisX = ductdir; t.BasisY = up; t.BasisZ = viewdir; BoundingBoxXYZ sectionBox = new BoundingBoxXYZ(); try { sectionBox.Transform = t; sectionBox.Min = min; sectionBox.Max = max; } catch (Exception ex) { using (Transaction tx = new Transaction(doc)) { tx.Start("Create pipe Section View"); if (SectionConfigForm.vft == null) { viewSec = ViewSection.CreateSection(doc, vft.Id, sectionBox); } else { viewSec = ViewSection.CreateSection(doc, SectionConfigForm.vft.Id, sectionBox); } tx.Commit(); } } using (Transaction tx = new Transaction(doc)) { tx.Start("Create pipe Section View"); if (SectionConfigForm.vft == null) { viewSec = ViewSection.CreateSection(doc, vft.Id, sectionBox); } else { viewSec = ViewSection.CreateSection(doc, SectionConfigForm.vft.Id, sectionBox); } tx.Commit(); } return(Result.Succeeded); }
public static bool IsParallel( XYZ p, XYZ q ) { return p.CrossProduct( q ).IsZeroLength(); }
private bool IsParallel(XYZ p, XYZ q) { return(p.CrossProduct(q).IsZeroLength()); }
public static ModelCurve MakeLine( UIApplication app, XYZ ptA, XYZ ptB, Document doc ) { // Create plane by the points Line line = app.Application.Create.NewLine( ptA, ptB, true ); XYZ norm = ptA.CrossProduct( ptB ); if( norm.GetLength() == 0 ) norm = XYZ.BasisZ; Plane plane = app.Application.Create.NewPlane( norm, ptB ); SketchPlane skplane = doc.FamilyCreate.NewSketchPlane( plane ); // Create line here ModelCurve modelcurve = doc.FamilyCreate.NewModelCurve( line, skplane ); return modelcurve; }
static ModelCurve MakeLine( Document doc, XYZ p, XYZ q) { // Create plane by the points Line line = Line.CreateBound( p, q ); XYZ norm = p.CrossProduct( q ); if( norm.GetLength() == 0 ) { norm = XYZ.BasisZ; } Plane plane = new Plane( norm, q ); SketchPlane skplane = SketchPlane.Create( doc, plane ); // Create line return doc.FamilyCreate.NewModelCurve( line, skplane ); }
public static string GetFacesAndEdges(Element e, bool startFromZero) { String xx = ""; bool RetainCurvedSurfaceFacets = true; // Get element geometry Options opt = new Options(); GeometryElement geomElem = e.get_Geometry(opt); int[] triangleIndices = new int[3]; XYZ[] triangleCorners = new XYZ[3]; List <string> faceVertices = new List <string>(); List <string> faceNormals = new List <string>(); List <string> faceElements = new List <string>(); //// First we need to get transformation //LocationCurve lc = e.Location as LocationCurve; //// Get curve starting- and endpoint //XYZ startingPoint = lc.Curve.GetEndPoint(0); //XYZ endPoint = lc.Curve.GetEndPoint(1); foreach (GeometryObject geomObj in geomElem) { Solid geomSolid = geomObj as Solid; if (null != geomSolid) { faceVertices.Clear(); faceNormals.Clear(); faceElements.Clear(); foreach (Face face in geomSolid.Faces) { // Triangulate face to get mesh Mesh mesh = face.Triangulate(); int nTriangles = mesh.NumTriangles; IList <XYZ> vertices = mesh.Vertices; int nVertices = vertices.Count; List <int> vertexCoordsMm = new List <int>(3 * nVertices); // A vertex may be reused several times with // different normals for different faces, so // we cannot precalculate normals per vertex. // List<double> normals = new List<double>( 3 * nVertices ); // Extract vertices foreach (XYZ v in vertices) { vertexCoordsMm.Add(ConvertLengthToMM(v.X)); vertexCoordsMm.Add(ConvertLengthToMM(v.Y)); vertexCoordsMm.Add(ConvertLengthToMM(v.Z)); } // Loop over triangles for (int i = 0; i < nTriangles; ++i) { MeshTriangle triangle = mesh.get_Triangle(i); for (int j = 0; j < 3; ++j) { int k = (int)triangle.get_Index(j); triangleIndices[j] = k; triangleCorners[j] = vertices[k]; } // Calculate constant triangle facet normal. XYZ v = triangleCorners[1] - triangleCorners[0]; XYZ w = triangleCorners[2] - triangleCorners[0]; XYZ triangleNormal = v .CrossProduct(w) .Normalize(); // List to store vertice indexes in the form: [v1//vn1 v2//vn2 v3//vn3] List <string> vertIndexes = new List <string>(); for (int j = 0; j < 3; ++j) { int nFaceVertices = faceVertices.Count; //if(nFaceVertices != faceNormals.Count) //{ // xx += "expected equal number of face vertex and normal coordinates\n"; //} int i3 = triangleIndices[j] * 3; // Rotate the X, Y and Z directions, // since the Z direction points upward // in Revit as opposed to sideways or // outwards or forwards in WebGL. string vStr = $"v {vertexCoordsMm[i3]} {vertexCoordsMm[i3 + 1]} {vertexCoordsMm[i3 + 2]}"; // get vertice index int vidx = faceVertices.IndexOf(vStr); // add if not exist if (vidx == -1) { faceVertices.Add(vStr); vidx = faceVertices.Count - 1; } string vnStr = ""; if (RetainCurvedSurfaceFacets) { vnStr = $"vn {Math.Round(triangleNormal.X, 2)} {Math.Round(triangleNormal.Y, 2)} {Math.Round(triangleNormal.Z, 2)}"; } else { UV uv = face.Project( triangleCorners[j]).UVPoint; XYZ normal = face.ComputeNormal(uv); vnStr = $"vn {Math.Round(normal.X, 2)} {Math.Round(normal.Y, 2)} {Math.Round(normal.Z, 2)}"; } // get face normal index int vnidx = faceNormals.IndexOf(vnStr); // add if not in list if (vnidx == -1) { faceNormals.Add(vnStr); vnidx = faceNormals.Count - 1; } // add indexes to list vertIndexes.Add($"{vidx+1+objStartIndex}/{vnidx+1 + objStartNormal}"); } // Store face elements string fStr = $"f {vertIndexes[0]} {vertIndexes[1]} {vertIndexes[2]}"; faceElements.Add(fStr); } } // Write to string xx += String.Join("\n\t", faceVertices) + "\n\t"; xx += String.Join("\n\t", faceNormals) + "\n\t"; xx += String.Join("\n\t", faceElements) + "\n\t"; if (!startFromZero) { objStartIndex += faceVertices.Count; objStartNormal += faceNormals.Count; } } Mesh geomMesh = geomObj as Mesh; Curve geomCurve = geomObj as Curve; Point geomPoint = geomObj as Point; PolyLine geomPoly = geomObj as PolyLine; GeometryInstance geomInst = geomObj as GeometryInstance; if (null != geomInst) { GeometryElement geomElement = geomInst.GetInstanceGeometry(); foreach (GeometryObject geomObj1 in geomElement) { Solid geomSolid1 = geomObj1 as Solid; if (null != geomSolid1) { Console.Out.WriteLine("got element: " + geomSolid1.Faces); } } } } return(xx); }
public static void RotateElementInPosition(XYZ placementPoint, Connector conOnFamilyToConnect, Connector start, Element element) { #region Geometric manipulation //http://thebuildingcoder.typepad.com/blog/2012/05/create-a-pipe-cap.html //Select the OTHER connector MEPCurve hostPipe = start.Owner as MEPCurve; Connector end = (from Connector c in hostPipe.ConnectorManager.Connectors //End of the host/dummy pipe where c.Id != start.Id && (int)c.ConnectorType == 1 select c).FirstOrDefault(); XYZ dir = (start.Origin - end.Origin); // rotate the cap if necessary // rotate about Z first XYZ pipeHorizontalDirection = new XYZ(dir.X, dir.Y, 0.0).Normalize(); //XYZ pipeHorizontalDirection = new XYZ(dir.X, dir.Y, 0.0); XYZ connectorDirection = -conOnFamilyToConnect.CoordinateSystem.BasisZ; double zRotationAngle = pipeHorizontalDirection.AngleTo(connectorDirection); Transform trf = Transform.CreateRotationAtPoint(XYZ.BasisZ, zRotationAngle, placementPoint); XYZ testRotation = trf.OfVector(connectorDirection).Normalize(); if (Math.Abs(testRotation.DotProduct(pipeHorizontalDirection) - 1) > 0.00001) { zRotationAngle = -zRotationAngle; } Line axis = Line.CreateBound(placementPoint, placementPoint + XYZ.BasisZ); ElementTransformUtils.RotateElement(element.Document, element.Id, axis, zRotationAngle); //Parameter comments = element.get_Parameter(BuiltInParameter.ALL_MODEL_INSTANCE_COMMENTS); //comments.Set("Horizontal only"); // Need to rotate vertically? if (Math.Abs(dir.DotProduct(XYZ.BasisZ)) > 0.000001) { // if pipe is straight up and down, // kludge it my way else if (dir.X.Round3() == 0 && dir.Y.Round3() == 0 && dir.Z.Round3() != 0) { XYZ yaxis = new XYZ(0.0, 1.0, 0.0); //XYZ yaxis = dir.CrossProduct(connectorDirection); double rotationAngle = dir.AngleTo(yaxis); //double rotationAngle = 90; if (dir.Z.Equals(1)) { rotationAngle = -rotationAngle; } axis = Line.CreateBound(placementPoint, new XYZ(placementPoint.X, placementPoint.Y + 5, placementPoint.Z)); ElementTransformUtils.RotateElement(element.Document, element.Id, axis, rotationAngle); //comments.Set("Vertical!"); } else { #region sloped pipes double rotationAngle = dir.AngleTo(pipeHorizontalDirection); XYZ normal = pipeHorizontalDirection.CrossProduct(XYZ.BasisZ); trf = Transform.CreateRotationAtPoint(normal, rotationAngle, placementPoint); testRotation = trf.OfVector(dir).Normalize(); if (Math.Abs(testRotation.DotProduct(pipeHorizontalDirection) - 1) < 0.00001) { rotationAngle = -rotationAngle; } axis = Line.CreateBound(placementPoint, placementPoint + normal); ElementTransformUtils.RotateElement(element.Document, element.Id, axis, rotationAngle); //comments.Set("Sloped"); #endregion } } #endregion }
/// <summary> /// Determine the plane that a given curve resides in and return its normal vector. /// Ask the curve for its start and end points and some point in the middle. /// The latter can be obtained by asking the curve for its parameter range and /// evaluating it in the middle, or by tessellation. In case of tessellation, /// you could iterate through the tessellation points and use each one together /// with the start and end points to try and determine a valid plane. /// Once one is found, you can add debug assertions to ensure that the other /// tessellation points (if there are any more) are in the same plane. /// In the case of the line, the tessellation only returns two points. /// I once heard that that is the only element that can do that, all /// non-linear curves return at least three. So you could use this property /// to determine that a line is a line (and add an assertion as well, if you like). /// Update, later: please note that the Revit API provides an overload of the /// NewPlane method taking a CurveArray argument. /// </summary> XYZ GetCurveNormal(Curve curve) { IList <XYZ> pts = curve.Tessellate(); int n = pts.Count; Debug.Assert(1 < n, "expected at least two points " + "from curve tessellation"); XYZ p = pts[0]; XYZ q = pts[n - 1]; XYZ v = q - p; XYZ w, normal = null; if (2 == n) { Debug.Assert(curve is Line, "expected non-line element to have " + "more than two tessellation points"); // For non-vertical lines, use Z axis to // span the plane, otherwise Y axis: double dxy = Math.Abs(v.X) + Math.Abs(v.Y); w = (dxy > Util.TolPointOnPlane) ? XYZ.BasisZ : XYZ.BasisY; normal = v.CrossProduct(w).Normalize(); } else { int i = 0; while (++i < n - 1) { w = pts[i] - p; normal = v.CrossProduct(w); if (!normal.IsZeroLength()) { normal = normal.Normalize(); break; } } #if DEBUG { XYZ normal2; while (++i < n - 1) { w = pts[i] - p; normal2 = v.CrossProduct(w); Debug.Assert(normal2.IsZeroLength() || Util.IsZero(normal2.AngleTo(normal)), "expected all points of curve to " + "lie in same plane"); } } #endif // DEBUG } return(normal); }
/// <summary> /// Get information about the structural member axis, if possible. /// Here we will do the following: /// - Calculate the Axis LCS by using the Axis curve itself with the StartPoint of the curve to be the origin and the tangent of the curve at origin as the direction /// - The curve is then transformed to its LCS /// </summary> /// <param name="element">The structural member element.</param> /// <returns>The StructuralMemberAxisInfo structure, or null if the structural member has no axis, or it is not a Line or Arc.</returns> public static StructuralMemberAxisInfo GetStructuralMemberAxisTransform(Element element) { StructuralMemberAxisInfo axisInfo = null; Transform orientTrf = Transform.Identity; XYZ structMemberDirection = null; XYZ projDir = null; Curve curve = null; LocationCurve locCurve = element.Location as LocationCurve; bool canExportAxis = (locCurve != null); if (canExportAxis) { // Here we are defining the Axis Curve LCS by using the start point (for line) as the origin. // For the Arc, the center is the origin // The Structural member direction is the X-Axis curve = locCurve.Curve; if (curve is Line) { Line line = curve as Line; XYZ planeY; XYZ LCSorigin = line.GetEndPoint(0); structMemberDirection = line.Direction.Normalize(); if (Math.Abs(structMemberDirection.Z) < 0.707) // approx 1.0/sqrt(2.0) { planeY = XYZ.BasisZ.CrossProduct(structMemberDirection).Normalize(); } else { planeY = XYZ.BasisX.CrossProduct(structMemberDirection).Normalize(); } projDir = structMemberDirection.CrossProduct(planeY); orientTrf.BasisX = structMemberDirection; orientTrf.BasisY = planeY; orientTrf.BasisZ = projDir; orientTrf.Origin = LCSorigin; } else if (curve is Arc) { XYZ yDir; Arc arc = curve as Arc; structMemberDirection = arc.XDirection.Normalize(); yDir = arc.YDirection.Normalize(); projDir = arc.Normal; XYZ center = arc.Center; if (!MathUtil.IsAlmostZero(structMemberDirection.DotProduct(yDir))) { // ensure that beamDirection and yDir are orthogonal yDir = projDir.CrossProduct(structMemberDirection); yDir = yDir.Normalize(); } orientTrf.BasisX = structMemberDirection; orientTrf.BasisY = yDir; orientTrf.BasisZ = projDir; orientTrf.Origin = center; } else { canExportAxis = false; } } if (canExportAxis) { axisInfo = new StructuralMemberAxisInfo(); axisInfo.Axis = curve.CreateTransformed(orientTrf.Inverse); // transform the curve into its LCS axisInfo.AxisDirection = orientTrf.BasisX; // We define here the Axis Curve to be following the X-axis axisInfo.AxisNormal = orientTrf.BasisZ; axisInfo.LCSAsTransform = orientTrf; } return(axisInfo); }
/// <summary> /// Return the normal of a plane /// spanned by the two given vectors. /// </summary> static XYZ GetNormal( XYZ v1, XYZ v2 ) { return v1 .CrossProduct( v2 ) .Normalize(); }
// return null if parent should be completely clipped. // TODO: determine whether or not to use face boundary. private static IFCAnyHandle ProcessClippingFace(ExporterIFC exporterIFC, CurveLoop outerBoundary, Plane boundaryPlane, Plane extrusionBasePlane, XYZ extrusionDirection, IFCRange range, bool useFaceBoundary, IFCAnyHandle bodyItemHnd) { if (outerBoundary == null || boundaryPlane == null) { throw new Exception("Invalid face boundary."); } double clippingSlant = boundaryPlane.Normal.DotProduct(extrusionDirection); if (useFaceBoundary) { if (MathUtil.IsAlmostZero(clippingSlant)) { return(bodyItemHnd); } } bool clipCompletely; if (!IsInRange(range, outerBoundary, boundaryPlane, extrusionDirection, out clipCompletely)) { return(clipCompletely ? null : bodyItemHnd); } if (MathUtil.IsAlmostZero(clippingSlant)) { throw new Exception("Can't create clipping perpendicular to extrusion."); } IFCFile file = exporterIFC.GetFile(); XYZ scaledOrig = ExporterIFCUtils.TransformAndScalePoint(exporterIFC, boundaryPlane.Origin); XYZ scaledNorm = ExporterIFCUtils.TransformAndScaleVector(exporterIFC, boundaryPlane.Normal); XYZ scaledXDir = ExporterIFCUtils.TransformAndScaleVector(exporterIFC, boundaryPlane.XVec); IFCAnyHandle planeAxisHnd = ExporterUtil.CreateAxis(file, scaledOrig, scaledNorm, scaledXDir); IFCAnyHandle surfHnd = IFCInstanceExporter.CreatePlane(file, planeAxisHnd); IFCAnyHandle clippedBodyItemHnd = null; IFCAnyHandle halfSpaceHnd = null; if (useFaceBoundary) { IFCAnyHandle boundedCurveHnd; if (boundaryPlane != null) { XYZ projScaledOrigin = ExporterIFCUtils.TransformAndScalePoint(exporterIFC, extrusionBasePlane.Origin); XYZ projScaledX = ExporterIFCUtils.TransformAndScaleVector(exporterIFC, extrusionBasePlane.XVec); XYZ projScaledY = ExporterIFCUtils.TransformAndScaleVector(exporterIFC, extrusionBasePlane.YVec); XYZ projScaledNorm = projScaledX.CrossProduct(projScaledY); Plane projScaledPlane = new Plane(projScaledX, projScaledY, projScaledOrigin); IList <UV> polylinePts = TransformAndProjectCurveLoopToPlane(exporterIFC, outerBoundary, projScaledPlane); polylinePts.Add(polylinePts[0]); boundedCurveHnd = ExporterUtil.CreatePolyline(file, polylinePts); IFCAnyHandle boundedAxisHnd = ExporterUtil.CreateAxis(file, projScaledOrigin, projScaledNorm, projScaledX); halfSpaceHnd = IFCInstanceExporter.CreatePolygonalBoundedHalfSpace(file, boundedAxisHnd, boundedCurveHnd, surfHnd, false); } else { throw new Exception("Can't create non-polygonal face boundary."); } } else { halfSpaceHnd = IFCInstanceExporter.CreateHalfSpaceSolid(file, surfHnd, false); } if (halfSpaceHnd == null) { throw new Exception("Can't create clipping."); } clippedBodyItemHnd = IFCInstanceExporter.CreateBooleanClippingResult(file, IFCBooleanOperator.Difference, bodyItemHnd, halfSpaceHnd); return(clippedBodyItemHnd); }
private static Autodesk.Revit.DB.ModelText CreateModelText(XYZ normal, XYZ position, XYZ up, string text, ModelTextType mtt, double depth) { Autodesk.Revit.DB.ModelText mt = null; var xAxis = normal.CrossProduct(up).Normalize(); var yAxis = normal.CrossProduct(xAxis).Normalize(); var plane = new Autodesk.Revit.DB.Plane(xAxis, yAxis, position); var sp = Autodesk.Revit.DB.SketchPlane.Create(dynRevitSettings.Doc.Document, plane); mt = dynRevitSettings.Doc.Document.FamilyCreate.NewModelText(text, mtt, sp, position, HorizontalAlign.Left, depth); return mt; }
/// <summary> /// Get information about the beam axis, if possible. /// </summary> /// <param name="element">The beam element.</param> /// <returns>The BeamAxisInfo structure, or null if the beam has no axis, or it is not a Line or Arc.</returns> private static BeamAxisInfo GetBeamAxisTransform(Element element) { BeamAxisInfo axisInfo = null; Transform orientTrf = Transform.Identity; XYZ beamDirection = null; XYZ projDir = null; Curve curve = null; LocationCurve locCurve = element.Location as LocationCurve; bool canExportAxis = (locCurve != null); if (canExportAxis) { curve = locCurve.Curve; if (curve is Line) { Line line = curve as Line; XYZ planeY, planeOrig; planeOrig = line.GetEndPoint(0); beamDirection = line.Direction; beamDirection = beamDirection.Normalize(); if (Math.Abs(beamDirection.Z) < 0.707) // approx 1.0/sqrt(2.0) { planeY = XYZ.BasisZ.CrossProduct(beamDirection); } else { planeY = XYZ.BasisX.CrossProduct(beamDirection); } planeY = planeY.Normalize(); projDir = beamDirection.CrossProduct(planeY); orientTrf.BasisX = beamDirection; orientTrf.BasisY = planeY; orientTrf.BasisZ = projDir; orientTrf.Origin = planeOrig; } else if (curve is Arc) { XYZ yDir, center; Arc arc = curve as Arc; beamDirection = arc.XDirection; yDir = arc.YDirection; projDir = arc.Normal; center = arc.Center; beamDirection = beamDirection.Normalize(); yDir = yDir.Normalize(); if (!MathUtil.IsAlmostZero(beamDirection.DotProduct(yDir))) { // ensure that beamDirection and yDir are orthogonal yDir = projDir.CrossProduct(beamDirection); yDir = yDir.Normalize(); } orientTrf.BasisX = beamDirection; orientTrf.BasisY = yDir; orientTrf.BasisZ = projDir; orientTrf.Origin = center; } else { canExportAxis = false; } } if (canExportAxis) { axisInfo = new BeamAxisInfo(); axisInfo.Axis = curve; axisInfo.AxisDirection = beamDirection; axisInfo.AxisNormal = projDir; axisInfo.LCSAsTransform = orientTrf; } return(axisInfo); }
private ModelCurve MakeLine(Document familyDoc, XYZ ptA, XYZ ptB) { try { Application app = familyDoc.Application; Line line = app.Create.NewLine(ptA, ptB, true); XYZ norm = ptA.CrossProduct(ptB); if (norm.IsZeroLength()) norm = XYZ.BasisZ; Plane plane = app.Create.NewPlane(norm, ptB); SketchPlane skplane = familyDoc.FamilyCreate.NewSketchPlane(plane); return familyDoc.FamilyCreate.NewModelCurve(line, skplane); } catch (Exception ex) { TaskDialog.Show("Line Error", ex.Message); return null; } }
public Result Execute( ExternalCommandData commandData, ref String message, ElementSet elements) { UIApplication app = commandData.Application; UIDocument uidoc = app.ActiveUIDocument; Document doc = uidoc.Document; Element e = Util.SelectSingleElement( uidoc, "a line or wall"); LocationCurve curve = null; if (null == e) { message = "No element selected"; } else { curve = e.Location as LocationCurve; } if (null == curve) { message = "No curve available"; } else { XYZ p = curve.Curve.GetEndPoint(0); XYZ q = curve.Curve.GetEndPoint(1); Debug.WriteLine("Start point " + Util.PointString(p)); Debug.WriteLine("End point " + Util.PointString(q)); // the angle between the vectors from the project origin // to the start and end points of the wall is pretty irrelevant: double a = p.AngleTo(q); Debug.WriteLine( "Angle between start and end point vectors = " + Util.AngleString(a)); XYZ v = q - p; XYZ vx = XYZ.BasisX; a = vx.AngleTo(v); Debug.WriteLine( "Angle between points measured from X axis = " + Util.AngleString(a)); XYZ z = XYZ.BasisZ; a = vx.AngleOnPlaneTo(v, z); Debug.WriteLine( "Angle around measured from X axis = " + Util.AngleString(a)); if (e is Wall) { Wall wall = e as Wall; XYZ w = z.CrossProduct(v).Normalize(); if (wall.Flipped) { w = -w; } a = vx.AngleOnPlaneTo(w, z); Debug.WriteLine( "Angle pointing out of wall = " + Util.AngleString(a)); } } foreach (ProjectLocation location in doc.ProjectLocations) { //ProjectPosition projectPosition // = location.get_ProjectPosition( XYZ.Zero ); // 2017 ProjectPosition projectPosition = location.GetProjectPosition(XYZ.Zero); // 2018 double pna = projectPosition.Angle; Debug.WriteLine( "Angle between project north and true north " + Util.AngleString(pna)); } return(Result.Failed); }
/* * /// <summary> * /// Return the average of a list of values. * /// Prerequisite: the underlying class T must supply * /// operator*(double) and operator+(const T &). * /// </summary> * T Average<T>( List<T> a ) * { * T result; * bool first = true; * foreach( T x in a ) * { * if( first ) * { * result = x; * } * else * { * result += x; * } * } * return result * ( 1.0 / a.Count ); * } * * XYZ Sum( List<XYZ> a ) * { * XYZ sum = XYZ.Zero; * foreach( XYZ x in a ) * { * sum += x; * } * return sum; * } * * XYZ Average( List<XYZ> a ) * { * return Sum( a ) * (1.0 / a.Count); * } * * XYZ TriangleCenter( List<XYZ> pts ) * { * Debug.Assert( 3 == pts.Count, "expected three points in triangle" ); * return Average( pts ); * } */ /// <summary> /// Return the plane properties of a given polygon, /// i.e. the plane normal, area, and its distance /// from the origin. Cf. also GetSignedPolygonArea. /// </summary> internal static bool GetPolygonPlane( List <XYZ> polygon, out XYZ normal, out double dist, out double area) { normal = XYZ.Zero; dist = area = 0.0; int n = (null == polygon) ? 0 : polygon.Count; bool rc = (2 < n); if (3 == n) { // the general case returns a wrong result for the triangle // ((-1 -1 -1) (1 -1 -1) (-1 -1 1)), so implement specific // code for triangle: XYZ a = polygon[0]; XYZ b = polygon[1]; XYZ c = polygon[2]; XYZ v = b - a; normal = v.CrossProduct(c - a); dist = normal.DotProduct(a); } else if (4 == n) { // more efficient code for 4-sided polygons XYZ a = polygon[0]; XYZ b = polygon[1]; XYZ c = polygon[2]; XYZ d = polygon[3]; normal = new XYZ( (c.Y - a.Y) * (d.Z - b.Z) + (c.Z - a.Z) * (b.Y - d.Y), (c.Z - a.Z) * (d.X - b.X) + (c.X - a.X) * (b.Z - d.Z), (c.X - a.X) * (d.Y - b.Y) + (c.Y - a.Y) * (b.X - d.X)); dist = 0.25 * (normal.X * (a.X + b.X + c.X + d.X) + normal.Y * (a.Y + b.Y + c.Y + d.Y) + normal.Z * (a.Z + b.Z + c.Z + d.Z)); } else if (4 < n) { // general case for n-sided polygons XYZ a; XYZ b = polygon[n - 2]; XYZ c = polygon[n - 1]; XYZ s = XYZ.Zero; for (int i = 0; i < n; ++i) { a = b; b = c; c = polygon[i]; normal = new XYZ( normal.X + b.Y * (c.Z - a.Z), normal.Y + b.Z * (c.X - a.X), normal.Z + b.X * (c.Y - a.Y)); s += c; } dist = s.DotProduct(normal) / n; } if (rc) { // the polygon area is half of the length // of the non-normalized normal vector of the plane: double length = normal.GetLength(); rc = !Util.IsZero(length); Debug.Assert(rc); if (rc) { normal /= length; dist /= length; area = 0.5 * length; } } return(rc); }
/// <summary> /// Exports a beam to IFC beam. /// </summary> /// <param name="exporterIFC"> /// The ExporterIFC object. /// </param> /// <param name="element"> /// The element to be exported. /// </param> /// <param name="geometryElement"> /// The geometry element. /// </param> /// <param name="productWrapper"> /// The IFCProductWrapper. /// </param> public static void ExportBeam(ExporterIFC exporterIFC, Element element, GeometryElement geometryElement, IFCProductWrapper productWrapper) { if (geometryElement == null) { return; } IFCFile file = exporterIFC.GetFile(); double scale = exporterIFC.LinearScale; using (IFCTransaction transaction = new IFCTransaction(file)) { LocationCurve locCurve = element.Location as LocationCurve; Transform orientTrf = Transform.Identity; bool canExportAxis = (locCurve != null); IFCAnyHandle axisRep = null; XYZ beamDirection = null; XYZ projDir = null; Curve curve = null; Plane plane = null; if (canExportAxis) { curve = locCurve.Curve; if (curve is Line) { Line line = curve as Line; XYZ planeY, planeOrig; planeOrig = line.get_EndPoint(0); beamDirection = line.Direction; if (Math.Abs(beamDirection.Z) < 0.707) // approx 1.0/sqrt(2.0) { planeY = XYZ.BasisZ.CrossProduct(beamDirection); } else { planeY = XYZ.BasisX.CrossProduct(beamDirection); } planeY = planeY.Normalize(); projDir = beamDirection.CrossProduct(planeY); plane = new Plane(beamDirection, planeY, planeOrig); orientTrf.BasisX = beamDirection; orientTrf.BasisY = planeY; orientTrf.BasisZ = projDir; orientTrf.Origin = planeOrig; } else if (curve is Arc) { XYZ yDir, center; Arc arc = curve as Arc; beamDirection = arc.XDirection; yDir = arc.YDirection; projDir = arc.Normal; center = arc.Center; plane = new Plane(beamDirection, yDir, center); orientTrf.BasisX = beamDirection; orientTrf.BasisY = yDir; orientTrf.BasisZ = projDir; orientTrf.Origin = center; } else { canExportAxis = false; } } using (IFCPlacementSetter setter = IFCPlacementSetter.Create(exporterIFC, element, null, canExportAxis ? orientTrf : null, ElementId.InvalidElementId)) { IFCAnyHandle localPlacement = setter.GetPlacement(); SolidMeshGeometryInfo solidMeshInfo = GeometryUtil.GetSolidMeshGeometry(geometryElement, Transform.Identity); using (IFCExtrusionCreationData extrusionCreationData = new IFCExtrusionCreationData()) { extrusionCreationData.SetLocalPlacement(localPlacement); if (canExportAxis && (orientTrf.BasisX != null)) { extrusionCreationData.CustomAxis = beamDirection; extrusionCreationData.PossibleExtrusionAxes = IFCExtrusionAxes.TryCustom; } else { extrusionCreationData.PossibleExtrusionAxes = IFCExtrusionAxes.TryXY; } IList <Solid> solids = solidMeshInfo.GetSolids(); IList <Mesh> meshes = solidMeshInfo.GetMeshes(); ElementId catId = CategoryUtil.GetSafeCategoryId(element); // The representation handle generated from one of the methods below. IFCAnyHandle repHnd = null; // The list of materials in the solids or meshes. ICollection <ElementId> materialIds = new HashSet <ElementId>(); // If we can only export as a BRep, there may be an offset to make the BRep local coordinate system // be near the origin. This offset will be used to move the axis to the new LCS. Transform brepOffsetTransform = null; // If we have a beam with a Linear location line that only has one solid geometry, // we will try to use the ExtrusionAnalyzer to generate an extrusion with 0 or more clippings. // This code is currently limited in that it will not process beams with openings, so we // use other methods below if this one fails. if (solids.Count == 1 && meshes.Count == 0 && (canExportAxis && (curve is Line))) { IList <Solid> splitVolumes = SolidUtils.SplitVolumes(solids[0]); if (splitVolumes.Count == 1) { bool completelyClipped; beamDirection = orientTrf.BasisX; Plane beamExtrusionPlane = new Plane(orientTrf.BasisY, orientTrf.BasisZ, orientTrf.Origin); repHnd = ExtrusionExporter.CreateExtrusionWithClipping(exporterIFC, element, catId, solids[0], beamExtrusionPlane, beamDirection, null, out completelyClipped); if (completelyClipped) { return; } if (!IFCAnyHandleUtil.IsNullOrHasNoValue(repHnd)) { ElementId materialId = BodyExporter.GetBestMaterialIdForGeometry(solids[0], exporterIFC); if (materialId != ElementId.InvalidElementId) { materialIds.Add(materialId); } } } } if (IFCAnyHandleUtil.IsNullOrHasNoValue(repHnd)) { BodyData bodyData = null; BodyExporterOptions bodyExporterOptions = new BodyExporterOptions(true); if (solids.Count > 0 || meshes.Count > 0) { bodyData = BodyExporter.ExportBody(element.Document.Application, exporterIFC, element, catId, solids, meshes, bodyExporterOptions, extrusionCreationData); } else { IList <GeometryObject> geomlist = new List <GeometryObject>(); geomlist.Add(geometryElement); bodyData = BodyExporter.ExportBody(element.Document.Application, exporterIFC, element, catId, geomlist, bodyExporterOptions, extrusionCreationData); } repHnd = bodyData.RepresentationHnd; materialIds = bodyData.MaterialIds; brepOffsetTransform = bodyData.BrepOffsetTransform; } if (IFCAnyHandleUtil.IsNullOrHasNoValue(repHnd)) { extrusionCreationData.ClearOpenings(); return; } IList <IFCAnyHandle> representations = new List <IFCAnyHandle>(); if (canExportAxis) { XYZ curveOffset = new XYZ(0, 0, 0); if (brepOffsetTransform != null) { curveOffset = -brepOffsetTransform.Origin / scale; } else { // Note that we do not have to have any scaling adjustment here, since the curve origin is in the // same internal coordinate system as the curve. curveOffset = -plane.Origin; } Plane offsetPlane = new Plane(plane.XVec, plane.YVec, XYZ.Zero); IFCGeometryInfo info = IFCGeometryInfo.CreateCurveGeometryInfo(exporterIFC, offsetPlane, projDir, false); ExporterIFCUtils.CollectGeometryInfo(exporterIFC, info, curve, curveOffset, true); IList <IFCAnyHandle> axis_items = info.GetCurves(); if (axis_items.Count > 0) { string identifierOpt = "Axis"; // this is by IFC2x2 convention, not temporary string representationTypeOpt = "Curve2D"; // this is by IFC2x2 convention, not temporary axisRep = RepresentationUtil.CreateShapeRepresentation(exporterIFC, element, catId, exporterIFC.Get3DContextHandle(identifierOpt), identifierOpt, representationTypeOpt, axis_items); representations.Add(axisRep); } } representations.Add(repHnd); IFCAnyHandle prodRep = IFCInstanceExporter.CreateProductDefinitionShape(file, null, null, representations); string instanceGUID = ExporterIFCUtils.CreateGUID(element); string origInstanceName = exporterIFC.GetName(); string instanceName = NamingUtil.GetNameOverride(element, origInstanceName); string instanceDescription = NamingUtil.GetDescriptionOverride(element, null); string instanceObjectType = NamingUtil.GetObjectTypeOverride(element, NamingUtil.CreateIFCObjectName(exporterIFC, element)); string instanceElemId = NamingUtil.CreateIFCElementId(element); IFCAnyHandle beam = IFCInstanceExporter.CreateBeam(file, instanceGUID, exporterIFC.GetOwnerHistoryHandle(), instanceName, instanceDescription, instanceObjectType, extrusionCreationData.GetLocalPlacement(), prodRep, instanceElemId); productWrapper.AddElement(beam, setter, extrusionCreationData, LevelUtil.AssociateElementToLevel(element)); OpeningUtil.CreateOpeningsIfNecessary(beam, element, extrusionCreationData, exporterIFC, extrusionCreationData.GetLocalPlacement(), setter, productWrapper); FamilyTypeInfo typeInfo = new FamilyTypeInfo(); typeInfo.ScaledDepth = extrusionCreationData.ScaledLength; typeInfo.ScaledArea = extrusionCreationData.ScaledArea; typeInfo.ScaledInnerPerimeter = extrusionCreationData.ScaledInnerPerimeter; typeInfo.ScaledOuterPerimeter = extrusionCreationData.ScaledOuterPerimeter; PropertyUtil.CreateBeamColumnBaseQuantities(exporterIFC, beam, element, typeInfo); if (materialIds.Count != 0) { CategoryUtil.CreateMaterialAssociations(element.Document, exporterIFC, beam, materialIds); } PropertyUtil.CreateInternalRevitPropertySets(exporterIFC, element, productWrapper); } } transaction.Commit(); } }
public virtual Result Execute( ExternalCommandData commandData, ref string message, ElementSet elements) { UIApplication app = commandData.Application; Document doc = app.ActiveUIDocument.Document; Autodesk.Revit.Creation.Application ac = app.Application.Create; Transaction transaction = new Transaction(doc); transaction.Start("TestWall"); XYZ[] pts = new XYZ[] { new XYZ(5.675844469, 8.769334161, -5.537348007), new XYZ(5.665137820, 8.771332255, 2.956630685), new XYZ(7.672569880, 8.396698044, 2.959412671), }; //CurveArray profile = new CurveArray(); // 2012 List <Curve> profile = new List <Curve>(pts.Length); // 2013 XYZ q = pts[pts.Length - 1]; foreach (XYZ p in pts) { //profile.Append( CreateLine( ac, q, p, true ) ); // 2012 //profile.Add( CreateLine( ac, q, p, true ) ); // 2013 profile.Add(Line.CreateBound(q, p)); // 2014 q = p; } XYZ t1 = pts[0] - pts[1]; XYZ t2 = pts[1] - pts[2]; XYZ normal2 = t1.CrossProduct(t2); normal2 = normal2.Normalize(); // Verify this plane is vertical to plane XOY if (!IsVertical(normal2, XYZ.BasisZ)) { System.Windows.Forms.MessageBox.Show("not vertical"); } SketchPlane sketchPlane = CreateSketchPlane( doc, normal2, pts[0]); //CreateModelCurveArray( // 2012 // doc, profile, sketchPlane ); foreach (Curve c in profile) // 2013 { doc.Create.NewModelCurve(c, sketchPlane); } WallType wallType = new FilteredElementCollector(doc) .OfClass(typeof(WallType)) .First <Element>() as WallType; Level level = new FilteredElementCollector(doc) .OfClass(typeof(Level)) .First <Element>( e => e.Name.Equals("Level 1")) as Level; //Wall wall = doc.Create.NewWall( // 2012 // profile, wallType, level, true, normal2 ); Wall wall = Wall.Create(doc, profile, wallType.Id, level.Id, true, normal2); transaction.Commit(); return(Result.Succeeded); }
/// <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); }
private void CreateTessellatedShapeInternal(IFCImportShapeEditScope shapeEditScope, Transform scaledLcs) { TessellatedShapeBuilderScope tsBuilderScope = shapeEditScope.BuilderScope as TessellatedShapeBuilderScope; if (tsBuilderScope == null) { throw new InvalidOperationException("Expect a TessellatedShapeBuilderScope, but get a BrepBuilderScope instead"); } IList <XYZ> loopVertices = Bound.LoopVertices; int count = 0; if (loopVertices == null || ((count = loopVertices.Count) == 0)) { throw new InvalidOperationException("#" + Id + ": missing loop vertices, ignoring."); } if (count < 3) { throw new InvalidOperationException("#" + Id + ": too few loop vertices (" + count + "), ignoring."); } if (!Orientation) { loopVertices.Reverse(); } // Apply the transform IList <XYZ> transformedVertices = new List <XYZ>(); foreach (XYZ vertex in loopVertices) { transformedVertices.Add(scaledLcs.OfPoint(vertex)); } // Check that the loop vertices don't contain points that are very close to one another; // if so, throw the point away and hope that the TessellatedShapeBuilder can repair the result. // Warn in this case. If the entire boundary is bad, report an error and don't add the loop vertices. List <XYZ> validVertices = null; for (int pass = 0; pass < 2; pass++) { if (pass == 1 && !tsBuilderScope.RevertToMeshIfPossible()) { break; } IFCGeometryUtil.CheckAnyDistanceVerticesWithinTolerance(Id, shapeEditScope, transformedVertices, out validVertices); count = validVertices.Count; if (count >= 3 || !IsOuter) { break; } } // 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 = (count < 3); if (bPotentiallyAbortFace) { Importer.TheLog.LogComment(Id, "Too few distinct loop vertices (" + count + "), ignoring.", false); } else { // Last check: check to see if the vertices are actually planar. If not, for the vertices to be planar. if (!tsBuilderScope.AddLoopVertices(Id, validVertices)) // We are not going to be particularly fancy about how we pick the plane. if (count > 3) { XYZ planeNormal = null; bool foundGoodNormal = false; XYZ firstPoint = validVertices[0]; XYZ secondPoint = validVertices[1]; XYZ firstDir = secondPoint - firstPoint; for (int index = 2; index <= count; index++) { XYZ thirdPoint = validVertices[(index % count)]; planeNormal = firstDir.CrossProduct(thirdPoint - firstPoint); if (planeNormal.GetLength() > 0.01) { planeNormal = planeNormal.Normalize(); foundGoodNormal = true; break; } firstPoint = secondPoint; secondPoint = thirdPoint; firstDir = secondPoint - firstPoint; } if (!foundGoodNormal) { // Even if we don't find a good normal, we will still see if the internal function can make sense of it. Importer.TheLog.LogComment(Id, "Bounded loop plane is likely non-planar, won't try to correct.", false); } else { double vertexEps = IFCImportFile.TheFile.Document.Application.VertexTolerance; for (int index = 0; index < count; index++) { XYZ pointOnPlane = validVertices[index] - (validVertices[index] - firstPoint).DotProduct(planeNormal) * planeNormal; double distance = pointOnPlane.DistanceTo(validVertices[index]); if (distance > vertexEps * 10.0) { Importer.TheLog.LogComment(Id, "Bounded loop plane is non-planar, can't correct.", false); bPotentiallyAbortFace = true; break; } else if (distance > vertexEps) { Importer.TheLog.LogComment(Id, "Bounded loop plane is slightly non-planar, correcting.", false); validVertices[index] = pointOnPlane; } } } } if (!bPotentiallyAbortFace) { bPotentiallyAbortFace = !tsBuilderScope.AddLoopVertices(Id, validVertices); } } if (bPotentiallyAbortFace && IsOuter) { tsBuilderScope.AbortCurrentFace(); } }
/// <summary> /// Given a curve element, determine three parallel /// curves on the right, left and above, offset by /// a given radius or half diameter. /// </summary> void CreateConduitOffsets( Element conduit, double diameter, double distance) { Document doc = conduit.Document; // Given element location curve var obj = conduit.Location as LocationCurve; XYZ start = obj.Curve.GetEndPoint(0); XYZ end = obj.Curve.GetEndPoint(1); XYZ vx = end - start; // Offsets double radius = 0.5 * diameter; double offset_lr = radius; double offset_up = radius * Math.Sqrt(3); // Assume vx is horizontal to start with XYZ vz = XYZ.BasisZ; XYZ vy = vz.CrossProduct(vx); XYZ start1 = start + offset_lr * vy; XYZ start2 = start - offset_lr * vy; XYZ start3 = start + offset_up * vz; XYZ end1 = start1 + vx; XYZ end2 = start2 + vx; XYZ end3 = start3 + vx; // Confusing sample code from // https://forums.autodesk.com/t5/revit-api-forum/offset-conduit-only-by-z-axis/m-p/9972671 var L = Math.Sqrt((start.X - end.X) * (start.X - end.X) + (start.Y - end.Y) * (start.Y - end.Y)); double x1startO = start.X + distance * (end.Y - start.Y) / L; double x1endO = end.X + distance * (end.Y - start.Y) / L; double y1startO = start.Y + distance * (start.X - end.X) / L; double y1end0 = end.Y + distance * (start.X - end.X) / L; Conduit conduit1 = Conduit.Create(doc, conduit.GetTypeId(), new XYZ(x1startO, y1startO, start.Z), new XYZ(x1endO, y1end0, end.Z), conduit.LevelId); conduit1.get_Parameter(BuiltInParameter.RBS_CONDUIT_DIAMETER_PARAM).Set(diameter); double x2startO = start.X - distance * (end.Y - start.Y) / L; double x2endO = end.X - distance * (end.Y - start.Y) / L; double y2startO = start.Y - distance * (start.X - end.X) / L; double y2end0 = end.Y - distance * (start.X - end.X) / L; Conduit conduit2 = Conduit.Create(doc, conduit.GetTypeId(), new XYZ(x2startO, y2startO, start.Z), new XYZ(x2endO, y2end0, end.Z), conduit.LevelId); conduit2.get_Parameter(BuiltInParameter.RBS_CONDUIT_DIAMETER_PARAM).Set(diameter); XYZ p0 = new XYZ(start.X - (end.Y - start.Y) * (1 / obj.Curve.ApproximateLength), start.Y + (end.X - start.X) * (1 / obj.Curve.ApproximateLength), start.Z); XYZ p1 = new XYZ(start.X + (end.Y - start.Y) * (1 / obj.Curve.ApproximateLength), start.Y - (end.X - start.X) * (1 / obj.Curve.ApproximateLength), start.Z); Conduit conduit3; Curve copyCurve = obj.Curve.CreateOffset(-diameter * Math.Sqrt(3) / 2, Line.CreateBound(p0, p1).Direction); conduit3 = Conduit.Create(doc, conduit.GetTypeId(), copyCurve.GetEndPoint(0), copyCurve.GetEndPoint(1), conduit.LevelId); conduit3.get_Parameter(BuiltInParameter.RBS_CONDUIT_DIAMETER_PARAM).Set(diameter); }
public static void Draw(Document doc, Element elem, String Section_Name, double LeftOffset, double RightOffset, double TopOffset, double BottomOffset, double NearClipOffset, double FarClipOffset) { ElementId elemid = elem.Id; //= refe.ElementId; XYZ Cen_pt = ((LocationPoint)elem.Location).Point; XYZ Y_Plane = new XYZ(0, -1, 0); ViewFamilyType view = KJU.Filter.ElementFiltering(doc, typeof(ViewFamilyType), "Section", Section_Name, null) as ViewFamilyType; FamilyInstance inst = elem as FamilyInstance; Transform tr = inst.GetTransform(); Parameter Elec_PanelName = inst.get_Parameter(BuiltInParameter.RBS_ELEC_PANEL_NAME); string Elec_Equipment_Name = null; Room room = inst.Room; if (null != room) { Elec_Equipment_Name = room.Name.Substring(0, room.Name.Length - room.Number.Length - 1) + "-" + inst.get_Parameter(BuiltInParameter.ALL_MODEL_MARK).AsString(); } else { Elec_Equipment_Name = "Exterior" + "-" + inst.get_Parameter(BuiltInParameter.ALL_MODEL_MARK).AsString(); } double Half_Width = inst.GetParameters("##Width")[0].AsDouble() / 2.0, Half_Height = inst.GetParameters("##Height")[0].AsDouble() / 2.0; XYZ Right_Dir = tr.BasisX; XYZ St_Pt = tr.Origin - Right_Dir * Half_Width, End_Pt = tr.Origin + Right_Dir * Half_Width; XYZ v = St_Pt - End_Pt; double X_Angle = (End_Pt - St_Pt).AngleOnPlaneTo(XYZ.BasisX, XYZ.BasisZ); //TaskDialog.Show("Angle","Angle = " + Math.Round(X_Angle * 180 / Math.PI,5).ToString() // + " --- " + Elec_Equipment_Name); XYZ Min = new XYZ(-(Half_Width + LeftOffset), -(Half_Height + BottomOffset), NearClipOffset); XYZ Max = new XYZ(Half_Width + RightOffset, Half_Height + TopOffset, FarClipOffset); XYZ Orgin = End_Pt + 0.5 * v; XYZ X_Dir = v.Normalize(); XYZ Up_Dir = XYZ.BasisZ; XYZ View_Dir = X_Dir.CrossProduct(Up_Dir); Transform Sec_Tr = Transform.Identity; Sec_Tr.Origin = Orgin; Sec_Tr.BasisX = X_Dir; Sec_Tr.BasisY = Up_Dir; Sec_Tr.BasisZ = View_Dir; BoundingBoxXYZ sectionBox = new BoundingBoxXYZ(); sectionBox.Transform = Sec_Tr; sectionBox.Min = Min; sectionBox.Max = Max; ViewSection vs = null; using (Transaction tn = new Transaction(doc)) { tn.Start("Section"); try { vs = ViewSection.CreateSection(doc, view.Id, sectionBox); Elec_PanelName.Set(Elec_Equipment_Name); vs.Name = inst.get_Parameter(BuiltInParameter.RBS_ELEC_PANEL_NAME).AsString(); tn.Commit(); } catch (Exception) { return; } } }
public override Value Evaluate(FSharpList<Value> args) { View3D view = null; XYZ eye = (XYZ)((Value.Container)args[0]).Item; XYZ userUp = (XYZ)((Value.Container)args[1]).Item; XYZ direction = (XYZ)((Value.Container)args[2]).Item; XYZ side = new XYZ(); if (direction.IsAlmostEqualTo(userUp) || direction.IsAlmostEqualTo(userUp.Negate())) side = XYZ.BasisZ.CrossProduct(direction); else side = userUp.CrossProduct(direction); XYZ up = side.CrossProduct(direction); if (this.Elements.Any()) { Element e; if (dynUtils.TryGetElement(this.Elements[0], typeof(View3D), out e)) { view = e as View3D; if (!view.ViewDirection.IsAlmostEqualTo(direction)) { ViewOrientation3D orient = new ViewOrientation3D(eye, up, direction); view.SetOrientation(orient); view.SaveOrientationAndLock(); view.SetOrientation(orient); } } else { //create a new view view = Create3DView(eye, up, direction); Elements[0] = view.Id; } } else { view = Create3DView(eye, up, direction); Elements.Add(view.Id); } return Value.NewContainer(view); }
public static string SVGCreateDoor(View view, Element e, double rotAngle, XYZ newOrigin, string svgTypeName) { Options opt = new Options(); opt.View = view; List <Line> eleList = new List <Line>(); //<polygon points="50,0 150,0 150,10 50,10" stroke="red" stroke-width="1"/> GeometryElement obj = e.get_Geometry(opt); foreach (var o in obj) { GeometryInstance gi = o as GeometryInstance; foreach (GeometryObject instanceObj in gi.GetInstanceGeometry()) { if (instanceObj.GetType().ToString().Contains("Line")) { //TaskDialog.Show("r", instanceObj.GetType().ToString()); eleList.Add(instanceObj as Line); } } } LocationPoint loc = e.Location as LocationPoint; FamilyInstance fi = e as FamilyInstance; double length = fi.Symbol.get_Parameter(BuiltInParameter.DOOR_WIDTH).AsDouble(); Wall hostWall = fi.Host as Wall; LocationCurve lc = hostWall.Location as LocationCurve; XYZ wallDir = (lc.Curve.GetEndPoint(1) - lc.Curve.GetEndPoint(0)).Normalize(); XYZ wallPerp = wallDir.CrossProduct(XYZ.BasisZ); double width = hostWall.Width; XYZ corner1 = loc.Point + wallDir * length / 2 + wallPerp * width / 2; XYZ corner2 = loc.Point - wallDir * length / 2 + wallPerp * width / 2; XYZ corner3 = loc.Point - wallDir * length / 2 - wallPerp * width / 2; XYZ corner4 = loc.Point + wallDir * length / 2 - wallPerp * width / 2; List <XYZ> doorOpening = new List <XYZ> { corner1, corner2, corner3, corner4 }; IList <XYZ> transformedPoints = new List <XYZ>(); foreach (XYZ item in doorOpening) { transformedPoints.Add(MyTransform(item, rotAngle, newOrigin)); } string svg = $"<polygon points="; return(WriteSVG(transformedPoints, 304.8, svgTypeName)); }
public void GetPolygonsDefineFace() { Document doc = Wall.Document; Curve c = DrivingCurve; XYZ vecX = CheckGeometry.GetDirection(c); XYZ vecZ = XYZ.BasisZ; XYZ vecY = vecZ.CrossProduct(vecX); List <XYZ> ps = new List <XYZ> { c.GetEndPoint(0), c.GetEndPoint(1) }; List <XYZ> cenLengthPoints = new List <XYZ> { GeomUtil.OffsetPoint(ps[0], vecZ, 0), GeomUtil.OffsetPoint(ps[1], vecZ, 0), GeomUtil.OffsetPoint(ps[0], vecZ, Height), GeomUtil.OffsetPoint(ps[1], vecZ, Height) }; cenLengthPoints.Sort(new ZYXComparer()); XYZ temp = cenLengthPoints[2]; cenLengthPoints[2] = cenLengthPoints[3]; cenLengthPoints[3] = temp; XYZ midPoint = (ps[0] + ps[1]) / 2; ps = new List <XYZ> { GeomUtil.OffsetPoint(midPoint, vecY, -Width / 2), GeomUtil.OffsetPoint(midPoint, vecY, Width / 2) }; List <XYZ> cenWidthPoints = new List <XYZ> { GeomUtil.OffsetPoint(ps[0], vecZ, 0), GeomUtil.OffsetPoint(ps[1], vecZ, 0), GeomUtil.OffsetPoint(ps[0], vecZ, Height), GeomUtil.OffsetPoint(ps[1], vecZ, Height) }; cenWidthPoints.Sort(new ZYXComparer()); temp = cenWidthPoints[2]; cenWidthPoints[2] = cenWidthPoints[3]; cenWidthPoints[3] = temp; ps = new List <XYZ> { (cenLengthPoints[0] + cenLengthPoints[3]) / 2, (cenLengthPoints[1] + cenLengthPoints[2]) / 2 }; List <XYZ> cenHozPoints = new List <XYZ> { GeomUtil.OffsetPoint(ps[0], vecY, -Width / 2), GeomUtil.OffsetPoint(ps[1], vecY, -Width / 2), GeomUtil.OffsetPoint(ps[0], vecY, Width / 2), GeomUtil.OffsetPoint(ps[1], vecY, Width / 2) }; cenHozPoints.Sort(new ZYXComparer()); temp = cenHozPoints[2]; cenHozPoints[2] = cenHozPoints[3]; cenHozPoints[3] = temp; CentralVerticalLengthPolygon = new Polygon(cenLengthPoints); CentralVerticalWidthPolygon = new Polygon(cenWidthPoints); CentralHorizontalPolygon = new Polygon(cenHozPoints); vecX = GeomUtil.UnitVector(GeomUtil.IsBigger(vecX, -vecX) ? vecX : -vecX); vecY = GeomUtil.UnitVector(GeomUtil.IsBigger(vecY, -vecY) ? vecY : -vecY); vecZ = GeomUtil.UnitVector(GeomUtil.IsBigger(vecZ, -vecZ) ? vecZ : -vecZ); TopPolygon = GeomUtil.OffsetPolygon(CentralHorizontalPolygon, vecZ, Height / 2); BottomPolygon = GeomUtil.OffsetPolygon(CentralHorizontalPolygon, vecZ, -Height / 2); FirstLengthPolygon = GeomUtil.OffsetPolygon(CentralVerticalLengthPolygon, vecY, -Width / 2); SecondLengthPolygon = GeomUtil.OffsetPolygon(CentralVerticalLengthPolygon, vecY, Width / 2); FirstWidthPolygon = GeomUtil.OffsetPolygon(CentralVerticalWidthPolygon, vecX, -Length / 2); SecondWidthPolygon = GeomUtil.OffsetPolygon(CentralVerticalWidthPolygon, vecX, Length / 2); this.VecX = vecX; this.VecY = vecY; this.VecZ = vecZ; }
public override Value Evaluate(FSharpList <Value> args) { //unwrap the values IEnumerable <double> nvals = ((Value.List)args[0]).Item.Select(q => (double)((Value.Number)q).Item); var curve = (Curve)((Value.Container)args[1]).Item; sfm = (SpatialFieldManager)((Value.Container)args[2]).Item; if (!sfm.IsResultSchemaNameUnique(DYNAMO_TEMP_CURVES_SCHEMA, -1)) { IList <int> arses = sfm.GetRegisteredResults(); foreach (int i in arses) { AnalysisResultSchema arsTest = sfm.GetResultSchema(i); if (arsTest.Name == DYNAMO_TEMP_CURVES_SCHEMA) { schemaId = i; break; } } } else { var ars = new AnalysisResultSchema(DYNAMO_TEMP_CURVES_SCHEMA, "Temporary curves from Dynamo."); schemaId = sfm.RegisterResult(ars); } Transform trf = Transform.Identity; //http://thebuildingcoder.typepad.com/blog/2012/09/sphere-creation-for-avf-and-filtering.html#3 var create = dynRevitSettings.Doc.Application.Application.Create; Transform t = curve.ComputeDerivatives(0, true); XYZ x = t.BasisX.Normalize(); XYZ y = t.BasisX.IsAlmostEqualTo(XYZ.BasisZ) ? t.BasisX.CrossProduct(XYZ.BasisY).Normalize() : t.BasisX.CrossProduct(XYZ.BasisZ).Normalize(); XYZ z = x.CrossProduct(y); Ellipse arc1 = dynRevitSettings.Revit.Application.Create.NewEllipse(t.Origin, .1, .1, y, z, -Math.PI, 0); Ellipse arc2 = dynRevitSettings.Revit.Application.Create.NewEllipse(t.Origin, .1, .1, y, z, 0, Math.PI); var pathLoop = new CurveLoop(); pathLoop.Append(curve); var profileLoop = new CurveLoop(); profileLoop.Append(arc1); profileLoop.Append(arc2); double curveDomain = curve.get_EndParameter(1) - curve.get_EndParameter(0); int idx = -1; var s = GeometryCreationUtilities.CreateSweptGeometry(pathLoop, 0, 0, new List <CurveLoop> { profileLoop }); foreach (Face face in s.Faces) { //divide the V domain by the number of incoming BoundingBoxUV domain = face.GetBoundingBox(); double vSpan = domain.Max.V - domain.Min.V; //analysis values idx = sfm.AddSpatialFieldPrimitive(face, trf); //a list to hold the analysis points IList <UV> uvPts = new List <UV>(); //a list to hold the analysis values IList <ValueAtPoint> valList = new List <ValueAtPoint>(); //int count = nvals.Count(); //this is creating a lot of sample points, but if we used less //sampling points, AVF would draw the two surfaces as if there was a hard //edge between them. this provides a better blend. int count = 10; for (int i = 0; i < count; i++) { //get a UV point on the face //find its XYZ location and project to //the underlying curve. find the value which corresponds //to the location on the curve var uv = new UV(domain.Min.U, domain.Min.V + vSpan / count * (double)i); var uv1 = new UV(domain.Max.U, domain.Min.V + vSpan / count * (double)i); uvPts.Add(uv); uvPts.Add(uv1); XYZ facePt = face.Evaluate(uv); IntersectionResult ir = curve.Project(facePt); double curveParam = curve.ComputeNormalizedParameter(ir.Parameter); if (curveParam < 0) { curveParam = 0; } if (curveParam > 1) { curveParam = 1; } var valueIndex = (int)Math.Floor(curveParam * (double)nvals.Count()); if (valueIndex >= nvals.Count()) { valueIndex = nvals.Count() - 1; } //create list of values at this point - currently supporting only one //var doubleList = new List<double> { nvals.ElementAt(i) }; var doubleList = new List <double> { nvals.ElementAt(valueIndex) }; //add value at point object containing the value list valList.Add(new ValueAtPoint(doubleList)); valList.Add(new ValueAtPoint(doubleList)); } var pnts = new FieldDomainPointsByUV(uvPts); var vals = new FieldValues(valList); sfm.UpdateSpatialFieldPrimitive( idx, pnts, vals, schemaId); idxs.Add(idx); } return(Value.NewNumber(idx)); }
XYZ GetDimensionStartPointFirstAttempt( Dimension dim) { Document doc = dim.Document; Line dimLine = dim.Curve as Line; if (dimLine == null) { return(null); } dimLine.MakeBound(0, 1); XYZ dimStartPoint = null; XYZ pt1 = dimLine.GetEndPoint(0); // dim.Origin throws "Cannot access this method // if this dimension has more than one segment." //Debug.Assert( Util.IsEqual( pt1, dim.Origin ), // "expected equal points" ); foreach (Reference ref1 in dim.References) { XYZ refPoint = null; Element el = doc.GetElement(ref1.ElementId); GeometryObject obj = el.GetGeometryObjectFromReference( ref1); if (obj == null) { // element is Grid or ReferencePlane or ?? ReferencePlane refPl = el as ReferencePlane; if (refPl != null) { refPoint = refPl.GetPlane().Origin; } Grid grid = el as Grid; if (grid != null) { refPoint = grid.Curve.GetEndPoint(0); } } else { // reference to Line, Plane or Point? Line l = obj as Line; if (l != null) { refPoint = l.GetEndPoint(0); } PlanarFace f = obj as PlanarFace; if (f != null) { refPoint = f.Origin; } } if (refPoint != null) { //View v = doc.ActiveView; View v = dim.View; Plane WorkPlane = v.SketchPlane.GetPlane(); XYZ normal = WorkPlane.Normal.Normalize(); // Project the "globalpoint" of the reference onto the sketchplane XYZ refPtonPlane = refPoint.Subtract( normal.Multiply(normal.DotProduct( refPoint - WorkPlane.Origin))); XYZ lineNormal = normal.CrossProduct( dimLine.Direction).Normalize(); // Project the result onto the dimensionLine dimStartPoint = refPtonPlane.Subtract( lineNormal.Multiply(lineNormal.DotProduct( refPtonPlane - pt1))); } break; } return(dimStartPoint); }
/// <summary> /// Main implementation to export walls. /// </summary> /// <param name="exporterIFC"> /// The ExporterIFC object. /// </param> /// <param name="element"> /// The element. /// </param> /// <param name="geometryElement"> /// The geometry element. /// </param> /// <param name="origWrapper"> /// The ProductWrapper. /// </param> /// <param name="overrideLevelId"> /// The level id. /// </param> /// <param name="range"> /// The range to be exported for the element. /// </param> /// <returns> /// The exported wall handle. /// </returns> public static IFCAnyHandle ExportWallBase(ExporterIFC exporterIFC, Element element, GeometryElement geometryElement, ProductWrapper origWrapper, ElementId overrideLevelId, IFCRange range) { IFCFile file = exporterIFC.GetFile(); using (IFCTransaction tr = new IFCTransaction(file)) { using (ProductWrapper localWrapper = ProductWrapper.Create(origWrapper)) { ElementId catId = CategoryUtil.GetSafeCategoryId(element); Wall wallElement = element as Wall; FamilyInstance famInstWallElem = element as FamilyInstance; FaceWall faceWall = element as FaceWall; if (wallElement == null && famInstWallElem == null && faceWall == null) return null; if (wallElement != null && IsWallCompletelyClipped(wallElement, exporterIFC, range)) return null; Document doc = element.Document; double scale = exporterIFC.LinearScale; double baseWallElevation = 0.0; ElementId baseLevelId = ExporterUtil.GetBaseLevelIdForElement(element); if (baseLevelId != ElementId.InvalidElementId) { Element baseLevel = doc.GetElement(baseLevelId); if (baseLevel is Level) baseWallElevation = (baseLevel as Level).Elevation; } IFCAnyHandle ownerHistory = exporterIFC.GetOwnerHistoryHandle(); IFCAnyHandle contextOfItemsAxis = exporterIFC.Get3DContextHandle("Axis"); IFCAnyHandle contextOfItemsBody = exporterIFC.Get3DContextHandle("Body"); IFCRange zSpan = new IFCRange(); double depth = 0.0; bool validRange = (range != null && !MathUtil.IsAlmostZero(range.Start - range.End)); bool exportParts = PartExporter.CanExportParts(element); if (exportParts && !PartExporter.CanExportElementInPartExport(element, validRange ? overrideLevelId : element.Level.Id, validRange)) return null; // get bounding box height so that we can subtract out pieces properly. // only for Wall, not FamilyInstance. if (wallElement != null && geometryElement != null) { BoundingBoxXYZ boundingBox = element.get_BoundingBox(null); if (boundingBox == null) return null; zSpan = new IFCRange(boundingBox.Min.Z, boundingBox.Max.Z); // if we have a top clipping plane, modify depth accordingly. double bottomHeight = validRange ? Math.Max(zSpan.Start, range.Start) : zSpan.Start; double topHeight = validRange ? Math.Min(zSpan.End, range.End) : zSpan.End; depth = topHeight - bottomHeight; if (MathUtil.IsAlmostZero(depth)) return null; depth *= scale; } IFCAnyHandle axisRep = null; IFCAnyHandle bodyRep = null; bool exportingAxis = false; Curve curve = null; bool exportedAsWallWithAxis = false; bool exportedBodyDirectly = false; bool exportingInplaceOpenings = false; Curve centerCurve = GetWallAxis(wallElement); XYZ localXDir = new XYZ(1, 0, 0); XYZ localYDir = new XYZ(0, 1, 0); XYZ localZDir = new XYZ(0, 0, 1); XYZ localOrig = new XYZ(0, 0, 0); double eps = MathUtil.Eps(); if (centerCurve != null) { Curve baseCurve = GetWallAxisAtBaseHeight(wallElement); curve = GetWallTrimmedCurve(wallElement, baseCurve); IFCRange curveBounds; XYZ oldOrig; GeometryUtil.GetAxisAndRangeFromCurve(curve, out curveBounds, out localXDir, out oldOrig); localOrig = oldOrig; if (baseCurve != null) { if (!validRange || (MathUtil.IsAlmostEqual(range.Start, zSpan.Start))) { XYZ newOrig = baseCurve.Evaluate(curveBounds.Start, false); if (!validRange && (zSpan.Start < newOrig[2] - eps)) localOrig = new XYZ(localOrig.X, localOrig.Y, zSpan.Start); else localOrig = new XYZ(localOrig.X, localOrig.Y, newOrig[2]); } else { localOrig = new XYZ(localOrig.X, localOrig.Y, range.Start); } } double dist = localOrig[2] - oldOrig[2]; if (!MathUtil.IsAlmostZero(dist)) { XYZ moveVec = new XYZ(0, 0, dist); curve = GeometryUtil.MoveCurve(curve, moveVec); } localYDir = localZDir.CrossProduct(localXDir); // ensure that X and Z axes are orthogonal. double xzDot = localZDir.DotProduct(localXDir); if (!MathUtil.IsAlmostZero(xzDot)) localXDir = localYDir.CrossProduct(localZDir); } else { BoundingBoxXYZ boundingBox = element.get_BoundingBox(null); if (boundingBox != null) { XYZ bBoxMin = boundingBox.Min; XYZ bBoxMax = boundingBox.Max; if (validRange) localOrig = new XYZ(bBoxMin.X, bBoxMin.Y, range.Start); else localOrig = boundingBox.Min; XYZ localXDirMax = null; Transform bTrf = boundingBox.Transform; XYZ localXDirMax1 = new XYZ(bBoxMax.X, localOrig.Y, localOrig.Z); localXDirMax1 = bTrf.OfPoint(localXDirMax1); XYZ localXDirMax2 = new XYZ(localOrig.X, bBoxMax.Y, localOrig.Z); localXDirMax2 = bTrf.OfPoint(localXDirMax2); if (localXDirMax1.DistanceTo(localOrig) >= localXDirMax2.DistanceTo(localOrig)) localXDirMax = localXDirMax1; else localXDirMax = localXDirMax2; localXDir = localXDirMax.Subtract(localOrig); localXDir = localXDir.Normalize(); localYDir = localZDir.CrossProduct(localXDir); // ensure that X and Z axes are orthogonal. double xzDot = localZDir.DotProduct(localXDir); if (!MathUtil.IsAlmostZero(xzDot)) localXDir = localYDir.CrossProduct(localZDir); } } Transform orientationTrf = Transform.Identity; orientationTrf.BasisX = localXDir; orientationTrf.BasisY = localYDir; orientationTrf.BasisZ = localZDir; orientationTrf.Origin = localOrig; if (overrideLevelId == ElementId.InvalidElementId) overrideLevelId = ExporterUtil.GetBaseLevelIdForElement(element); using (IFCPlacementSetter setter = IFCPlacementSetter.Create(exporterIFC, element, null, orientationTrf, overrideLevelId)) { IFCAnyHandle localPlacement = setter.GetPlacement(); Plane plane = new Plane(localXDir, localYDir, localOrig); // project curve to XY plane. XYZ projDir = XYZ.BasisZ; // two representations: axis, body. { if (!exportParts && (centerCurve != null) && (GeometryUtil.CurveIsLineOrArc(centerCurve))) { exportingAxis = true; string identifierOpt = "Axis"; // IFC2x2 convention string representationTypeOpt = "Curve2D"; // IFC2x2 convention IFCGeometryInfo info = IFCGeometryInfo.CreateCurveGeometryInfo(exporterIFC, plane, projDir, false); ExporterIFCUtils.CollectGeometryInfo(exporterIFC, info, curve, XYZ.Zero, true); IList<IFCAnyHandle> axisItems = info.GetCurves(); if (axisItems.Count == 0) { exportingAxis = false; } else { HashSet<IFCAnyHandle> axisItemSet = new HashSet<IFCAnyHandle>(); foreach (IFCAnyHandle axisItem in axisItems) axisItemSet.Add(axisItem); axisRep = RepresentationUtil.CreateShapeRepresentation(exporterIFC, element, catId, contextOfItemsAxis, identifierOpt, representationTypeOpt, axisItemSet); } } } IList<IFCExtrusionData> cutPairOpenings = new List<IFCExtrusionData>(); Document document = element.Document; IList<Solid> solids = new List<Solid>(); IList<Mesh> meshes = new List<Mesh>(); if (!exportParts && wallElement != null && exportingAxis && curve != null) { SolidMeshGeometryInfo solidMeshInfo = (range == null) ? GeometryUtil.GetSplitSolidMeshGeometry(geometryElement) : GeometryUtil.GetSplitClippedSolidMeshGeometry(geometryElement, range); solids = solidMeshInfo.GetSolids(); meshes = solidMeshInfo.GetMeshes(); if (solids.Count == 0 && meshes.Count == 0) return null; bool useNewCode = false; if (useNewCode && solids.Count == 1 && meshes.Count == 0) { bool completelyClipped; bodyRep = ExtrusionExporter.CreateExtrusionWithClipping(exporterIFC, wallElement, catId, solids[0], plane, projDir, range, out completelyClipped); if (completelyClipped) return null; if (!IFCAnyHandleUtil.IsNullOrHasNoValue(bodyRep)) { exportedAsWallWithAxis = true; exportedBodyDirectly = true; } else { exportedAsWallWithAxis = false; exportedBodyDirectly = false; } } if (!exportedAsWallWithAxis) { // Fallback - use native routines to try to export wall. bool isCompletelyClipped; bodyRep = FallbackTryToCreateAsExtrusion(exporterIFC, wallElement, solidMeshInfo, baseWallElevation, catId, curve, plane, depth, zSpan, range, setter, out cutPairOpenings, out isCompletelyClipped); if (isCompletelyClipped) return null; if (!IFCAnyHandleUtil.IsNullOrHasNoValue(bodyRep)) exportedAsWallWithAxis = true; } } using (IFCExtrusionCreationData extraParams = new IFCExtrusionCreationData()) { BodyData bodyData = null; if (!exportedAsWallWithAxis) { SolidMeshGeometryInfo solidMeshCapsule = null; if (wallElement != null || faceWall != null) { if (validRange) { solidMeshCapsule = GeometryUtil.GetSplitClippedSolidMeshGeometry(geometryElement, range); } else { solidMeshCapsule = GeometryUtil.GetSplitSolidMeshGeometry(geometryElement); } if (solidMeshCapsule.SolidsCount() == 0 && solidMeshCapsule.MeshesCount() == 0) { return null; } } else { GeometryElement geomElemToUse = GetGeometryFromInplaceWall(famInstWallElem); if (geomElemToUse != null) { exportingInplaceOpenings = true; } else { exportingInplaceOpenings = false; geomElemToUse = geometryElement; } Transform trf = Transform.Identity; if (geomElemToUse != geometryElement) trf = famInstWallElem.GetTransform(); solidMeshCapsule = GeometryUtil.GetSplitSolidMeshGeometry(geomElemToUse, trf); } solids = solidMeshCapsule.GetSolids(); meshes = solidMeshCapsule.GetMeshes(); extraParams.PossibleExtrusionAxes = IFCExtrusionAxes.TryZ; // only allow vertical extrusions! extraParams.AreInnerRegionsOpenings = true; BodyExporterOptions bodyExporterOptions = new BodyExporterOptions(true); // Swept solids are not natively exported as part of CV2.0. // We have removed the UI toggle for this, so that it is by default false, but keep for possible future use. if (ExporterCacheManager.ExportOptionsCache.ExportAdvancedSweptSolids) bodyExporterOptions.TryToExportAsSweptSolid = true; ElementId overrideMaterialId = ElementId.InvalidElementId; if (wallElement != null) overrideMaterialId = HostObjectExporter.GetFirstLayerMaterialId(wallElement); if (!exportParts) { if ((solids.Count > 0) || (meshes.Count > 0)) { bodyRep = BodyExporter.ExportBody(exporterIFC, element, catId, overrideMaterialId, solids, meshes, bodyExporterOptions, extraParams).RepresentationHnd; } else { IList<GeometryObject> geomElemList = new List<GeometryObject>(); geomElemList.Add(geometryElement); bodyData = BodyExporter.ExportBody(exporterIFC, element, catId, overrideMaterialId, geomElemList, bodyExporterOptions, extraParams); bodyRep = bodyData.RepresentationHnd; } if (IFCAnyHandleUtil.IsNullOrHasNoValue(bodyRep)) { extraParams.ClearOpenings(); return null; } } // We will be able to export as a IfcWallStandardCase as long as we have an axis curve. XYZ extrDirUsed = XYZ.Zero; if (extraParams.HasExtrusionDirection) { extrDirUsed = extraParams.ExtrusionDirection; if (MathUtil.IsAlmostEqual(Math.Abs(extrDirUsed[2]), 1.0)) { if ((solids.Count == 1) && (meshes.Count == 0)) exportedAsWallWithAxis = exportingAxis; exportedBodyDirectly = true; } } } IFCAnyHandle prodRep = null; if (!exportParts) { IList<IFCAnyHandle> representations = new List<IFCAnyHandle>(); if (exportingAxis) representations.Add(axisRep); representations.Add(bodyRep); IFCAnyHandle boundingBoxRep = null; if ((solids.Count > 0) || (meshes.Count > 0)) boundingBoxRep = BoundingBoxExporter.ExportBoundingBox(exporterIFC, solids, meshes, Transform.Identity); else boundingBoxRep = BoundingBoxExporter.ExportBoundingBox(exporterIFC, geometryElement, Transform.Identity); if (boundingBoxRep != null) representations.Add(boundingBoxRep); prodRep = IFCInstanceExporter.CreateProductDefinitionShape(file, null, null, representations); } ElementId matId = ElementId.InvalidElementId; string objectType = NamingUtil.CreateIFCObjectName(exporterIFC, element); IFCAnyHandle wallHnd = null; string elemGUID = (validRange) ? GUIDUtil.CreateGUID() : GUIDUtil.CreateGUID(element); string elemName = NamingUtil.GetNameOverride(element, NamingUtil.GetIFCName(element)); string elemDesc = NamingUtil.GetDescriptionOverride(element, null); string elemObjectType = NamingUtil.GetObjectTypeOverride(element, objectType); string elemTag = NamingUtil.GetTagOverride(element, NamingUtil.CreateIFCElementId(element)); // For Foundation and Retaining walls, allow exporting as IfcFooting instead. bool exportAsFooting = false; string enumTypeValue = null; if (wallElement != null) { WallType wallType = wallElement.WallType; if (wallType != null) { int wallFunction; if (ParameterUtil.GetIntValueFromElement(wallType, BuiltInParameter.FUNCTION_PARAM, out wallFunction) != null) { if (wallFunction == (int)WallFunction.Retaining || wallFunction == (int)WallFunction.Foundation) { // In this case, allow potential to export foundation and retaining walls as footing. IFCExportType exportType = ExporterUtil.GetExportType(exporterIFC, wallElement, out enumTypeValue); if (exportType == IFCExportType.ExportFooting) exportAsFooting = true; } } } } if (exportedAsWallWithAxis) { if (exportAsFooting) { Toolkit.IFCFootingType footingType = FootingExporter.GetIFCFootingType(element, enumTypeValue); wallHnd = IFCInstanceExporter.CreateFooting(file, elemGUID, ownerHistory, elemName, elemDesc, elemObjectType, localPlacement, exportParts ? null : prodRep, elemTag, footingType); } else if (exportParts) { wallHnd = IFCInstanceExporter.CreateWall(file, elemGUID, ownerHistory, elemName, elemDesc, elemObjectType, localPlacement, null, elemTag); } else { wallHnd = IFCInstanceExporter.CreateWallStandardCase(file, elemGUID, ownerHistory, elemName, elemDesc, elemObjectType, localPlacement, prodRep, elemTag); } if (exportParts) PartExporter.ExportHostPart(exporterIFC, element, wallHnd, localWrapper, setter, localPlacement, overrideLevelId); localWrapper.AddElement(element, wallHnd, setter, extraParams, true); if (!exportParts) { OpeningUtil.CreateOpeningsIfNecessary(wallHnd, element, cutPairOpenings, null, exporterIFC, localPlacement, setter, localWrapper); if (exportedBodyDirectly) { Transform offsetTransform = (bodyData != null) ? bodyData.OffsetTransform : Transform.Identity; OpeningUtil.CreateOpeningsIfNecessary(wallHnd, element, extraParams, offsetTransform, exporterIFC, localPlacement, setter, localWrapper); } else { ICollection<IFCAnyHandle> beforeOpenings = localWrapper.GetAllObjects(); double scaledWidth = wallElement.Width * scale; ExporterIFCUtils.AddOpeningsToElement(exporterIFC, wallHnd, wallElement, scaledWidth, range, setter, localPlacement, localWrapper.ToNative()); ICollection<IFCAnyHandle> afterOpenings = localWrapper.GetAllObjects(); if (beforeOpenings.Count != afterOpenings.Count) { foreach (IFCAnyHandle before in beforeOpenings) afterOpenings.Remove(before); foreach (IFCAnyHandle potentiallyBadOpening in afterOpenings) { PotentiallyCorrectOpeningOrientationAndOpeningType(potentiallyBadOpening, localPlacement, scaledWidth); } } } } // export Base Quantities if (ExporterCacheManager.ExportOptionsCache.ExportBaseQuantities) { CreateWallBaseQuantities(exporterIFC, wallElement, wallHnd, depth); } } else { if (exportAsFooting) { Toolkit.IFCFootingType footingType = FootingExporter.GetIFCFootingType(element, enumTypeValue); wallHnd = IFCInstanceExporter.CreateFooting(file, elemGUID, ownerHistory, elemName, elemDesc, elemObjectType, localPlacement, exportParts ? null : prodRep, elemTag, footingType); } else { wallHnd = IFCInstanceExporter.CreateWall(file, elemGUID, ownerHistory, elemName, elemDesc, elemObjectType, localPlacement, exportParts ? null : prodRep, elemTag); } if (exportParts) PartExporter.ExportHostPart(exporterIFC, element, wallHnd, localWrapper, setter, localPlacement, overrideLevelId); localWrapper.AddElement(element, wallHnd, setter, extraParams, true); if (!exportParts) { // Only export one material for 2x2; for future versions, export the whole list. if (exporterIFC.ExportAs2x2 || famInstWallElem != null) { matId = BodyExporter.GetBestMaterialIdFromGeometryOrParameter(solids, meshes, element); if (matId != ElementId.InvalidElementId) CategoryUtil.CreateMaterialAssociation(exporterIFC, wallHnd, matId); } if (exportingInplaceOpenings) { ExporterIFCUtils.AddOpeningsToElement(exporterIFC, wallHnd, famInstWallElem, 0.0, range, setter, localPlacement, localWrapper.ToNative()); } if (exportedBodyDirectly) { Transform offsetTransform = (bodyData != null) ? bodyData.OffsetTransform : Transform.Identity; OpeningUtil.CreateOpeningsIfNecessary(wallHnd, element, extraParams, offsetTransform, exporterIFC, localPlacement, setter, localWrapper); } } } ElementId wallLevelId = (validRange) ? setter.LevelId : ElementId.InvalidElementId; if ((wallElement != null || faceWall != null) && !exportParts) { HostObject hostObject = null; if (wallElement != null) hostObject = wallElement; else hostObject = faceWall; if (!exporterIFC.ExportAs2x2 || exportedAsWallWithAxis) HostObjectExporter.ExportHostObjectMaterials(exporterIFC, hostObject, localWrapper.GetAnElement(), geometryElement, localWrapper, wallLevelId, Toolkit.IFCLayerSetDirection.Axis2, !exportedAsWallWithAxis); } ExportWallType(exporterIFC, localWrapper, wallHnd, element, matId, exportedAsWallWithAxis, exportAsFooting); exporterIFC.RegisterSpaceBoundingElementHandle(wallHnd, element.Id, wallLevelId); tr.Commit(); return wallHnd; } } } } }
public static bool IsParallel(XYZ p, XYZ q) { return(p.CrossProduct(q).IsZeroLength()); }
/// <summary> /// Create the opening associated to an already created door or window. /// </summary> /// <param name="exporterIFC">The exporter class.</param> /// <param name="doc">The document.</param> /// <param name="hostObjHnd">The host object IFC handle.</param> /// <param name="hostId">The host object element id.</param> /// <param name="insertId">The insert element id.</param> /// <param name="openingGUID">The GUID for the IfcOpeningElement.</param> /// <param name="cutLoop">The 2D outline representing the opening geometry.</param> /// <param name="cutDir">The direction of the extrusion representing the opening geometry.</param> /// <param name="origUnscaledDepth">The width of the host object that the opening is cutting.</param> /// <param name="posHingeSide">True if the 2D outline is on the plane containing the hinge.</param> /// <param name="isRecess">True if the IfcOpeningElement should represent a recess.</param> /// <returns>The class containing information about the opening.</returns> static public DoorWindowOpeningInfo CreateOpeningForDoorWindow(ExporterIFC exporterIFC, Document doc, IFCAnyHandle hostObjHnd, ElementId hostId, ElementId insertId, string openingGUID, CurveLoop cutLoop, XYZ cutDir, double origUnscaledDepth, bool posHingeSide, bool isRecess) { // calculate some values. double openingHeight = -1.0; double openingWidth = -1.0; Element wallElement = doc.GetElement(hostId); Wall wall = (wallElement != null) ? wallElement as Wall : null; Curve curve = WallExporter.GetWallAxis(wall); if (curve == null) return null; // Don't export opening if we are exporting parts on a wall, as the parts will already have the openings cut out. if (PartExporter.CanExportParts(wall)) return null; ElementId catId = CategoryUtil.GetSafeCategoryId(wall); double unScaledDepth = origUnscaledDepth; IFCAnyHandle hostObjPlacementHnd = IFCAnyHandleUtil.GetObjectPlacement(hostObjHnd); IFCAnyHandle ownerHistory = ExporterCacheManager.OwnerHistoryHandle; XYZ relOrig = XYZ.Zero; XYZ relZ = XYZ.BasisZ; XYZ relX = XYZ.BasisX; double openingZNonScaled = -1.0; Plane plane = new Plane(cutDir, XYZ.Zero); // get height, width before transform BoundingBoxXYZ cutLoopBBox = ComputeApproximateCurveLoopBBoxForOpening(cutLoop, null); if (cutLoopBBox != null) { XYZ dist = cutLoopBBox.Max - cutLoopBBox.Min; openingZNonScaled = cutLoopBBox.Min.Z; openingHeight = Math.Abs(dist.Z); openingWidth = Math.Sqrt(dist.X * dist.X + dist.Y * dist.Y); } Transform openingTrf = ExporterIFCUtils.GetUnscaledTransform(exporterIFC, hostObjPlacementHnd); XYZ hostObjYDir = openingTrf.BasisY; XYZ hostObjOrig = openingTrf.Origin; openingTrf = openingTrf.Inverse; // move to wall axis CurveLoop tmpCutLoop = GeometryUtil.TransformCurveLoop(cutLoop, openingTrf); cutDir = openingTrf.OfVector(cutDir); if (curve is Line) { Plane cutLoopPlane = null; try { cutLoopPlane = tmpCutLoop.GetPlane(); } catch { return null; } XYZ clOrig = cutLoopPlane.Origin; double wantOriginAtY = posHingeSide ? (-unScaledDepth / 2.0) : (unScaledDepth / 2.0); if (!MathUtil.IsAlmostEqual(wantOriginAtY, clOrig[1])) { XYZ moveVec = new XYZ(0, wantOriginAtY - clOrig[1], 0); tmpCutLoop = GeometryUtil.MoveCurveLoop(tmpCutLoop, moveVec); } bool cutDirRelToHostObjY = (cutDir[1] > 0.0); // true = same sense, false = opp. sense if (posHingeSide != cutDirRelToHostObjY) { cutDir = cutDir * -1.0; cutDirRelToHostObjY = !cutDirRelToHostObjY; // not used beyond this point. } } else if ((cutLoopBBox != null) && (curve is Arc)) { Arc arc = curve as Arc; double radius = arc.Radius; XYZ curveCtr = arc.Center; // check orientation to cutDir, make sure it points to center of arc. XYZ origLL = new XYZ(cutLoopBBox.Min.X, cutLoopBBox.Min.Y, curveCtr.Z); XYZ origUR = new XYZ(cutLoopBBox.Max.X, cutLoopBBox.Max.Y, curveCtr.Z); XYZ origCtr = (origLL + origUR) / 2.0; double centerDist = origCtr.DistanceTo(curveCtr); XYZ approxMoveDir = (origCtr - curveCtr).Normalize(); bool cutDirPointingIn = (cutDir.DotProduct(approxMoveDir) < 0.0); bool centerInsideArc = (centerDist < radius); if (centerInsideArc == cutDirPointingIn) { XYZ moveVec = cutDir * -unScaledDepth; origCtr += moveVec; tmpCutLoop = GeometryUtil.MoveCurveLoop(tmpCutLoop, moveVec); } // not for windows that are too big ... forget about it. Very rare case. double depthFactor = openingWidth / (2.0 * radius); double eps = MathUtil.Eps(); if (depthFactor < 1.0 - eps) { double depthFactorSq = depthFactor * depthFactor * 4; double extraDepth = radius * (1.0 - Math.Sqrt(1.0 - depthFactorSq)); if (extraDepth > eps) { XYZ moveVec = cutDir * -extraDepth; tmpCutLoop = GeometryUtil.MoveCurveLoop(tmpCutLoop, moveVec); unScaledDepth += extraDepth; } } // extra fudge on the other side of the window opening. depthFactor = origUnscaledDepth / (2.0 * radius); if (depthFactor < 1.0 - eps) { double extraDepth = radius * (1.0 - Math.Sqrt(1.0 - depthFactor)); if (extraDepth > eps) unScaledDepth += extraDepth; } } XYZ cutXDir = XYZ.BasisZ; XYZ cutOrig = XYZ.Zero; XYZ cutYDir = cutDir.CrossProduct(cutXDir); plane = new Plane(cutXDir, cutYDir, cutOrig); // now move to origin in this coordinate system. // todo: update openingtrf if we are to use it again! BoundingBoxXYZ tmpBBox = ComputeApproximateCurveLoopBBoxForOpening(tmpCutLoop, plane); if (tmpBBox != null) { relOrig = tmpBBox.Min; XYZ moveVec = relOrig * -1.0; tmpCutLoop = GeometryUtil.MoveCurveLoop(tmpCutLoop, moveVec); } IList<CurveLoop> oCutLoopList = new List<CurveLoop>(); oCutLoopList.Add(tmpCutLoop); double depth = UnitUtil.ScaleLength(unScaledDepth); Element doorWindowElement = doc.GetElement(insertId); IFCAnyHandle openingRepHnd = RepresentationUtil.CreateExtrudedProductDefShape(exporterIFC, doorWindowElement, catId, oCutLoopList, plane, cutDir, depth); if (IFCAnyHandleUtil.IsNullOrHasNoValue(openingRepHnd)) return null; // care only about first loop. IFCFile file = exporterIFC.GetFile(); XYZ scaledOrig = UnitUtil.ScaleLength(relOrig); IFCAnyHandle openingPlacement = ExporterUtil.CreateLocalPlacement(file, hostObjPlacementHnd, scaledOrig, relZ, relX); string openingObjectType = isRecess ? "Recess": "Opening"; string origOpeningName = NamingUtil.GetIFCNamePlusIndex(doorWindowElement, 1); string openingName = NamingUtil.GetNameOverride(doorWindowElement, origOpeningName); IFCAnyHandle openingHnd = IFCInstanceExporter.CreateOpeningElement(file, openingGUID, ownerHistory, openingName, null, openingObjectType, openingPlacement, openingRepHnd, null); string openingVoidsGUID = GUIDUtil.CreateSubElementGUID(doorWindowElement, (int)IFCDoorSubElements.DoorOpeningRelVoid); IFCInstanceExporter.CreateRelVoidsElement(file, openingVoidsGUID, ownerHistory, null, null, hostObjHnd, openingHnd); if (ExporterCacheManager.ExportOptionsCache.ExportBaseQuantities) { using (IFCExtrusionCreationData extraParams = new IFCExtrusionCreationData()) { double height = 0.0, width = 0.0; if (ExtrusionExporter.ComputeHeightWidthOfCurveLoop(tmpCutLoop, plane, out height, out width)) { extraParams.ScaledHeight = UnitUtil.ScaleLength(height); extraParams.ScaledWidth = UnitUtil.ScaleLength(width); } IList<CurveLoop> curveLoops = new List<CurveLoop>(); curveLoops.Add(tmpCutLoop); double area = ExporterIFCUtils.ComputeAreaOfCurveLoops(curveLoops); if (area > 0.0) extraParams.ScaledArea = UnitUtil.ScaleArea(area); extraParams.ScaledLength = depth; PropertyUtil.CreateOpeningQuantities(exporterIFC, openingHnd, extraParams); } } return DoorWindowOpeningInfo.Create(openingHnd, openingHeight, openingWidth); }
public Dictionary <Line, XYZ> Edges() { Dictionary <Line, XYZ> e = new Dictionary <Line, XYZ>(); //get first point //get line from first point to second point = l1 //get line from first point to last point = ln //compare their direction, If it is consistent, look at line from last point to second to last (l n-1). repeat. //get line from second point to third point = l2 //compare direction from l1 and l2. if direction is similar or if l2 is short enough move on to l3. //When the direction diverges, end the line, begin a new one (l3 = third point to fourth point) if (BasePoints().Count >= 2) { int i = 0; int j = BasePoints().Count - 1; while (i < j) { XYZ ipt = BasePoints()[i + 1] - BasePoints()[i]; XYZ up = XYZ.BasisZ; XYZ rd = ipt.CrossProduct(up); XYZ angle = rd.Normalize(); bool EoL = false; int k = i; int l = i + 1; if (i == 0) { bool BoL = false; if (LineRelation(ipt, BasePoints()[j], BasePoints()[0])) { while (BoL == false) { k = j; if (j >= 1) { if (LineRelation(ipt, BasePoints()[j - 1], BasePoints()[j])) { j--; } else { BoL = true; } } } } else { XYZ jpt = BasePoints()[0] - BasePoints()[j]; if (!LineRelation(jpt, BasePoints()[j - 1], BasePoints()[j])) { XYZ jAngle = jpt.CrossProduct(up).Normalize(); e.Add(Line.CreateBound(BasePoints()[j], BasePoints()[0]), jAngle); } } } while (EoL == false) { if (i < BasePoints().Count() - 1) { if (LineRelation(ipt, BasePoints()[i], BasePoints()[i + 1])) { i++; l = i; } else { EoL = true; } } else { if (LineRelation(ipt, BasePoints()[i], BasePoints()[0])) { l = 0; } EoL = true; } } e.Add(Line.CreateBound(BasePoints()[k], BasePoints()[l]), angle); } } return(e); }
/// <summary> /// Main implementation to export walls. /// </summary> /// <param name="exporterIFC">The ExporterIFC object.</param> /// <param name="element">The element.</param> /// <param name="connectedWalls">Information about walls joined to this wall.</param> /// <param name="geometryElement">The geometry element.</param> /// <param name="origWrapper">The ProductWrapper.</param> /// <param name="overrideLevelId">The level id.</param> /// <param name="range">The range to be exported for the element.</param> /// <returns>The exported wall handle.</returns> public static IFCAnyHandle ExportWallBase(ExporterIFC exporterIFC, Element element, IList<IList<IFCConnectedWallData>> connectedWalls, GeometryElement geometryElement, ProductWrapper origWrapper, ElementId overrideLevelId, IFCRange range) { // Check cases where we choose not to export early. ElementId catId = CategoryUtil.GetSafeCategoryId(element); Wall wallElement = element as Wall; FamilyInstance famInstWallElem = element as FamilyInstance; FaceWall faceWall = element as FaceWall; bool exportingWallElement = (wallElement != null); bool exportingFamilyInstance = (famInstWallElem != null); bool exportingFaceWall = (faceWall != null); if (!exportingWallElement && !exportingFamilyInstance && !exportingFaceWall) return null; if (exportingWallElement && IsWallCompletelyClipped(wallElement, exporterIFC, range)) return null; IFCRange zSpan = null; double depth = 0.0; bool validRange = (range != null && !MathUtil.IsAlmostZero(range.Start - range.End)); bool exportParts = PartExporter.CanExportParts(element); if (exportParts && !PartExporter.CanExportElementInPartExport(element, validRange ? overrideLevelId : element.LevelId, validRange)) return null; IList<Solid> solids = new List<Solid>(); IList<Mesh> meshes = new List<Mesh>(); bool exportingInplaceOpenings = false; if (!exportParts) { if (exportingWallElement || exportingFaceWall) { GetSolidsAndMeshes(geometryElement, range, ref solids, ref meshes); if (solids.Count == 0 && meshes.Count == 0) return null; } else { GeometryElement geomElemToUse = GetGeometryFromInplaceWall(famInstWallElem); if (geomElemToUse != null) { exportingInplaceOpenings = true; } else { exportingInplaceOpenings = false; geomElemToUse = geometryElement; } Transform trf = Transform.Identity; if (geomElemToUse != geometryElement) trf = famInstWallElem.GetTransform(); SolidMeshGeometryInfo solidMeshCapsule = GeometryUtil.GetSplitSolidMeshGeometry(geomElemToUse, trf); solids = solidMeshCapsule.GetSolids(); meshes = solidMeshCapsule.GetMeshes(); } } IFCFile file = exporterIFC.GetFile(); using (IFCTransaction tr = new IFCTransaction(file)) { using (ProductWrapper localWrapper = ProductWrapper.Create(origWrapper)) { // get bounding box height so that we can subtract out pieces properly. // only for Wall, not FamilyInstance. if (exportingWallElement && geometryElement != null) { // There is a problem in the API where some walls with vertical structures are overreporting their height, // making it appear as if there are clipping problems on export. We will work around this by getting the // height directly from the solid(s). if (solids.Count > 0 && meshes.Count == 0) { zSpan = GetBoundingBoxOfSolids(solids); } else { BoundingBoxXYZ boundingBox = wallElement.get_BoundingBox(null); if (boundingBox != null) zSpan = GetBoundingBoxZRange(boundingBox); } if (zSpan == null) return null; // if we have a top clipping plane, modify depth accordingly. double bottomHeight = validRange ? Math.Max(zSpan.Start, range.Start) : zSpan.Start; double topHeight = validRange ? Math.Min(zSpan.End, range.End) : zSpan.End; depth = topHeight - bottomHeight; if (MathUtil.IsAlmostZero(depth)) return null; depth = UnitUtil.ScaleLength(depth); } else { zSpan = new IFCRange(); } Document doc = element.Document; double baseWallElevation = 0.0; ElementId baseLevelId = PlacementSetter.GetBaseLevelIdForElement(element); if (baseLevelId != ElementId.InvalidElementId) { Element baseLevel = doc.GetElement(baseLevelId); if (baseLevel is Level) baseWallElevation = (baseLevel as Level).Elevation; } IFCAnyHandle axisRep = null; IFCAnyHandle bodyRep = null; bool exportingAxis = false; Curve trimmedCurve = null; bool exportedAsWallWithAxis = false; bool exportedBodyDirectly = false; Curve centerCurve = GetWallAxis(wallElement); XYZ localXDir = new XYZ(1, 0, 0); XYZ localYDir = new XYZ(0, 1, 0); XYZ localZDir = new XYZ(0, 0, 1); XYZ localOrig = new XYZ(0, 0, 0); double eps = MathUtil.Eps(); if (centerCurve != null) { Curve baseCurve = GetWallAxisAtBaseHeight(wallElement); trimmedCurve = GetWallTrimmedCurve(wallElement, baseCurve); IFCRange curveBounds; XYZ oldOrig; GeometryUtil.GetAxisAndRangeFromCurve(trimmedCurve, out curveBounds, out localXDir, out oldOrig); // Move the curve to the bottom of the geometry or the bottom of the range, which is higher. if (baseCurve != null) localOrig = new XYZ(oldOrig.X, oldOrig.Y, validRange ? Math.Max(range.Start, zSpan.Start) : zSpan.Start); else localOrig = oldOrig; double dist = localOrig[2] - oldOrig[2]; if (!MathUtil.IsAlmostZero(dist)) { XYZ moveVec = new XYZ(0, 0, dist); trimmedCurve = GeometryUtil.MoveCurve(trimmedCurve, moveVec); } localYDir = localZDir.CrossProduct(localXDir); // ensure that X and Z axes are orthogonal. double xzDot = localZDir.DotProduct(localXDir); if (!MathUtil.IsAlmostZero(xzDot)) localXDir = localYDir.CrossProduct(localZDir); } else { BoundingBoxXYZ boundingBox = element.get_BoundingBox(null); if (boundingBox != null) { XYZ bBoxMin = boundingBox.Min; XYZ bBoxMax = boundingBox.Max; if (validRange) localOrig = new XYZ(bBoxMin.X, bBoxMin.Y, range.Start); else localOrig = boundingBox.Min; XYZ localXDirMax = null; Transform bTrf = boundingBox.Transform; XYZ localXDirMax1 = new XYZ(bBoxMax.X, localOrig.Y, localOrig.Z); localXDirMax1 = bTrf.OfPoint(localXDirMax1); XYZ localXDirMax2 = new XYZ(localOrig.X, bBoxMax.Y, localOrig.Z); localXDirMax2 = bTrf.OfPoint(localXDirMax2); if (localXDirMax1.DistanceTo(localOrig) >= localXDirMax2.DistanceTo(localOrig)) localXDirMax = localXDirMax1; else localXDirMax = localXDirMax2; localXDir = localXDirMax.Subtract(localOrig); localXDir = localXDir.Normalize(); localYDir = localZDir.CrossProduct(localXDir); // ensure that X and Z axes are orthogonal. double xzDot = localZDir.DotProduct(localXDir); if (!MathUtil.IsAlmostZero(xzDot)) localXDir = localYDir.CrossProduct(localZDir); } } IFCAnyHandle ownerHistory = exporterIFC.GetOwnerHistoryHandle(); Transform orientationTrf = Transform.Identity; orientationTrf.BasisX = localXDir; orientationTrf.BasisY = localYDir; orientationTrf.BasisZ = localZDir; orientationTrf.Origin = localOrig; double scaledFootprintArea = 0; double scaledLength = 0; using (PlacementSetter setter = PlacementSetter.Create(exporterIFC, element, null, orientationTrf, overrideLevelId)) { IFCAnyHandle localPlacement = setter.LocalPlacement; // The local coordinate system of the wall as defined by IFC for IfcWallStandardCase. Plane wallLCS = new Plane(localXDir, localYDir, localOrig); // project curve to XY plane. XYZ projDir = XYZ.BasisZ; // two representations: axis, body. { if (!exportParts && (centerCurve != null) && (GeometryUtil.CurveIsLineOrArc(centerCurve))) { exportingAxis = true; string identifierOpt = "Axis"; // IFC2x2 convention string representationTypeOpt = "Curve2D"; // IFC2x2 convention IFCGeometryInfo info = IFCGeometryInfo.CreateCurveGeometryInfo(exporterIFC, wallLCS, projDir, false); ExporterIFCUtils.CollectGeometryInfo(exporterIFC, info, trimmedCurve, XYZ.Zero, true); IList<IFCAnyHandle> axisItems = info.GetCurves(); if (axisItems.Count == 0) { exportingAxis = false; } else { HashSet<IFCAnyHandle> axisItemSet = new HashSet<IFCAnyHandle>(); foreach (IFCAnyHandle axisItem in axisItems) axisItemSet.Add(axisItem); IFCAnyHandle contextOfItemsAxis = exporterIFC.Get3DContextHandle("Axis"); axisRep = RepresentationUtil.CreateShapeRepresentation(exporterIFC, element, catId, contextOfItemsAxis, identifierOpt, representationTypeOpt, axisItemSet); } } } IList<IFCExtrusionData> cutPairOpenings = new List<IFCExtrusionData>(); if (!exportParts && exportingWallElement && exportingAxis && trimmedCurve != null) { bool isCompletelyClipped; bodyRep = TryToCreateAsExtrusion(exporterIFC, wallElement, connectedWalls, solids, meshes, baseWallElevation, catId, centerCurve, trimmedCurve, wallLCS, depth, zSpan, range, setter, out cutPairOpenings, out isCompletelyClipped, out scaledFootprintArea, out scaledLength); if (isCompletelyClipped) return null; if (!IFCAnyHandleUtil.IsNullOrHasNoValue(bodyRep)) exportedAsWallWithAxis = true; } using (IFCExtrusionCreationData extraParams = new IFCExtrusionCreationData()) { BodyData bodyData = null; if (!exportedAsWallWithAxis) { extraParams.PossibleExtrusionAxes = IFCExtrusionAxes.TryZ; // only allow vertical extrusions! extraParams.AreInnerRegionsOpenings = true; BodyExporterOptions bodyExporterOptions = new BodyExporterOptions(true); // Swept solids are not natively exported as part of CV2.0. // We have removed the UI toggle for this, so that it is by default false, but keep for possible future use. if (ExporterCacheManager.ExportOptionsCache.ExportAdvancedSweptSolids) bodyExporterOptions.TryToExportAsSweptSolid = true; ElementId overrideMaterialId = ElementId.InvalidElementId; if (exportingWallElement) overrideMaterialId = HostObjectExporter.GetFirstLayerMaterialId(wallElement); if (!exportParts) { if ((solids.Count > 0) || (meshes.Count > 0)) { bodyRep = BodyExporter.ExportBody(exporterIFC, element, catId, overrideMaterialId, solids, meshes, bodyExporterOptions, extraParams).RepresentationHnd; } else { IList<GeometryObject> geomElemList = new List<GeometryObject>(); geomElemList.Add(geometryElement); bodyData = BodyExporter.ExportBody(exporterIFC, element, catId, overrideMaterialId, geomElemList, bodyExporterOptions, extraParams); bodyRep = bodyData.RepresentationHnd; } if (IFCAnyHandleUtil.IsNullOrHasNoValue(bodyRep)) { extraParams.ClearOpenings(); return null; } } // We will be able to export as a IfcWallStandardCase as long as we have an axis curve. XYZ extrDirUsed = XYZ.Zero; if (extraParams.HasExtrusionDirection) { extrDirUsed = extraParams.ExtrusionDirection; if (MathUtil.IsAlmostEqual(Math.Abs(extrDirUsed[2]), 1.0)) { if ((solids.Count == 1) && (meshes.Count == 0)) exportedAsWallWithAxis = exportingAxis; exportedBodyDirectly = true; } } } IFCAnyHandle prodRep = null; if (!exportParts) { IList<IFCAnyHandle> representations = new List<IFCAnyHandle>(); if (exportingAxis) representations.Add(axisRep); representations.Add(bodyRep); IFCAnyHandle boundingBoxRep = null; if ((solids.Count > 0) || (meshes.Count > 0)) boundingBoxRep = BoundingBoxExporter.ExportBoundingBox(exporterIFC, solids, meshes, Transform.Identity); else boundingBoxRep = BoundingBoxExporter.ExportBoundingBox(exporterIFC, geometryElement, Transform.Identity); if (boundingBoxRep != null) representations.Add(boundingBoxRep); prodRep = IFCInstanceExporter.CreateProductDefinitionShape(file, null, null, representations); } ElementId matId = ElementId.InvalidElementId; string objectType = NamingUtil.CreateIFCObjectName(exporterIFC, element); IFCAnyHandle wallHnd = null; string elemGUID = null; int subElementIndex = ExporterStateManager.GetCurrentRangeIndex(); if (subElementIndex == 0) elemGUID = GUIDUtil.CreateGUID(element); else if (subElementIndex <= ExporterStateManager.RangeIndexSetter.GetMaxStableGUIDs()) elemGUID = GUIDUtil.CreateSubElementGUID(element, subElementIndex + (int)IFCGenericSubElements.SplitInstanceStart - 1); else elemGUID = GUIDUtil.CreateGUID(); string elemName = NamingUtil.GetNameOverride(element, NamingUtil.GetIFCName(element)); string elemDesc = NamingUtil.GetDescriptionOverride(element, null); string elemObjectType = NamingUtil.GetObjectTypeOverride(element, objectType); string elemTag = NamingUtil.GetTagOverride(element, NamingUtil.CreateIFCElementId(element)); string ifcType = IFCValidateEntry.GetValidIFCType(element, null); // For Foundation and Retaining walls, allow exporting as IfcFooting instead. bool exportAsFooting = false; if (exportingWallElement) { WallType wallType = wallElement.WallType; if (wallType != null) { int wallFunction; if (ParameterUtil.GetIntValueFromElement(wallType, BuiltInParameter.FUNCTION_PARAM, out wallFunction) != null) { if (wallFunction == (int)WallFunction.Retaining || wallFunction == (int)WallFunction.Foundation) { // In this case, allow potential to export foundation and retaining walls as footing. string enumTypeValue = null; IFCExportType exportType = ExporterUtil.GetExportType(exporterIFC, wallElement, out enumTypeValue); if (exportType == IFCExportType.IfcFooting) exportAsFooting = true; } } } } if (exportedAsWallWithAxis) { if (exportAsFooting) { wallHnd = IFCInstanceExporter.CreateFooting(file, elemGUID, ownerHistory, elemName, elemDesc, elemObjectType, localPlacement, exportParts ? null : prodRep, elemTag, ifcType); } else { bool exportAsWall = exportParts; if (!exportAsWall) { // (For Reference View export) If the representation returned earlier is of type Tessellation, create IfcWall instead. foreach (IFCAnyHandle pRep in IFCAnyHandleUtil.GetRepresentations(prodRep)) { if (String.Compare(IFCAnyHandleUtil.GetRepresentationType(pRep), "Tessellation") == 0) { exportAsWall = true; break; } } } if (exportAsWall) { wallHnd = IFCInstanceExporter.CreateWall(file, elemGUID, ownerHistory, elemName, elemDesc, elemObjectType, localPlacement, null, elemTag, ifcType); } else { wallHnd = IFCInstanceExporter.CreateWallStandardCase(file, elemGUID, ownerHistory, elemName, elemDesc, elemObjectType, localPlacement, prodRep, elemTag, ifcType); } } if (exportParts) PartExporter.ExportHostPart(exporterIFC, element, wallHnd, localWrapper, setter, localPlacement, overrideLevelId); localWrapper.AddElement(element, wallHnd, setter, extraParams, true); if (!exportParts) { OpeningUtil.CreateOpeningsIfNecessary(wallHnd, element, cutPairOpenings, null, exporterIFC, localPlacement, setter, localWrapper); if (exportedBodyDirectly) { Transform offsetTransform = (bodyData != null) ? bodyData.OffsetTransform : Transform.Identity; OpeningUtil.CreateOpeningsIfNecessary(wallHnd, element, extraParams, offsetTransform, exporterIFC, localPlacement, setter, localWrapper); } else { double scaledWidth = UnitUtil.ScaleLength(wallElement.Width); OpeningUtil.AddOpeningsToElement(exporterIFC, wallHnd, wallElement, null, scaledWidth, range, setter, localPlacement, localWrapper); } } // export Base Quantities if (ExporterCacheManager.ExportOptionsCache.ExportBaseQuantities) { scaledFootprintArea = MathUtil.AreaIsAlmostZero(scaledFootprintArea) ? extraParams.ScaledArea : scaledFootprintArea; scaledLength = MathUtil.IsAlmostZero(scaledLength) ? extraParams.ScaledLength : scaledLength; PropertyUtil.CreateWallBaseQuantities(exporterIFC, wallElement, solids, meshes, wallHnd, scaledLength, depth, scaledFootprintArea); } } else { if (exportAsFooting) { wallHnd = IFCInstanceExporter.CreateFooting(file, elemGUID, ownerHistory, elemName, elemDesc, elemObjectType, localPlacement, exportParts ? null : prodRep, elemTag, ifcType); } else { wallHnd = IFCInstanceExporter.CreateWall(file, elemGUID, ownerHistory, elemName, elemDesc, elemObjectType, localPlacement, exportParts ? null : prodRep, elemTag, ifcType); } if (exportParts) PartExporter.ExportHostPart(exporterIFC, element, wallHnd, localWrapper, setter, localPlacement, overrideLevelId); localWrapper.AddElement(element, wallHnd, setter, extraParams, true); if (!exportParts) { // Only export one material for 2x2; for future versions, export the whole list. if (ExporterCacheManager.ExportOptionsCache.ExportAs2x2 || exportingFamilyInstance) { matId = BodyExporter.GetBestMaterialIdFromGeometryOrParameter(solids, meshes, element); if (matId != ElementId.InvalidElementId) CategoryUtil.CreateMaterialAssociation(exporterIFC, wallHnd, matId); } if (exportingInplaceOpenings) { OpeningUtil.AddOpeningsToElement(exporterIFC, wallHnd, famInstWallElem, null, 0.0, range, setter, localPlacement, localWrapper); } if (exportedBodyDirectly) { Transform offsetTransform = (bodyData != null) ? bodyData.OffsetTransform : Transform.Identity; OpeningUtil.CreateOpeningsIfNecessary(wallHnd, element, extraParams, offsetTransform, exporterIFC, localPlacement, setter, localWrapper); } } } ElementId wallLevelId = (validRange) ? setter.LevelId : ElementId.InvalidElementId; if ((exportingWallElement || exportingFaceWall) && !exportParts) { HostObject hostObject = null; if (exportingWallElement) hostObject = wallElement; else hostObject = faceWall; if (!ExporterCacheManager.ExportOptionsCache.ExportAs2x2 || exportedAsWallWithAxis) HostObjectExporter.ExportHostObjectMaterials(exporterIFC, hostObject, localWrapper.GetAnElement(), geometryElement, localWrapper, wallLevelId, Toolkit.IFCLayerSetDirection.Axis2, !exportedAsWallWithAxis); } ExportWallType(exporterIFC, localWrapper, wallHnd, element, matId, exportedAsWallWithAxis, exportAsFooting); SpaceBoundingElementUtil.RegisterSpaceBoundingElementHandle(exporterIFC, wallHnd, element.Id, wallLevelId); tr.Commit(); return wallHnd; } } } } }
/// <summary> /// Exports text note elements. /// </summary> /// <param name="exporterIFC"> /// The ExporterIFC object. /// </param> /// <param name="textNote"> /// The text note element. /// </param> /// <param name="productWrapper"> /// The ProductWrapper. /// </param> public static void Export(ExporterIFC exporterIFC, TextNote textNote, ProductWrapper productWrapper) { // Entity not allowed in IFC4RV if (ExporterCacheManager.ExportOptionsCache.ExportAs4ReferenceView) { return; } // Check the intended IFC entity or type name is in the exclude list specified in the UI Common.Enums.IFCEntityType elementClassTypeEnum = Common.Enums.IFCEntityType.IfcAnnotation; if (ExporterCacheManager.ExportOptionsCache.IsElementInExcludeList(elementClassTypeEnum)) { return; } IFCFile file = exporterIFC.GetFile(); using (IFCTransaction tr = new IFCTransaction(file)) { string textString = textNote.Text; if (String.IsNullOrEmpty(textString)) { throw new Exception("TextNote does not have test string."); } ElementId symId = textNote.GetTypeId(); if (symId == ElementId.InvalidElementId) { throw new Exception("TextNote does not have valid type id."); } PresentationStyleAssignmentCache cache = ExporterCacheManager.PresentationStyleAssignmentCache; IFCAnyHandle presHnd = cache.Find(symId); if (IFCAnyHandleUtil.IsNullOrHasNoValue(presHnd)) { TextElementType textElemType = textNote.Symbol; CreatePresentationStyleAssignmentForTextElementType(exporterIFC, textElemType, cache); presHnd = cache.Find(symId); if (IFCAnyHandleUtil.IsNullOrHasNoValue(presHnd)) { throw new Exception("Failed to create presentation style assignment for TextElementType."); } } HashSet <IFCAnyHandle> presHndSet = new HashSet <IFCAnyHandle>(); presHndSet.Add(presHnd); using (PlacementSetter setter = PlacementSetter.Create(exporterIFC, textNote)) { const double planScale = 100.0; // currently hardwired. XYZ orig = UnitUtil.ScaleLength(textNote.Coord); XYZ yDir = textNote.UpDirection; XYZ xDir = textNote.BaseDirection; XYZ zDir = xDir.CrossProduct(yDir); double sizeX = UnitUtil.ScaleLength(textNote.Width * planScale); double sizeY = UnitUtil.ScaleLength(textNote.Height * planScale); // When we display text on screen, we "flip" it if the xDir is negative with relation to // the X-axis. So if it is, we'll flip x and y. bool flipOrig = false; if (xDir.X < 0) { xDir = xDir.Multiply(-1.0); yDir = yDir.Multiply(-1.0); flipOrig = true; } // xFactor, yFactor only used if flipOrig. double xFactor = 0.0, yFactor = 0.0; string boxAlignment = ConvertTextNoteAlignToBoxAlign(textNote, out xFactor, out yFactor); // modify the origin to match the alignment. In Revit, the origin is at the top-left (unless flipped, // then bottom-right). if (flipOrig) { orig = orig.Add(xDir.Multiply(sizeX * xFactor)); orig = orig.Add(yDir.Multiply(sizeY * yFactor)); } IFCAnyHandle origin = ExporterUtil.CreateAxis(file, orig, zDir, xDir); IFCAnyHandle extent = IFCInstanceExporter.CreatePlanarExtent(file, sizeX, sizeY); IFCAnyHandle repItemHnd = IFCInstanceExporter.CreateTextLiteralWithExtent(file, textString, origin, Toolkit.IFCTextPath.Left, extent, boxAlignment); IFCAnyHandle annoTextOccHnd = IFCInstanceExporter.CreateStyledItem(file, repItemHnd, presHndSet, null); ElementId catId = textNote.Category != null ? textNote.Category.Id : ElementId.InvalidElementId; HashSet <IFCAnyHandle> bodyItems = new HashSet <IFCAnyHandle>(); bodyItems.Add(repItemHnd); IFCAnyHandle bodyRepHnd = RepresentationUtil.CreateAnnotationSetRep(exporterIFC, textNote, catId, exporterIFC.Get2DContextHandle(), bodyItems); if (IFCAnyHandleUtil.IsNullOrHasNoValue(bodyRepHnd)) { throw new Exception("Failed to create shape representation."); } IList <IFCAnyHandle> shapeReps = new List <IFCAnyHandle>(); shapeReps.Add(bodyRepHnd); IFCAnyHandle prodShapeHnd = IFCInstanceExporter.CreateProductDefinitionShape(file, null, null, shapeReps); IFCAnyHandle annoHnd = IFCInstanceExporter.CreateAnnotation(exporterIFC, textNote, GUIDUtil.CreateGUID(), ExporterCacheManager.OwnerHistoryHandle, setter.LocalPlacement, prodShapeHnd); productWrapper.AddAnnotation(annoHnd, setter.LevelInfo, true); } tr.Commit(); } }
/// <summary> /// Main implementation to export walls. /// </summary> /// <param name="exporterIFC"> /// The ExporterIFC object. /// </param> /// <param name="element"> /// The element. /// </param> /// <param name="geometryElement"> /// The geometry element. /// </param> /// <param name="origWrapper"> /// The IFCProductWrapper. /// </param> /// <param name="overrideLevelId"> /// The level id. /// </param> /// <param name="range"> /// The range to be exported for the element. /// </param> /// <returns> /// The exported wall handle. /// </returns> public static IFCAnyHandle ExportWallBase(ExporterIFC exporterIFC, Element element, GeometryElement geometryElement, IFCProductWrapper origWrapper, ElementId overrideLevelId, IFCRange range) { using (IFCProductWrapper localWrapper = IFCProductWrapper.Create(origWrapper)) { ElementId catId = CategoryUtil.GetSafeCategoryId(element); Wall wallElement = element as Wall; FamilyInstance famInstWallElem = element as FamilyInstance; if (wallElement == null && famInstWallElem == null) return null; if (wallElement != null && IsWallCompletelyClipped(wallElement, exporterIFC, range)) return null; // get global values. Document doc = element.Document; double scale = exporterIFC.LinearScale; IFCFile file = exporterIFC.GetFile(); IFCAnyHandle ownerHistory = exporterIFC.GetOwnerHistoryHandle(); IFCAnyHandle contextOfItemsAxis = exporterIFC.Get3DContextHandle("Axis"); IFCAnyHandle contextOfItemsBody = exporterIFC.Get3DContextHandle("Body"); IFCRange zSpan = new IFCRange(); double depth = 0.0; bool validRange = (range != null && !MathUtil.IsAlmostZero(range.Start - range.End)); bool exportParts = PartExporter.CanExportParts(wallElement); if (exportParts && !PartExporter.CanExportElementInPartExport(wallElement, validRange? overrideLevelId : wallElement.Level.Id, validRange)) return null; // get bounding box height so that we can subtract out pieces properly. // only for Wall, not FamilyInstance. if (wallElement != null && geometryElement != null) { BoundingBoxXYZ boundingBox = element.get_BoundingBox(null); if (boundingBox == null) return null; zSpan = new IFCRange(boundingBox.Min.Z, boundingBox.Max.Z); // if we have a top clipping plane, modify depth accordingly. double bottomHeight = validRange ? Math.Max(zSpan.Start, range.Start) : zSpan.Start; double topHeight = validRange ? Math.Min(zSpan.End, range.End) : zSpan.End; depth = topHeight - bottomHeight; if (MathUtil.IsAlmostZero(depth)) return null; depth *= scale; } IFCAnyHandle axisRep = null; IFCAnyHandle bodyRep = null; bool exportingAxis = false; Curve curve = null; bool exportedAsWallWithAxis = false; bool exportedBodyDirectly = false; bool exportingInplaceOpenings = false; Curve centerCurve = GetWallAxis(wallElement); XYZ localXDir = new XYZ(1, 0, 0); XYZ localYDir = new XYZ(0, 1, 0); XYZ localZDir = new XYZ(0, 0, 1); XYZ localOrig = new XYZ(0, 0, 0); double eps = MathUtil.Eps(); if (centerCurve != null) { Curve baseCurve = GetWallAxisAtBaseHeight(wallElement); curve = GetWallTrimmedCurve(wallElement, baseCurve); IFCRange curveBounds; XYZ oldOrig; GeometryUtil.GetAxisAndRangeFromCurve(curve, out curveBounds, out localXDir, out oldOrig); localOrig = oldOrig; if (baseCurve != null) { if (!validRange || (MathUtil.IsAlmostEqual(range.Start, zSpan.Start))) { XYZ newOrig = baseCurve.Evaluate(curveBounds.Start, false); if (!validRange && (zSpan.Start < newOrig[2] - eps)) localOrig = new XYZ(localOrig.X, localOrig.Y, zSpan.Start); else localOrig = new XYZ(localOrig.X, localOrig.Y, newOrig[2]); } else { localOrig = new XYZ(localOrig.X, localOrig.Y, range.Start); } } double dist = localOrig[2] - oldOrig[2]; if (!MathUtil.IsAlmostZero(dist)) { XYZ moveVec = new XYZ(0, 0, dist); curve = GeometryUtil.MoveCurve(curve, moveVec); } localYDir = localZDir.CrossProduct(localXDir); // ensure that X and Z axes are orthogonal. double xzDot = localZDir.DotProduct(localXDir); if (!MathUtil.IsAlmostZero(xzDot)) localXDir = localYDir.CrossProduct(localZDir); } Transform orientationTrf = Transform.Identity; orientationTrf.BasisX = localXDir; orientationTrf.BasisY = localYDir; orientationTrf.BasisZ = localZDir; orientationTrf.Origin = localOrig; using (IFCPlacementSetter setter = IFCPlacementSetter.Create(exporterIFC, element, null, orientationTrf, overrideLevelId)) { IFCAnyHandle localPlacement = setter.GetPlacement(); Plane plane = new Plane(localXDir, localYDir, localOrig); // project curve to XY plane. XYZ projDir = XYZ.BasisZ; // two representations: axis, body. { if ((centerCurve != null) && (GeometryUtil.CurveIsLineOrArc(centerCurve))) { exportingAxis = true; string identifierOpt = "Axis"; // IFC2x2 convention string representationTypeOpt = "Curve2D"; // IFC2x2 convention IFCGeometryInfo info = IFCGeometryInfo.CreateCurveGeometryInfo(exporterIFC, plane, projDir, false); ExporterIFCUtils.CollectGeometryInfo(exporterIFC, info, curve, XYZ.Zero, true); IList<IFCAnyHandle> axisItems = info.GetCurves(); if (axisItems.Count == 0) { exportingAxis = false; } else { HashSet<IFCAnyHandle> axisItemSet = new HashSet<IFCAnyHandle>(); foreach (IFCAnyHandle axisItem in axisItems) axisItemSet.Add(axisItem); axisRep = RepresentationUtil.CreateShapeRepresentation(exporterIFC, element, catId, contextOfItemsAxis, identifierOpt, representationTypeOpt, axisItemSet); } } } IList<IFCExtrusionData> cutPairOpenings = new List<IFCExtrusionData>(); Document document = element.Document; if (wallElement != null && exportingAxis && curve != null) { SolidMeshGeometryInfo solidMeshInfo = (range == null) ? GeometryUtil.GetSolidMeshGeometry(geometryElement, Transform.Identity) : GeometryUtil.GetClippedSolidMeshGeometry(geometryElement, range); IList<Solid> solids = solidMeshInfo.GetSolids(); IList<Mesh> meshes = solidMeshInfo.GetMeshes(); if (solids.Count == 0 && meshes.Count == 0) return null; bool useNewCode = false; if (useNewCode && solids.Count == 1 && meshes.Count == 0) { bool completelyClipped; bodyRep = ExtrusionExporter.CreateExtrusionWithClipping(exporterIFC, wallElement, catId, solids[0], plane, projDir, range, out completelyClipped); if (completelyClipped) return null; if (!IFCAnyHandleUtil.IsNullOrHasNoValue(bodyRep)) { exportedAsWallWithAxis = true; exportedBodyDirectly = true; } else { exportedAsWallWithAxis = false; exportedBodyDirectly = false; } } if (!exportedAsWallWithAxis) { // Fallback - use native routines to try to export wall. bool isCompletelyClipped; bodyRep = FallbackTryToCreateAsExtrusion(exporterIFC, wallElement, solidMeshInfo, catId, curve, plane, depth, zSpan, range, setter, out cutPairOpenings, out isCompletelyClipped); if (isCompletelyClipped) return null; if (!IFCAnyHandleUtil.IsNullOrHasNoValue(bodyRep)) exportedAsWallWithAxis = true; } } using (IFCExtrusionCreationData extraParams = new IFCExtrusionCreationData()) { ElementId matId = ElementId.InvalidElementId; if (!exportedAsWallWithAxis) { SolidMeshGeometryInfo solidMeshCapsule = null; if (wallElement != null) { if (validRange) { solidMeshCapsule = GeometryUtil.GetClippedSolidMeshGeometry(geometryElement, range); } else { solidMeshCapsule = GeometryUtil.GetSplitSolidMeshGeometry(geometryElement); } if (solidMeshCapsule.SolidsCount() == 0 && solidMeshCapsule.MeshesCount() == 0) { return null; } } else { GeometryElement geomElemToUse = GetGeometryFromInplaceWall(famInstWallElem); if (geomElemToUse != null) { exportingInplaceOpenings = true; } else { exportingInplaceOpenings = false; geomElemToUse = geometryElement; } Transform trf = Transform.Identity; if (geomElemToUse != geometryElement) trf = famInstWallElem.GetTransform(); solidMeshCapsule = GeometryUtil.GetSolidMeshGeometry(geomElemToUse, trf); } IList<Solid> solids = solidMeshCapsule.GetSolids(); IList<Mesh> meshes = solidMeshCapsule.GetMeshes(); extraParams.PossibleExtrusionAxes = IFCExtrusionAxes.TryZ; // only allow vertical extrusions! extraParams.AreInnerRegionsOpenings = true; BodyExporterOptions bodyExporterOptions = new BodyExporterOptions(true); if ((solids.Count > 0) || (meshes.Count > 0)) { matId = BodyExporter.GetBestMaterialIdForGeometry(solids, meshes); bodyRep = BodyExporter.ExportBody(element.Document.Application, exporterIFC, element, catId, solids, meshes, bodyExporterOptions, extraParams).RepresentationHnd; } else { IList<GeometryObject> geomElemList = new List<GeometryObject>(); geomElemList.Add(geometryElement); BodyData bodyData = BodyExporter.ExportBody(element.Document.Application, exporterIFC, element, catId, geomElemList, bodyExporterOptions, extraParams); bodyRep = bodyData.RepresentationHnd; } if (IFCAnyHandleUtil.IsNullOrHasNoValue(bodyRep)) { extraParams.ClearOpenings(); return null; } // We will be able to export as a IfcWallStandardCase as long as we have an axis curve. XYZ extrDirUsed = XYZ.Zero; if (extraParams.HasExtrusionDirection) { extrDirUsed = extraParams.ExtrusionDirection; if (MathUtil.IsAlmostEqual(Math.Abs(extrDirUsed[2]), 1.0)) { if ((solids.Count == 1) && (meshes.Count == 0)) exportedAsWallWithAxis = exportingAxis; exportedBodyDirectly = true; } } } IFCAnyHandle prodRep = null; IList<IFCAnyHandle> representations = new List<IFCAnyHandle>(); if (exportingAxis) representations.Add(axisRep); representations.Add(bodyRep); prodRep = IFCInstanceExporter.CreateProductDefinitionShape(file, null, null, representations); string objectType = NamingUtil.CreateIFCObjectName(exporterIFC, element); IFCAnyHandle wallHnd = null; string elemGUID = (validRange) ? ExporterIFCUtils.CreateGUID() : ExporterIFCUtils.CreateGUID(element); string elemName = NamingUtil.GetNameOverride(element, exporterIFC.GetName()); string elemDesc = NamingUtil.GetDescriptionOverride(element, null); string elemObjectType = NamingUtil.GetObjectTypeOverride(element, objectType); string elemId = NamingUtil.CreateIFCElementId(element); if (exportedAsWallWithAxis) { wallHnd = IFCInstanceExporter.CreateWallStandardCase(file, elemGUID, ownerHistory, elemName, elemDesc, elemObjectType, localPlacement, exportParts ? null : prodRep, elemId); if (exportParts) PartExporter.ExportHostPart(exporterIFC, wallElement, wallHnd, localWrapper, setter, localPlacement, overrideLevelId); localWrapper.AddElement(wallHnd, setter, extraParams, true); OpeningUtil.CreateOpeningsIfNecessary(wallHnd, element, cutPairOpenings, exporterIFC, localPlacement, setter, localWrapper); if (exportedBodyDirectly) { OpeningUtil.CreateOpeningsIfNecessary(wallHnd, element, extraParams, exporterIFC, localPlacement, setter, localWrapper); } else { double scaledWidth = wallElement.Width * scale; ExporterIFCUtils.AddOpeningsToElement(exporterIFC, wallHnd, wallElement, scaledWidth, range, setter, localPlacement, localWrapper); } // export Base Quantities if (ExporterCacheManager.ExportOptionsCache.ExportBaseQuantities) { CreateWallBaseQuantities(exporterIFC, wallElement, wallHnd, depth); } } else { wallHnd = IFCInstanceExporter.CreateWall(file, elemGUID, ownerHistory, elemName, elemDesc, elemObjectType, localPlacement, exportParts ? null : prodRep, elemId); if (exportParts) PartExporter.ExportHostPart(exporterIFC, wallElement, wallHnd, localWrapper, setter, localPlacement, overrideLevelId); localWrapper.AddElement(wallHnd, setter, extraParams, true); // Only export one material for 2x2; for future versions, export the whole list. if (exporterIFC.ExportAs2x2 && (matId != ElementId.InvalidElementId) && !exportParts) { CategoryUtil.CreateMaterialAssociation(doc, exporterIFC, wallHnd, matId); } if (exportingInplaceOpenings) { ExporterIFCUtils.AddOpeningsToElement(exporterIFC, wallHnd, famInstWallElem, 0.0, range, setter, localPlacement, localWrapper); } if (exportedBodyDirectly) OpeningUtil.CreateOpeningsIfNecessary(wallHnd, element, extraParams, exporterIFC, localPlacement, setter, localWrapper); } PropertyUtil.CreateInternalRevitPropertySets(exporterIFC, element, localWrapper); ElementId wallLevelId = (validRange) ? setter.LevelId : ElementId.InvalidElementId; if (wallElement != null && !exportParts) { if (!exporterIFC.ExportAs2x2 || exportedAsWallWithAxis) //will move this check into ExportHostObject HostObjectExporter.ExportHostObjectMaterials(exporterIFC, wallElement, localWrapper.GetAnElement(), geometryElement, localWrapper, wallLevelId, Toolkit.IFCLayerSetDirection.Axis2); } exporterIFC.RegisterSpaceBoundingElementHandle(wallHnd, element.Id, wallLevelId); return wallHnd; } } } }
private void CalculateDoorWindowInformation(ExporterIFC exporterIFC, FamilyInstance famInst, ElementId overrideLevelId, Transform trf) { IFCFile file = exporterIFC.GetFile(); if (ExportingDoor) { string doorOperationType = null; Element doorType = famInst.Document.GetElement(famInst.GetTypeId()); if (doorType != null) { // Look at the "Operation" override first, then the built-in parameter. ParameterUtil.GetStringValueFromElementOrSymbol(doorType, "Operation", out doorOperationType); if (string.IsNullOrWhiteSpace(doorOperationType)) { ParameterUtil.GetStringValueFromElement(doorType, BuiltInParameter.DOOR_OPERATION_TYPE, out doorOperationType); } } DoorOperationTypeString = "NOTDEFINED"; if (!string.IsNullOrWhiteSpace(doorOperationType)) { Type enumType = null; if (ExporterCacheManager.ExportOptionsCache.ExportAs4) { enumType = typeof(Toolkit.IFC4.IFCDoorStyleOperation); } else { enumType = typeof(Toolkit.IFCDoorStyleOperation); } foreach (Enum ifcDoorStyleOperation in Enum.GetValues(enumType)) { string enumAsString = ifcDoorStyleOperation.ToString(); if (NamingUtil.IsEqualIgnoringCaseSpacesAndUnderscores(enumAsString, doorOperationType)) { DoorOperationTypeString = enumAsString; break; } } } if (DoorOperationTypeString == "NOTDEFINED") { // We are going to try to guess the hinge placement. DoorOperationTypeString = CalculateDoorOperationStyle(famInst, trf); } else { if (FlippedX ^ FlippedY) { DoorOperationTypeString = ReverseDoorStyleOperation(DoorOperationTypeString); } } if (String.Compare(DoorOperationTypeString, "USERDEFINED", true) == 0) { string userDefinedOperationType; ParameterUtil.GetStringValueFromElementOrSymbol(doorType, "UserDefinedOperationType", out userDefinedOperationType); if (!string.IsNullOrEmpty(userDefinedOperationType)) { UserDefinedOperationType = userDefinedOperationType; } else { DoorOperationTypeString = "NOTDEFINED"; //re-set to NotDefined if operation type is set to UserDefined but the userDefinedOperationType parameter is empty! } } } if (HasRealWallHost) { // do hingeside calculation Wall wall = HostObject as Wall; PosHingeSide = true; BoundingBoxXYZ famBBox = null; Options options = GeometryUtil.GetIFCExportGeometryOptions(); GeometryElement geomElement = famInst.GetOriginalGeometry(options); if (geomElement != null) { famBBox = geomElement.GetBoundingBox(); } if (famBBox != null) { XYZ bboxCtr = trf.OfPoint((famBBox.Min + famBBox.Max) / 2.0); Curve curve = WallExporter.GetWallAxis(wall); XYZ wallZDir = WallExporter.GetWallExtrusionDirection(wall); if (wallZDir == null) { wallZDir = XYZ.BasisZ; // Right thing here? } // famInst.HostParameter will fail if FamilyPlacementType is WorkPlaneBased, regardless of whether or not the reported host is a Wall. // In this case, just use the start parameter of the curve. bool hasHostParameter = famInst.Symbol.Family.FamilyPlacementType != FamilyPlacementType.WorkPlaneBased; double param = hasHostParameter ? famInst.HostParameter : curve.GetEndParameter(0); Transform wallTrf = curve.ComputeDerivatives(param, false); XYZ wallOrig = wallTrf.Origin; XYZ wallXDir = wallTrf.BasisX; XYZ wallYDir = wallZDir.CrossProduct(wallXDir); double eps = MathUtil.Eps(); bboxCtr -= wallOrig; PosHingeSide = (bboxCtr.DotProduct(wallYDir) > -eps); XYZ famInstYDir = trf.BasisY; FlippedSymbol = (PosHingeSide != (wallYDir.DotProduct(famInstYDir) > -eps)); } } }
public Dimension CreateLinearDimension( Document doc) { Application app = doc.Application; // first create two lines XYZ pt1 = new XYZ( 5, 5, 0 ); XYZ pt2 = new XYZ( 5, 10, 0 ); Line line = Line.CreateBound( pt1, pt2 ); //Plane plane = app.Create.NewPlane( pt1.CrossProduct( pt2 ), pt2 ); // 2016 Plane plane = Plane.CreateByNormalAndOrigin( pt1.CrossProduct( pt2 ), pt2 ); // 2017 //SketchPlane skplane = doc.FamilyCreate.NewSketchPlane( plane ); // 2013 SketchPlane skplane = SketchPlane.Create( doc, plane ); // 2014 ModelCurve modelcurve1 = doc.FamilyCreate .NewModelCurve( line, skplane ); pt1 = new XYZ( 10, 5, 0 ); pt2 = new XYZ( 10, 10, 0 ); line = Line.CreateBound( pt1, pt2 ); //plane = app.Create.NewPlane( pt1.CrossProduct( pt2 ), pt2 ); // 2016 plane = Plane.CreateByNormalAndOrigin( pt1.CrossProduct( pt2 ), pt2 ); // 2017 //skplane = doc.FamilyCreate.NewSketchPlane( plane ); // 2013 skplane = SketchPlane.Create( doc, plane ); // 2014 ModelCurve modelcurve2 = doc.FamilyCreate .NewModelCurve( line, skplane ); // now create a linear dimension between them ReferenceArray ra = new ReferenceArray(); ra.Append( modelcurve1.GeometryCurve.Reference ); ra.Append( modelcurve2.GeometryCurve.Reference ); pt1 = new XYZ( 5, 10, 0 ); pt2 = new XYZ( 10, 10, 0 ); line = Line.CreateBound( pt1, pt2 ); Dimension dim = doc.FamilyCreate .NewLinearDimension( doc.ActiveView, line, ra ); // create a label for the dimension called "width" FamilyParameter param = doc.FamilyManager .AddParameter( "width", BuiltInParameterGroup.PG_CONSTRAINTS, ParameterType.Length, false ); //dim.Label = param; // 2013 dim.FamilyLabel = param; // 2014 return dim; }
/// <summary> /// Main implementation to export walls. /// </summary> /// <param name="exporterIFC"> /// The ExporterIFC object. /// </param> /// <param name="element"> /// The element. /// </param> /// <param name="geometryElement"> /// The geometry element. /// </param> /// <param name="productWrapper"> /// The IFCProductWrapper. /// </param> /// <param name="overrideLevelId"> /// The level id. /// </param> /// <param name="range"> /// The range to be exported for the element. /// </param> /// <returns> /// The exported wall handle. /// </returns> public static IFCAnyHandle ExportWallBase(ExporterIFC exporterIFC, Element element, GeometryElement geometryElement, IFCProductWrapper productWrapper, ElementId overrideLevelId, UV range) { using (IFCProductWrapper localWrapper = IFCProductWrapper.Create(productWrapper)) { ElementId catId = CategoryUtil.GetSafeCategoryId(element); Wall wallElement = element as Wall; FamilyInstance famInstWallElem = element as FamilyInstance; if (wallElement == null && famInstWallElem == null) return IFCAnyHandle.Create(); if (wallElement != null && IsWallCompletelyClipped(wallElement, exporterIFC, range)) return IFCAnyHandle.Create(); // get global values. Document doc = element.Document; double scale = exporterIFC.LinearScale; IFCFile file = exporterIFC.GetFile(); IFCAnyHandle ownerHistory = exporterIFC.GetOwnerHistoryHandle(); IFCAnyHandle contextOfItems = exporterIFC.Get3DContextHandle(); UV zSpan = UV.Zero; double depth = 0.0; bool validRange = (!MathUtil.IsAlmostZero(range.V - range.U)); // get bounding box height so that we can subtract out pieces properly. // only for Wall, not FamilyInstance. if (wallElement != null && geometryElement != null) { BoundingBoxXYZ boundingBox = element.get_BoundingBox(null); zSpan = new UV(boundingBox.Min.Z, boundingBox.Max.Z); // if we have a top clipping plane, modify depth accordingly. double bottomHeight = validRange ? Math.Max(zSpan[0], range[0]) : zSpan[0]; double topHeight = validRange ? Math.Min(zSpan[1], range[1]) : zSpan[1]; depth = topHeight - bottomHeight; if (MathUtil.IsAlmostZero(depth)) return IFCAnyHandle.Create(); depth *= scale; } IFCAnyHandle axisRep = IFCAnyHandle.Create(); IFCAnyHandle bodyRep = IFCAnyHandle.Create(); bool exportingAxis = false; Curve curve = null; bool exportedAsWallWithAxis = false; bool exportedBodyDirectly = false; bool exportingInplaceOpenings = false; Curve centerCurve = GetWallAxis(wallElement); XYZ localXDir = new XYZ(1, 0, 0); XYZ localYDir = new XYZ(0, 1, 0); XYZ localZDir = new XYZ(0, 0, 1); XYZ localOrig = new XYZ(0, 0, 0); double eps = MathUtil.Eps(); if (centerCurve != null) { Curve baseCurve = GetWallAxisAtBaseHeight(wallElement); curve = GetWallTrimmedCurve(wallElement, baseCurve); UV curveBounds; XYZ oldOrig; GeometryUtil.GetAxisAndRangeFromCurve(curve, out curveBounds, out localXDir, out oldOrig); localOrig = oldOrig; if (baseCurve != null) { if (!validRange || (MathUtil.IsAlmostEqual(range[0], zSpan[0]))) { XYZ newOrig = baseCurve.Evaluate(curveBounds.U, false); if (validRange && (zSpan[0] < newOrig[2] - eps)) localOrig = new XYZ(localOrig.X, localOrig.Y, zSpan[0]); else localOrig = new XYZ(localOrig.X, localOrig.Y, newOrig[2]); } else { localOrig = new XYZ(localOrig.X, localOrig.Y, range[0]); } } double dist = localOrig[2] - oldOrig[2]; if (!MathUtil.IsAlmostZero(dist)) { XYZ moveVec = new XYZ(0, 0, dist); curve = GeometryUtil.MoveCurve(curve, moveVec); } localYDir = localZDir.CrossProduct(localXDir); // ensure that X and Z axes are orthogonal. double xzDot = localZDir.DotProduct(localXDir); if (!MathUtil.IsAlmostZero(xzDot)) localXDir = localYDir.CrossProduct(localZDir); } Transform orientationTrf = Transform.Identity; orientationTrf.BasisX = localXDir; orientationTrf.BasisY = localYDir; orientationTrf.BasisZ = localZDir; orientationTrf.Origin = localOrig; using (IFCPlacementSetter setter = IFCPlacementSetter.Create(exporterIFC, element, null, orientationTrf, overrideLevelId)) { IFCAnyHandle localPlacement = setter.GetPlacement(); Plane plane = new Plane(localXDir, localYDir, localOrig); // project curve to XY plane. XYZ projDir = new XYZ(0, 0, 1); // two representations: axis, body. { if ((centerCurve != null) && (GeometryUtil.CurveIsLineOrArc(centerCurve))) { exportingAxis = true; IFCLabel identifierOpt = IFCLabel.Create("Axis"); // IFC2x2 convention IFCLabel representationTypeOpt = IFCLabel.Create("Curve2D"); // IFC2x2 convention IFCGeometryInfo info = IFCGeometryInfo.CreateCurveGeometryInfo(exporterIFC, plane, projDir, false); ExporterIFCUtils.CollectGeometryInfo(exporterIFC, info, curve, XYZ.Zero, true); IList<IFCAnyHandle> axisItems = info.GetCurves(); if (axisItems.Count == 0) { exportingAxis = false; } else { HashSet<IFCAnyHandle> axisItemSet = new HashSet<IFCAnyHandle>(); foreach (IFCAnyHandle axisItem in axisItems) axisItemSet.Add(axisItem); axisRep = RepresentationUtil.CreateShapeRepresentation(exporterIFC, catId, contextOfItems, identifierOpt, representationTypeOpt, axisItemSet); } } } IList<IFCExtrusionData> cutPairOpenings = new List<IFCExtrusionData>(); do { if (wallElement == null || !exportingAxis || curve == null) break; bool hasExtrusion = HasElevationProfile(wallElement); if (hasExtrusion) { IList<CurveLoop> loops = GetElevationProfile(wallElement); if (loops.Count == 0) hasExtrusion = false; else { IList<IList<CurveLoop>> sortedLoops = ExporterIFCUtils.SortCurveLoops(loops); if (sortedLoops.Count == 0) break; // Current limitation: can't handle wall split into multiple disjointed pieces. int numSortedLoops = sortedLoops.Count; if (numSortedLoops > 1) break; bool ignoreExtrusion = true; bool cantHandle = false; bool hasGeometry = false; for (int ii = 0; (ii < numSortedLoops) && !cantHandle; ii++) { int sortedLoopSize = sortedLoops[ii].Count; if (sortedLoopSize == 0) continue; if (!ExporterIFCUtils.IsCurveLoopConvexWithOpenings(sortedLoops[ii][0], range, wallElement, out ignoreExtrusion)) { if (ignoreExtrusion) { // we need more information. Is there something to export? If so, we'll // ignore the extrusion. Otherwise, we will fail. IFCSolidMeshGeometryInfo solidMeshInfo = ExporterIFCUtils.GetClippedSolidMeshGeometry(exporterIFC, range, geometryElement); if (solidMeshInfo.GetSolids().Count == 0 && solidMeshInfo.GetMeshes().Count == 0) continue; hasExtrusion = false; } else { cantHandle = true; } hasGeometry = true; } else { hasGeometry = true; } } if (!hasGeometry) return IFCAnyHandle.Create(); if (cantHandle) break; } } if (!CanExportWallGeometryAsExtrusion(element, range)) break; // extrusion direction. XYZ extrusionDir = GetWallHeightDirection(wallElement); // create extrusion boundary. IList<CurveLoop> boundaryLoops = new List<CurveLoop>(); bool alwaysThickenCurve = IsWallBaseRectangular(wallElement, curve); if (!alwaysThickenCurve) { boundaryLoops = GetLoopsFromTopBottomFace(wallElement, exporterIFC); if (boundaryLoops.Count == 0) continue; } else { CurveLoop newLoop = CurveLoop.CreateViaThicken(curve, wallElement.Width, new XYZ(0, 0, 1)); if (newLoop == null) break; if (!GeometryUtil.IsIFCLoopCCW(newLoop, new XYZ(0, 0, 1))) newLoop = GeometryUtil.ReverseOrientation(newLoop); boundaryLoops.Add(newLoop); } // origin gets scaled later. XYZ setterOffset = new XYZ(0, 0, setter.Offset + (localOrig[2] - setter.BaseOffset)); IFCAnyHandle baseBodyItemHnd = file.CreateExtrudedSolidFromCurveLoop(exporterIFC, catId, boundaryLoops, plane, extrusionDir, depth); if (!baseBodyItemHnd.HasValue) break; IFCAnyHandle bodyItemHnd = AddClippingsToBaseExtrusion(exporterIFC, wallElement, setterOffset, range, zSpan, baseBodyItemHnd, out cutPairOpenings); if (!bodyItemHnd.HasValue) break; HashSet<IFCAnyHandle> bodyItems = new HashSet<IFCAnyHandle>(); bodyItems.Add(bodyItemHnd); if (baseBodyItemHnd.Id == bodyItemHnd.Id) { bodyRep = RepresentationUtil.CreateSweptSolidRep(exporterIFC, catId, contextOfItems, bodyItems, IFCAnyHandle.Create()); } else { bodyRep = RepresentationUtil.CreateClippingRep(exporterIFC, catId, contextOfItems, bodyItems); } if (bodyRep.HasValue) exportedAsWallWithAxis = true; } while (false); IFCExtrusionCreationData extraParams = new IFCExtrusionCreationData(); ElementId matId = ElementId.InvalidElementId; if (!exportedAsWallWithAxis) { IFCSolidMeshGeometryInfo solidMeshInfo; if (wallElement != null) { if (validRange) { solidMeshInfo = ExporterIFCUtils.GetClippedSolidMeshGeometry(exporterIFC, range, geometryElement); if (solidMeshInfo.GetSolids().Count == 0 && solidMeshInfo.GetMeshes().Count == 0) return IFCAnyHandle.Create(); } else { solidMeshInfo = ExporterIFCUtils.GetSplitSolidMeshGeometry(exporterIFC, geometryElement); } } else { GeometryElement geomElemToUse = GetGeometryFromInplaceWall(famInstWallElem); if (geomElemToUse != null) { exportingInplaceOpenings = true; } else { exportingInplaceOpenings = false; geomElemToUse = geometryElement; } Transform trf = Transform.Identity; if (geomElemToUse != geometryElement) trf = famInstWallElem.GetTransform(); solidMeshInfo = ExporterIFCUtils.GetSolidMeshGeometry(exporterIFC, geomElemToUse, trf); } IList<Solid> solids = solidMeshInfo.GetSolids(); IList<Mesh> meshes = solidMeshInfo.GetMeshes(); extraParams.PossibleExtrusionAxes = IFCExtrusionAxes.TryZ; // only allow vertical extrusions! extraParams.AreInnerRegionsOpenings = true; if ((solids.Count > 0) || (meshes.Count > 0)) { matId = BodyExporter.GetBestMaterialIdForGeometry(solids, meshes); bodyRep = BodyExporter.ExportBody(element.Document.Application, exporterIFC, catId, solids, meshes, true, extraParams); } else { IList<GeometryObject> geomElemList = new List<GeometryObject>(); geomElemList.Add(geometryElement); bodyRep = BodyExporter.ExportBody(element.Document.Application, exporterIFC, catId, geomElemList, true, extraParams); } if (!bodyRep.HasValue) return IFCAnyHandle.Create(); // We will be able to export as a IfcWallStandardCase as long as we have an axis curve. XYZ extrDirUsed = XYZ.Zero; if (extraParams.HasCustomAxis) { extrDirUsed = extraParams.CustomAxis; if (MathUtil.IsAlmostEqual(Math.Abs(extrDirUsed[2]), 1.0)) { if ((solids.Count == 1) && (meshes.Count == 0)) exportedAsWallWithAxis = exportingAxis; exportedBodyDirectly = true; } } } IFCAnyHandle prodRep = IFCAnyHandle.Create(); IList<IFCAnyHandle> representations = new List<IFCAnyHandle>(); if (exportingAxis) representations.Add(axisRep); representations.Add(bodyRep); prodRep = file.CreateProductDefinitionShape(IFCLabel.Create(), IFCLabel.Create(), representations); IFCLabel objectType = NamingUtil.CreateIFCObjectName(exporterIFC, element); IFCAnyHandle wallHnd = IFCAnyHandle.Create(); IFCLabel elemGUID = (validRange) ? IFCLabel.CreateGUID() : IFCLabel.CreateGUID(element); IFCLabel elemName = NamingUtil.GetNameOverride(element, NamingUtil.CreateIFCName(exporterIFC, -1)); IFCLabel elemDesc = NamingUtil.GetDescriptionOverride(element, IFCLabel.Create()); IFCLabel elemObjectType = NamingUtil.GetObjectTypeOverride(element, objectType); IFCLabel elemId = NamingUtil.CreateIFCElementId(element); if (exportedAsWallWithAxis) { wallHnd = file.CreateWallStandardCase(elemGUID, ownerHistory, elemName, elemDesc, elemObjectType, localPlacement, elemId, prodRep); localWrapper.AddElement(wallHnd, setter, extraParams, true); OpeningUtil.CreateOpeningsIfNecessary(wallHnd, element, cutPairOpenings, exporterIFC, localPlacement, setter, localWrapper); if (exportedBodyDirectly) { OpeningUtil.CreateOpeningsIfNecessary(wallHnd, element, extraParams, exporterIFC, localPlacement, setter, localWrapper); } else { double scaledWidth = wallElement.Width * scale; ExporterIFCUtils.AddOpeningsToWall(exporterIFC, wallHnd, wallElement, scaledWidth, range, setter, localPlacement, localWrapper); } // export Base Quantities if (exporterIFC.ExportBaseQuantities) { CreateWallBaseQuantities(exporterIFC, wallElement, wallHnd, depth); } } else { wallHnd = file.CreateWall(elemGUID, ownerHistory, elemName, elemDesc, elemObjectType, localPlacement, elemId, prodRep); localWrapper.AddElement(wallHnd, setter, extraParams, true); // Only export one material for 2x2; for future versions, export the whole list. if (exporterIFC.ExportAs2x2 && (matId != ElementId.InvalidElementId)) { CategoryUtil.CreateMaterialAssociation(doc, exporterIFC, wallHnd, matId); } if (exportingInplaceOpenings) { double scaledWidth = wallElement.Width * scale; ExporterIFCUtils.AddOpeningsToWall(exporterIFC, wallHnd, wallElement, scaledWidth, range, setter, localPlacement, localWrapper); } if (exportedBodyDirectly) OpeningUtil.CreateOpeningsIfNecessary(wallHnd, element, extraParams, exporterIFC, localPlacement, setter, localWrapper); } ExporterIFCUtils.CreateGenericElementPropertySet(exporterIFC, element, localWrapper); ElementId wallLevelId = (validRange) ? setter.LevelId : ElementId.InvalidElementId; if (wallElement != null) ExporterIFCUtils.ExportHostObject(exporterIFC, wallElement, geometryElement, localWrapper); exporterIFC.RegisterSpaceBoundingElementHandle(wallHnd, element.Id, wallLevelId); return wallHnd; } } }