private static Curve FindLongestCurve(Face roomFace) { Curve longestCurve = null; try { IList <CurveLoop> curveLoopList = roomFace.GetEdgesAsCurveLoops(); List <Curve> outerCurves = new List <Curve>(); IList <IList <CurveLoop> > curveLoopLoop = ExporterIFCUtils.SortCurveLoops(curveLoopList); foreach (IList <CurveLoop> curveLoops in curveLoopLoop) { foreach (CurveLoop curveLoop in curveLoops) { if (curveLoop.IsCounterclockwise(roomFace.ComputeNormal(new UV(0, 0)))) { foreach (Curve curve in curveLoop) { outerCurves.Add(curve); } break; } } } outerCurves = outerCurves.OrderByDescending(o => o.ApproximateLength).ToList(); longestCurve = outerCurves.First(); } catch (Exception ex) { string message = ex.Message; } return(longestCurve); }
static private CurveLoop GetOuterCurveLoop(PlanarFace targetFace) { CurveLoop currentCurveLoop = new CurveLoop(); if (targetFace != null) { IList <XYZ> Points = new List <XYZ>(); IList <IList <CurveLoop> > currentListOfListOfCurveLoops = ExporterIFCUtils.SortCurveLoops(targetFace.GetEdgesAsCurveLoops()); if (currentListOfListOfCurveLoops != null) { if (currentListOfListOfCurveLoops.Count > 0) { IList <CurveLoop> currentOuterLoop = currentListOfListOfCurveLoops[0]; if (currentOuterLoop != null) { if (currentOuterLoop.Count > 0) { currentCurveLoop = currentOuterLoop[0]; } } } } } return(currentCurveLoop); }
private WallCollection GetWallInformation(UIDocument uidoc, Document revitDoc, Application app, Wall wall, WallType WallType) { Autodesk.Revit.Creation.Document credoc = revitDoc.Create; Autodesk.Revit.Creation.Application creapp = app.Create; View view = revitDoc.ActiveView; ElementType type = WallType as ElementType; Parameter b = type.get_Parameter((BuiltInParameter.WALL_ATTR_WIDTH_PARAM)); double width = b.AsDouble() / 2; IList <Reference> sideFaces = HostObjectUtils.GetSideFaces(wall, ShellLayerType.Exterior); Element e2 = revitDoc.GetElement(sideFaces[0]); Face face = e2.GetGeometryObjectFromReference(sideFaces[0]) as Face; // The normal of the wall external face. XYZ normal = face.ComputeNormal(new UV(0, 0)); // Offset curve copies for visibility. Transform offset = Transform.CreateTranslation(width * normal); // If the curve loop direction is counter- // clockwise, change its color to RED. // Get edge loops as curve loops. IList <CurveLoop> curveLoops = face.GetEdgesAsCurveLoops(); // ExporterIFCUtils class can also be used for // non-IFC purposes. The SortCurveLoops method // sorts curve loops (edge loops) so that the // outer loops come first. IList <IList <CurveLoop> > curveLoopLoop = ExporterIFCUtils.SortCurveLoops(curveLoops); List <List <Curve> > Walls = new List <List <Curve> >(); WallCollection WCCC = new WallCollection(); foreach (IList <CurveLoop> curveLoops2 in curveLoopLoop) { foreach (CurveLoop curveLoop2 in curveLoops2) { // Check if curve loop is counter-clockwise. CurveArray curves = creapp.NewCurveArray(); List <Curve> CC = new List <Curve>(); foreach (Curve curve in curveLoop2) { curves.Append(curve.CreateTransformed(offset)); CC.Add(curve.CreateTransformed(offset)); } // Create model lines for an curve loop. Walls.Add(CC); WCCC.AddWall(CC); } } return(WCCC); }
// Get Profile-------------------------------------------------------------------- public static List <XYZ> Get_Profile(Document doc, Element element) { List <XYZ> list_Profile_point = new List <XYZ>(); try { IList <Reference> sideFaces = null; if (element.Category.Name == "Walls") { sideFaces = HostObjectUtils.GetSideFaces(element as Wall, ShellLayerType.Exterior); } else { sideFaces = HostObjectUtils.GetTopFaces(element as Floor); } Element e2 = doc.GetElement(sideFaces[0]); Face face = e2.GetGeometryObjectFromReference(sideFaces[0]) as Face; // The normal of the wall external face. XYZ normal = face.ComputeNormal(new UV(0, 0)); // Get edge loops as curve loops. IList <CurveLoop> curveLoops = face.GetEdgesAsCurveLoops(); // ExporterIFCUtils class can also be used for // non-IFC purposes. The SortCurveLoops method // sorts curve loops (edge loops) so that the // outer loops come first. IList <IList <CurveLoop> > curveLoopLoop = ExporterIFCUtils.SortCurveLoops(curveLoops); foreach (IList <CurveLoop> curveLoops2 in curveLoopLoop) { foreach (CurveLoop curveLoop2 in curveLoops2) { // Check if curve loop is counter-clockwise. bool isCCW = curveLoop2.IsCounterclockwise(normal); foreach (Curve curve in curveLoop2) { list_Profile_point.Add(curve.GetEndPoint(0)); } } } } catch (Exception ex) { MessageBox.Show(ex.Message); } return(list_Profile_point); }
/// <summary> /// Alternative implementation published January 23, 2015: /// http://thebuildingcoder.typepad.com/blog/2015/01/getting-the-wall-elevation-profile.html /// </summary> public Result Execute2( ExternalCommandData commandData, ref string message, ElementSet elements) { UIApplication uiapp = commandData.Application; UIDocument uidoc = uiapp.ActiveUIDocument; Application app = uiapp.Application; Document doc = uidoc.Document; View view = doc.ActiveView; Autodesk.Revit.Creation.Application creapp = app.Create; Autodesk.Revit.Creation.Document credoc = doc.Create; Reference r = uidoc.Selection.PickObject( ObjectType.Element, "Select a wall"); Element e = uidoc.Document.GetElement(r); Wall wall = e as Wall; using (Transaction tx = new Transaction(doc)) { tx.Start("Wall Profile"); // Get the external wall face for the profile IList <Reference> sideFaces = HostObjectUtils.GetSideFaces(wall, ShellLayerType.Exterior); Element e2 = doc.GetElement(sideFaces[0]); Face face = e2.GetGeometryObjectFromReference( sideFaces[0]) as Face; // The normal of the wall external face. XYZ normal = face.ComputeNormal(new UV(0, 0)); // Offset curve copies for visibility. Transform offset = Transform.CreateTranslation( 5 * normal); // If the curve loop direction is counter- // clockwise, change its color to RED. Color colorRed = new Color(255, 0, 0); // Get edge loops as curve loops. IList <CurveLoop> curveLoops = face.GetEdgesAsCurveLoops(); // ExporterIFCUtils class can also be used for // non-IFC purposes. The SortCurveLoops method // sorts curve loops (edge loops) so that the // outer loops come first. IList <IList <CurveLoop> > curveLoopLoop = ExporterIFCUtils.SortCurveLoops( curveLoops); foreach (IList <CurveLoop> curveLoops2 in curveLoopLoop) { foreach (CurveLoop curveLoop2 in curveLoops2) { // Check if curve loop is counter-clockwise. bool isCCW = curveLoop2.IsCounterclockwise( normal); CurveArray curves = creapp.NewCurveArray(); foreach (Curve curve in curveLoop2) { curves.Append(curve.CreateTransformed(offset)); } // Create model lines for an curve loop. //Plane plane = creapp.NewPlane( curves ); // 2016 Plane plane = curveLoop2.GetPlane(); // 2017 SketchPlane sketchPlane = SketchPlane.Create(doc, plane); ModelCurveArray curveElements = credoc.NewModelCurveArray(curves, sketchPlane); if (isCCW) { foreach (ModelCurve mcurve in curveElements) { OverrideGraphicSettings overrides = view.GetElementOverrides( mcurve.Id); overrides.SetProjectionLineColor( colorRed); view.SetElementOverrides( mcurve.Id, overrides); } } } } tx.Commit(); } return(Result.Succeeded); }
/// <summary> /// Exports an element as an annotation. /// </summary> /// <param name="exporterIFC">The ExporterIFC object.</param> /// <param name="filledRegion">The filled region element.</param> /// <param name="geometryElement">The geometry element.</param> /// <param name="productWrapper">The ProductWrapper.</param> public static void Export(ExporterIFC exporterIFC, FilledRegion filledRegion, GeometryElement geometryElement, ProductWrapper productWrapper) { if (filledRegion == null || geometryElement == null) { 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 transaction = new IFCTransaction(file)) { IList <CurveLoop> boundaries = filledRegion.GetBoundaries(); if (boundaries.Count == 0) { return; } Plane plane = null; try { plane = boundaries[0].GetPlane(); } catch { return; } Transform orientTrf = GeometryUtil.CreateTransformFromPlane(plane); XYZ projectionDirection = plane.Normal; IList <IList <CurveLoop> > sortedLoops = ExporterIFCUtils.SortCurveLoops(boundaries); if (sortedLoops.Count == 0) { return; } FilledRegionType filledRegionType = filledRegion.Document.GetElement(filledRegion.GetTypeId()) as FilledRegionType; Color color = filledRegionType != null?CategoryUtil.GetSafeColor(filledRegionType.ForegroundPatternColor) : new Color(0, 0, 0); ElementId foregroundPatternId = filledRegionType != null ? filledRegionType.ForegroundPatternId : ElementId.InvalidElementId; ElementId categoryId = CategoryUtil.GetSafeCategoryId(filledRegion); using (PlacementSetter setter = PlacementSetter.Create(exporterIFC, filledRegion, null, orientTrf)) { foreach (IList <CurveLoop> curveLoopList in sortedLoops) { IFCAnyHandle outerCurve = null; HashSet <IFCAnyHandle> innerCurves = null; for (int ii = 0; ii < curveLoopList.Count; ii++) { IFCAnyHandle ifcCurve = GeometryUtil.CreateIFCCurveFromCurveLoop(exporterIFC, curveLoopList[ii], orientTrf, projectionDirection); if (ii == 0) { outerCurve = ifcCurve; } else { if (innerCurves == null) { innerCurves = new HashSet <IFCAnyHandle>(); } innerCurves.Add(ifcCurve); } } IFCAnyHandle representItem = IFCInstanceExporter.CreateAnnotationFillArea(file, outerCurve, innerCurves); file.CreateStyle(exporterIFC, representItem, color, foregroundPatternId); HashSet <IFCAnyHandle> bodyItems = new HashSet <IFCAnyHandle>(); bodyItems.Add(representItem); IFCAnyHandle bodyRepHnd = RepresentationUtil.CreateAnnotationSetRep(exporterIFC, filledRegion, categoryId, exporterIFC.Get2DContextHandle(), bodyItems); if (IFCAnyHandleUtil.IsNullOrHasNoValue(bodyRepHnd)) { return; } List <IFCAnyHandle> shapeReps = new List <IFCAnyHandle>(); shapeReps.Add(bodyRepHnd); IFCAnyHandle productShape = IFCInstanceExporter.CreateProductDefinitionShape(file, null, null, shapeReps); IFCAnyHandle annotation = IFCInstanceExporter.CreateAnnotation(exporterIFC, filledRegion, GUIDUtil.CreateGUID(), ExporterCacheManager.OwnerHistoryHandle, setter.LocalPlacement, productShape); productWrapper.AddAnnotation(annotation, setter.LevelInfo, true); } } transaction.Commit(); } }
private static IList <GeometryObject> GetGeometryObjectsFromFace(Face face) { IList <GeometryObject> shapeGeometries = null; try { List <CurveLoop> profiles = new List <CurveLoop>(); XYZ normal = face.ComputeNormal(new UV(0, 0)); IList <CurveLoop> curveLoops = face.GetEdgesAsCurveLoops(); IList <IList <CurveLoop> > sortedCurveLoops = ExporterIFCUtils.SortCurveLoops(curveLoops); foreach (IList <CurveLoop> curveLoopList in sortedCurveLoops) { foreach (CurveLoop curveLoop in curveLoopList) { if (curveLoop.IsCounterclockwise(normal)) { profiles.Insert(0, curveLoop); } else { profiles.Add(curveLoop); } } } List <List <XYZ> > allLoopVertices = new List <List <XYZ> >(); for (int i = 0; i < profiles.Count; i++) { List <XYZ> vertices = new List <XYZ>(); CurveLoop curveLoop = profiles[i]; foreach (Curve curve in curveLoop) { IList <XYZ> tessellatedVertices = curve.Tessellate(); tessellatedVertices.RemoveAt(tessellatedVertices.Count - 1); vertices.AddRange(tessellatedVertices); } allLoopVertices.Add(vertices); } TessellatedShapeBuilder builder = new TessellatedShapeBuilder(); builder.OpenConnectedFaceSet(false); TessellatedFace tesseFace = new TessellatedFace(allLoopVertices.ToArray(), ElementId.InvalidElementId); if (builder.DoesFaceHaveEnoughLoopsAndVertices(tesseFace)) { builder.AddFace(tesseFace); } builder.CloseConnectedFaceSet(); #if RELEASE2015 || RELEASE2016 TessellatedShapeBuilderResult result = builder.Build(TessellatedShapeBuilderTarget.AnyGeometry, TessellatedShapeBuilderFallback.Mesh, ElementId.InvalidElementId); #else builder.Target = TessellatedShapeBuilderTarget.AnyGeometry; builder.Fallback = TessellatedShapeBuilderFallback.Mesh; builder.Build(); TessellatedShapeBuilderResult result = builder.GetBuildResult(); #endif shapeGeometries = result.GetGeometricalObjects(); } catch (Exception ex) { MessageBox.Show("Failed to get geometry objects from a face.\n" + ex.Message, "Get Geometry Objects", MessageBoxButtons.OK, MessageBoxIcon.Warning); } return(shapeGeometries); }
private Result SlopeSelectedBuildingPad(UIDocument targetUIdoc, ref string message, double maxPointDistInFeet, double targetAngleInRadians) { Document doc = targetUIdoc.Document; Selection sel = targetUIdoc.Selection; View3D current3dView = doc.ActiveView as View3D; if (current3dView == null) { message = Properties.Messages.SlopeGradingFromPads_Not3DView; return(Result.Failed); } BuildingPad selectedBuildingPad = doc.GetElement(sel.PickObject(ObjectType.Element, new PadSelectionFilter(), Properties.Messages.SlopeGradingFromPads_SelectPad)) as BuildingPad; //Check if the Pad is associate with a Surface (never seen one doesnt, but anyways) ElementId topoElementID = selectedBuildingPad.HostId; if (topoElementID.Equals(ElementId.InvalidElementId)) { message = Properties.Messages.SlopeGradingFromPads_NoTopoAssociate; return(Result.Failed); } TopographySurface currentTopo = doc.GetElement(topoElementID) as TopographySurface; if (currentTopo == null) { message = Properties.Messages.SlopeGradingFromPads_NoTopoAssociate;; return(Result.Failed); } IList <CurveLoop> PadBoundaryLoops = new List <CurveLoop>(); CurveLoop outerLoop = null; IList <Reference> TopFacesReferences = HostObjectUtils.GetTopFaces(selectedBuildingPad); if (TopFacesReferences.Count > 1) { message = Properties.Messages.SlopeGradingFromPads_PadsWithMoreThanOneUpperFace; return(Result.Failed); } XYZ plannarDirection = XYZ.BasisZ; XYZ plannarOrigin = XYZ.Zero; // interate on the only face foreach (Reference currentFaceRef in TopFacesReferences) { GeometryObject currentFaceObj = selectedBuildingPad.GetGeometryObjectFromReference(currentFaceRef); if (currentFaceObj is PlanarFace) { PlanarFace currentPlanarFace = currentFaceObj as PlanarFace; plannarDirection = currentPlanarFace.FaceNormal; plannarOrigin = currentPlanarFace.Origin; PadBoundaryLoops = currentPlanarFace.GetEdgesAsCurveLoops(); } else { message = Properties.Messages.SlopeGradingFromPads_UpperFaceNotPlanar; return(Result.Failed); } } //Sort the curves so the outer loop comes first IList <IList <CurveLoop> > curveLoopLoop = ExporterIFCUtils.SortCurveLoops(PadBoundaryLoops); if (curveLoopLoop.Count > 0) { IList <CurveLoop> firstList = curveLoopLoop.First(); if (firstList.Count > 0) { outerLoop = firstList.First(); } } if (outerLoop == null) { message = Properties.Messages.SlopeGradingFromPads_OuterLoopIssue; return(Result.Failed); } //This will be the list of elements that the ReferenceIntersector will shoot the rays //If we try to shoot the rays only in the toposurface and the it has subregions, the reference //intersection will not recognize these regions, so its necessary to shoot rays to the surface and its subregions IList <ElementId> currentSubRegionsAndSurface = currentTopo.GetHostedSubRegionIds(); currentSubRegionsAndSurface.Add(topoElementID); //Search for the max distance from the Pad to the topography //Doesnt matter if it is upwards or downwards, but we will check that, since the ray has to go to one direction //This is to estabilish what the distance will be using to create the slope to the right amount ReferenceIntersector topoRefIntersec = new ReferenceIntersector(currentSubRegionsAndSurface, FindReferenceTarget.Mesh, current3dView); double maxDist = double.NegativeInfinity; foreach (Curve currentCurve in outerLoop) { int numberOfInteractions = 0; double increaseAmount = 0; double currentParameter = 0; EstabilishInteractionPoints(currentCurve, maxPointDistInFeet, out numberOfInteractions, out increaseAmount); for (int i = 0; i < numberOfInteractions; i++) { if (i == 0) { currentParameter = 0; } else { currentParameter += increaseAmount; } XYZ currentPointToEvaluate = currentCurve.Evaluate(currentParameter, true); ReferenceWithContext currentRefContext = topoRefIntersec.FindNearest(currentPointToEvaluate, XYZ.BasisZ); if (currentRefContext == null) { currentRefContext = topoRefIntersec.FindNearest(currentPointToEvaluate, XYZ.BasisZ.Negate()); } if (currentRefContext == null) { continue; } double currentDist = currentRefContext.Proximity; if (currentDist > maxDist) { maxDist = currentDist; } } } // if we haven't changed the maxdist yet, something went wrong if (maxDist == double.NegativeInfinity) { message = Properties.Messages.SlopeGradingFromPads_NoTopoAssociate; return(Result.Failed); } //Estabilish the offset from the pad double offsetDist = maxDist / Math.Tan(targetAngleInRadians); using (TopographyEditScope topoEditGroup = new TopographyEditScope(doc, Properties.Messages.SlopeGradingFromPads_Transaction)) { topoEditGroup.Start(topoElementID); using (Transaction t = new Transaction(doc, Properties.Messages.SlopeGradingFromPads_Transaction)) { t.Start(); CurveLoop offsetLoop = null; try { offsetLoop = CurveLoop.CreateViaOffset(outerLoop, offsetDist, plannarDirection); } catch { message += Properties.Messages.SlopeGradingFromPads_OuterOffsetLoopIssue; return(Result.Failed); } #region DebugCurve Loop //Plane p = new Plane(plannarDirection, plannarOrigin); //SketchPlane sktP = SketchPlane.Create(doc, p); //foreach (Curve currentOffsetCurve in offsetLoop) //{ // doc.Create.NewModelCurve(currentOffsetCurve, sktP); //} #endregion foreach (Curve currentOffsetCurve in offsetLoop) { int numberOfInteractions = 0; double increaseAmount = 0; double currentParameter = 0; EstabilishInteractionPoints(currentOffsetCurve, maxPointDistInFeet, out numberOfInteractions, out increaseAmount); for (int i = 0; i < numberOfInteractions; i++) { if (i == 0) { currentParameter = 0; } else { currentParameter += increaseAmount; } XYZ currentPointOffset = currentOffsetCurve.Evaluate(currentParameter, true); ReferenceWithContext currentRefContext = topoRefIntersec.FindNearest(currentPointOffset, XYZ.BasisZ); if (currentRefContext == null) { currentRefContext = topoRefIntersec.FindNearest(currentPointOffset, XYZ.BasisZ.Negate()); } //if we couldn't find points upwards and downwards, the topo is near the border, so we cant add points if (currentRefContext == null) { continue; } Reference currentReference = currentRefContext.GetReference(); XYZ currentPointToAdd = currentReference.GlobalPoint; if (currentTopo.ContainsPoint(currentPointToAdd)) { continue; } IList <XYZ> ListPointToAdd = new List <XYZ>(); ListPointToAdd.Add(currentPointToAdd); currentTopo.AddPoints(ListPointToAdd); } } foreach (Curve currentCurve in outerLoop) { int numberOfInteractions = 0; double increaseAmount = 0; double currentParameter = 0; EstabilishInteractionPoints(currentCurve, maxPointDistInFeet, out numberOfInteractions, out increaseAmount); for (int i = 0; i < numberOfInteractions; i++) { if (i == 0) { currentParameter = 0; } else { currentParameter += increaseAmount; } XYZ currentPointToAdd = currentCurve.Evaluate(currentParameter, true); if (currentTopo.ContainsPoint(currentPointToAdd)) { continue; } IList <XYZ> ListPointToAdd = new List <XYZ>(); ListPointToAdd.Add(currentPointToAdd); currentTopo.AddPoints(ListPointToAdd); } } t.Commit(); } topoEditGroup.Commit(new TopographyFailurePreprocessor()); return(Result.Succeeded); } }
private static List <Polygon> GetProfile(this Autodesk.Revit.DB.Element element) { Document doc = element.Document; List <Polygon> polygons = new List <Polygon>(); IList <Reference> firstSideFaces = null; IList <Reference> secondSideFaces = null; switch (element) { case Wall revitWall: //use host object utils to get the outside face firstSideFaces = HostObjectUtils.GetSideFaces(revitWall, ShellLayerType.Exterior); secondSideFaces = HostObjectUtils.GetSideFaces(revitWall, ShellLayerType.Interior); break; case Autodesk.Revit.DB.Floor revitFloor: firstSideFaces = HostObjectUtils.GetTopFaces(revitFloor); secondSideFaces = HostObjectUtils.GetBottomFaces(revitFloor); break; } Element faceElement = doc.GetElement(firstSideFaces[0]); if (!(faceElement.GetGeometryObjectFromReference(firstSideFaces[0]) is Face exteriorFace) || !(faceElement.GetGeometryObjectFromReference(secondSideFaces[0]) is Face interiorFace)) { return(null); } //this lets us pick the biggest face of the two sides. This is important because we want the shapes to close. 😁 Face face = exteriorFace.Area > interiorFace.Area ? exteriorFace : interiorFace; // get the edges as curve loops and use the IFCUtils to sort them // credit: https://thebuildingcoder.typepad.com/blog/2015/01/getting-the-wall-elevation-profile.html IList <CurveLoop> curveLoops = face.GetEdgesAsCurveLoops(); //this does the sorting so outside is the first item IList <CurveLoop> loops = ExporterIFCUtils.SortCurveLoops(curveLoops)[0]; for (int i = 0; i < loops.Count; i++) { //here for outermost loop if (i == 0) { var outer = loops[i]; List <Vector3> vertices = new List <Vector3>(); foreach (Autodesk.Revit.DB.Curve c in outer) { vertices.Add(c.GetEndPoint(0).ToVector3()); } polygons.Add(new Polygon(vertices)); } //here for the inner loops (voids) else { var inner = loops[i]; List <Vector3> vertices = new List <Vector3>(); foreach (Autodesk.Revit.DB.Curve c in inner) { vertices.Add(c.GetEndPoint(0).ToVector3()); } Polygon innerPolygon = new Polygon(vertices); polygons.Add(innerPolygon); } } return(polygons); }
/// <summary> /// 对一组曲线循环进行排序,以使外部循环和内部循环分开 /// more info :https://thebuildingcoder.typepad.com/blog/2015/01/exporterifcutils-curve-loop-sort-and-validate.html /// </summary> /// <param name="loops"></param> /// <returns>循环的排序集合</returns> /// <remarks> /// 外层循环是分开的,内层循环是根据它们的外层循环分组的。假定循环是不相交的,并且内部循环不会嵌套,即,内部循环的内部循环是另一个外部循环。 /// </remarks> public static IList <IList <CurveLoop> > SortCurveLoops(this IList <CurveLoop> loops) { return(ExporterIFCUtils.SortCurveLoops(loops)); }
/// <summary> /// Exports an element as an annotation. /// </summary> /// <param name="exporterIFC">The ExporterIFC object.</param> /// <param name="filledRegion">The filled region element.</param> /// <param name="geometryElement">The geometry element.</param> /// <param name="productWrapper">The ProductWrapper.</param> public static void Export(ExporterIFC exporterIFC, FilledRegion filledRegion, GeometryElement geometryElement, ProductWrapper productWrapper) { if (filledRegion == null || geometryElement == null) { return; } IFCFile file = exporterIFC.GetFile(); using (IFCTransaction transaction = new IFCTransaction(file)) { IList <CurveLoop> boundaries = filledRegion.GetBoundaries(); if (boundaries.Count == 0) { return; } Plane plane = null; try { plane = boundaries[0].GetPlane(); } catch { return; } Transform orientTrf = Transform.Identity; orientTrf.BasisX = plane.XVec; orientTrf.BasisY = plane.YVec; orientTrf.BasisZ = plane.Normal; orientTrf.Origin = plane.Origin; XYZ projectionDirection = plane.Normal; IList <IList <CurveLoop> > sortedLoops = ExporterIFCUtils.SortCurveLoops(boundaries); if (sortedLoops.Count == 0) { return; } FilledRegionType filledRegionType = filledRegion.Document.GetElement(filledRegion.GetTypeId()) as FilledRegionType; Color color = filledRegionType != null ? filledRegionType.Color : new Color(0, 0, 0); ElementId fillPatternId = filledRegionType != null ? filledRegionType.FillPatternId : ElementId.InvalidElementId; ElementId categoryId = CategoryUtil.GetSafeCategoryId(filledRegion); using (PlacementSetter setter = PlacementSetter.Create(exporterIFC, filledRegion, null, orientTrf)) { foreach (IList <CurveLoop> curveLoopList in sortedLoops) { IFCAnyHandle outerCurve = null; HashSet <IFCAnyHandle> innerCurves = null; for (int ii = 0; ii < curveLoopList.Count; ii++) { IFCAnyHandle ifcCurve = GeometryUtil.CreateIFCCurveFromCurveLoop(exporterIFC, curveLoopList[ii], plane, projectionDirection); if (ii == 0) { outerCurve = ifcCurve; } else { if (innerCurves == null) { innerCurves = new HashSet <IFCAnyHandle>(); } innerCurves.Add(ifcCurve); } } IFCAnyHandle representItem = IFCInstanceExporter.CreateAnnotationFillArea(file, outerCurve, innerCurves); file.CreateStyle(exporterIFC, representItem, color, fillPatternId); HashSet <IFCAnyHandle> bodyItems = new HashSet <IFCAnyHandle>(); bodyItems.Add(representItem); IFCAnyHandle bodyRepHnd = RepresentationUtil.CreateAnnotationSetRep(exporterIFC, filledRegion, categoryId, exporterIFC.Get2DContextHandle(), bodyItems); if (IFCAnyHandleUtil.IsNullOrHasNoValue(bodyRepHnd)) { return; } List <IFCAnyHandle> shapeReps = new List <IFCAnyHandle>(); shapeReps.Add(bodyRepHnd); IFCAnyHandle productShape = IFCInstanceExporter.CreateProductDefinitionShape(file, null, null, shapeReps); IFCAnyHandle annotation = IFCInstanceExporter.CreateAnnotation(file, GUIDUtil.CreateGUID(), exporterIFC.GetOwnerHistoryHandle(), null, null, null, setter.LocalPlacement, productShape); productWrapper.AddAnnotation(annotation, setter.LevelInfo, true); } } transaction.Commit(); } }
/// <summary> /// Add the 2D projection of the given face /// to the current element outline union /// </summary> static public bool AddToUnion( Polygons union, VertexLookup vl, Clipper c, Face f) { IList <CurveLoop> loops = f.GetEdgesAsCurveLoops(); // ExporterIFCUtils class can also be used for // non-IFC purposes. The SortCurveLoops method // sorts curve loops (edge loops) so that the // outer loops come first. IList <IList <CurveLoop> > sortedLoops = ExporterIFCUtils.SortCurveLoops(loops); int n = loops.Count; Debug.Assert(0 < n, "expected at least one face loop"); Polygons faces = new Polygons(n); Polygon face2d = new Polygon(loops[0].NumberOfCurves()); //foreach( IList<CurveLoop> loops2 // in sortedLoops ) foreach (CurveLoop loop in loops) { // Outer curve loops are counter-clockwise if (loop.IsCounterclockwise(XYZ.BasisZ)) { face2d.Clear(); foreach (Curve curve in loop) { IList <XYZ> pts = curve.Tessellate(); IntPoint a = vl.GetOrAdd(pts[0]); face2d.Add(a); n = pts.Count; for (int i = 1; i < n; ++i) { IntPoint b = vl.GetOrAdd(pts[i]); if (b != a) { face2d.Add(b); a = b; } } } faces.Add(face2d); } } return(c.AddPaths(faces, PolyType.ptSubject, true)); }