/// <summary> /// /// </summary> /// <param name="room"></param> /// <param name="boundaryLocation"></param> /// <returns></returns> public static double Height(Element room, string boundaryLocation = "Center") { if (room == null) { throw new ArgumentNullException(nameof(room)); } var bLoc = (Autodesk.Revit.DB.SpatialElementBoundaryLocation)Enum.Parse(typeof(Autodesk.Revit.DB.SpatialElementBoundaryLocation), boundaryLocation); var bOptions = new Autodesk.Revit.DB.SpatialElementBoundaryOptions { SpatialElementBoundaryLocation = bLoc }; var doc = DocumentManager.Instance.CurrentDBDocument; var rm = (Autodesk.Revit.DB.SpatialElement)room.InternalElement; var calculator = new Autodesk.Revit.DB.SpatialElementGeometryCalculator(doc, bOptions); var result = calculator.CalculateSpatialElementGeometry(rm); var geo = result.GetGeometry(); var bb = geo.GetBoundingBox(); var height = bb.Max.Z - bb.Min.Z; var fu = Autodesk.Revit.DB.UnitUtils.GetAllMeasurableSpecs() .FirstOrDefault(x => x.TypeId.StartsWith("autodesk.spec.aec:length")); var units = doc.GetUnits().GetFormatOptions(fu); return(Autodesk.Revit.DB.UnitUtils.ConvertFromInternalUnits(height, units.GetUnitTypeId())); }
/// <summary> /// /// </summary> /// <param name="room"></param> /// <param name="boundaryLocation"></param> /// <returns></returns> public static List <Curve> Boundaries(Element room, string boundaryLocation = "Center") { if (room == null) { throw new ArgumentNullException(nameof(room)); } var bLoc = (Autodesk.Revit.DB.SpatialElementBoundaryLocation)Enum.Parse(typeof(Autodesk.Revit.DB.SpatialElementBoundaryLocation), boundaryLocation); var bOptions = new Autodesk.Revit.DB.SpatialElementBoundaryOptions { SpatialElementBoundaryLocation = bLoc }; var rm = (Autodesk.Revit.DB.SpatialElement)room.InternalElement; var boundarySegments = rm.GetBoundarySegments(bOptions).First().ToList(); return(boundarySegments.Select(x => x.GetCurve().ToProtoType()).ToList()); }
private IEnumerable <IEnumerable <Autodesk.DesignScript.Geometry.Curve> > GetBoundaries(Autodesk.Revit.DB.SpatialElementBoundaryLocation position) { var options = new Autodesk.Revit.DB.SpatialElementBoundaryOptions() { SpatialElementBoundaryLocation = position, StoreFreeBoundaryFaces = true }; var boundaries = new List <List <Autodesk.DesignScript.Geometry.Curve> >(); foreach (var segments in this.InternalRevitElement.GetBoundarySegments(options)) { var boundary = new List <Autodesk.DesignScript.Geometry.Curve>(); foreach (Autodesk.Revit.DB.BoundarySegment segment in segments) { boundary.Add(segment.GetCurve().ToProtoType()); } boundaries.Add(boundary); } return(boundaries); }
/// <summary> /// /// </summary> /// <param name="room"></param> /// <param name="boundaryLocation"></param> /// <returns></returns> public static double Height(Element room, string boundaryLocation = "Center") { if (room == null) { throw new ArgumentNullException(nameof(room)); } var bLoc = (Autodesk.Revit.DB.SpatialElementBoundaryLocation)Enum.Parse(typeof(Autodesk.Revit.DB.SpatialElementBoundaryLocation), boundaryLocation); var bOptions = new Autodesk.Revit.DB.SpatialElementBoundaryOptions { SpatialElementBoundaryLocation = bLoc }; var doc = DocumentManager.Instance.CurrentDBDocument; var rm = (Autodesk.Revit.DB.SpatialElement)room.InternalElement; var calculator = new Autodesk.Revit.DB.SpatialElementGeometryCalculator(doc, bOptions); var result = calculator.CalculateSpatialElementGeometry(rm); var geo = result.GetGeometry(); var bb = geo.GetBoundingBox(); var height = bb.Max.Z - bb.Min.Z; var units = doc.GetUnits().GetFormatOptions(Autodesk.Revit.DB.UnitType.UT_Length); return(Autodesk.Revit.DB.UnitUtils.ConvertFromInternalUnits(height, units.DisplayUnits)); }
public static Dictionary <string, object> Faces(Element room, string boundaryLocation = "Center") { if (room == null) { throw new ArgumentNullException(nameof(room)); } var bLoc = (Autodesk.Revit.DB.SpatialElementBoundaryLocation)Enum.Parse(typeof(Autodesk.Revit.DB.SpatialElementBoundaryLocation), boundaryLocation); var bOptions = new Autodesk.Revit.DB.SpatialElementBoundaryOptions { SpatialElementBoundaryLocation = bLoc }; var doc = DocumentManager.Instance.CurrentDBDocument; var rm = (Autodesk.Revit.DB.SpatialElement)room.InternalElement; var calculator = new Autodesk.Revit.DB.SpatialElementGeometryCalculator(doc, bOptions); var result = calculator.CalculateSpatialElementGeometry(rm); var segments = rm.GetBoundarySegments(bOptions); var outerBoundaryCurves = new List <Autodesk.Revit.DB.Curve>(); var innerBoundaryCurves = new List <Autodesk.Revit.DB.Curve>(); for (var i = 0; i < segments.Count; i++) { if (i == 0) { outerBoundaryCurves = segments[i].Select(x => x.GetCurve()).ToList(); } else { innerBoundaryCurves.AddRange(segments[i].Select(x => x.GetCurve())); } } var bottom = new List <Surface>(); var top = new List <Surface>(); var boundary = new List <Surface>(); var holes = new List <Surface>(); var faces = result.GetGeometry().Faces; for (var i = 0; i < faces.Size; i++) { var face = faces.get_Item(i); var boundaryFaces = result.GetBoundaryFaceInfo(face).FirstOrDefault(); if (boundaryFaces?.SubfaceType == Autodesk.Revit.DB.SubfaceType.Top) { top.Add(face.ToProtoType().First()); continue; } if (boundaryFaces?.SubfaceType == Autodesk.Revit.DB.SubfaceType.Bottom) { bottom.Add(face.ToProtoType().First()); continue; } var edges = face.GetEdgesAsCurveLoops().First(); // first loop is outer boundary, first curve is bottom edge var outerIndex = outerBoundaryCurves.FindIndex(x => edges.Any(y => y.OverlapsWith(x))); var innerIndex = innerBoundaryCurves.FindIndex(x => edges.Any(y => y.OverlapsWith(x))); if (outerIndex != -1) { boundary.Add(face.ToProtoType().First()); } if (innerIndex != -1) { holes.Add(face.ToProtoType().First()); } } return(new Dictionary <string, object> { { "Boundary", boundary }, { "Holes", holes }, { "Bottom", bottom }, { "Top", top } }); }
public static Dictionary <string, object> PointsOnSurface( Element room, [DefaultArgument("Selection.Select.GetNull()")] List <Element> glazingMaterials, string boundaryLocation = "Center") { if (room == null) { throw new ArgumentNullException(nameof(room)); } var materialIds = new List <Autodesk.Revit.DB.ElementId>(); if (glazingMaterials != null && glazingMaterials.Any()) { materialIds = glazingMaterials.Select(x => x.InternalElement.Id).ToList(); } var bLoc = (Autodesk.Revit.DB.SpatialElementBoundaryLocation)Enum.Parse(typeof(Autodesk.Revit.DB.SpatialElementBoundaryLocation), boundaryLocation); var bOptions = new Autodesk.Revit.DB.SpatialElementBoundaryOptions { SpatialElementBoundaryLocation = bLoc }; var doc = DocumentManager.Instance.CurrentDBDocument; var tolerance = doc.Application.ShortCurveTolerance; var rm = (Autodesk.Revit.DB.SpatialElement)room.InternalElement; var calculator = new Autodesk.Revit.DB.SpatialElementGeometryCalculator(doc, bOptions); var result = calculator.CalculateSpatialElementGeometry(rm); var geo = result.GetGeometry(); var bb = geo.GetBoundingBox(); var height = bb.Max.Z - bb.Min.Z; //var units = doc.GetUnits().GetFormatOptions(Autodesk.Revit.DB.UnitType.UT_Length); //var convertedHeight = Autodesk.Revit.DB.UnitUtils.ConvertFromInternalUnits(height, units.DisplayUnits); var boundaryCurves = rm.GetBoundarySegments(bOptions).First().Select(x => x.GetCurve()).ToList(); var glazingPoints = new List <List <List <Point> > >(); var glazingRatios = new List <double>(); for (var j = 1; j < geo.Faces.Size; j++) // skip 0 as that's the Floor. { var face = geo.Faces.get_Item(j); var bottomEdge = face.GetEdgesAsCurveLoops().First().First(); // first loop is outer boundary, first curve is bottom edge var index = boundaryCurves.FindIndex(x => x.OverlapsWith(bottomEdge)); if (index == -1) { continue; // could be inner face/roof } var gPoints = new List <List <Point> >(); var gAreas = new List <double>(); if (!(face is Autodesk.Revit.DB.PlanarFace)) { glazingPoints[index] = gPoints; continue; // skip non-planar faces } var boundaryFaces = result.GetBoundaryFaceInfo(face); foreach (var bFace in boundaryFaces) { var bElement = doc.GetElement(bFace.SpatialBoundaryElement.HostElementId); if (bElement is Autodesk.Revit.DB.Wall wall) { if (wall.WallType.Kind == Autodesk.Revit.DB.WallKind.Curtain) { var cGrid = wall.CurtainGrid; var panels = cGrid.GetPanelIds().Select(x => doc.GetElement(x)); foreach (var panel in panels) { var mat = panel.GetMaterialIds(false); if (!materialIds.Any() || !materialIds.Intersect(mat).Any()) { continue; } var winPts = new List <Autodesk.Revit.DB.XYZ>(); using (var opt = new Autodesk.Revit.DB.Options()) { opt.IncludeNonVisibleObjects = true; using (var geom = panel.get_Geometry(opt)) { ExtractPtsRecursively(geom, ref winPts); } } var onSurface = new HashSet <Autodesk.Revit.DB.XYZ>(); var onSurfaceUvs = new HashSet <Autodesk.Revit.DB.UV>(); foreach (var pt in winPts) { var intResult = face.Project(pt); if (intResult == null) { continue; } if (onSurface.Add(intResult.XYZPoint)) { onSurfaceUvs.Add(intResult.UVPoint.Negate()); } } if (GetHull(onSurface.ToList(), onSurfaceUvs.ToList(), tolerance, out var hPts, out var hUvs)) { var outerEdges = face.GetEdgesAsCurveLoops().First(); foreach (var edge in outerEdges) { for (var i = 0; i < hPts.Count; i++) { var pt = hPts[i]; if (edge.Distance(pt) >= 0.01) { continue; } var direction = (edge.GetEndPoint(1) - edge.GetEndPoint(0)).Normalize(); var perpendicular = face.ComputeNormal(new Autodesk.Revit.DB.UV(0.5, 0.5)).CrossProduct(direction); var offset = 0.1 * perpendicular; var offsetPt = pt + offset; hPts[i] = offsetPt; } } gAreas.Add(PolygonArea(hUvs)); gPoints.Add(hPts.Select(x => x.ToPoint()).ToList()); } } } var inserts = wall.FindInserts(true, false, true, true).Select(x => doc.GetElement(x)); foreach (var insert in inserts) { if (insert.Category.Id.IntegerValue == Autodesk.Revit.DB.BuiltInCategory.OST_Windows.GetHashCode()) { // (Konrad) We have a Window. var winPts = new List <Autodesk.Revit.DB.XYZ>(); using (var opt = new Autodesk.Revit.DB.Options()) { opt.IncludeNonVisibleObjects = true; using (var geom = insert.get_Geometry(opt)) { ExtractPtsRecursively(geom, ref winPts); } } var onSurface = new HashSet <Autodesk.Revit.DB.XYZ>(); var onSurfaceUvs = new HashSet <Autodesk.Revit.DB.UV>(); foreach (var pt in winPts) { var intResult = face.Project(pt); if (intResult == null) { continue; } if (onSurface.Add(intResult.XYZPoint)) { onSurfaceUvs.Add(intResult.UVPoint.Negate()); } } if (GetHull(onSurface.ToList(), onSurfaceUvs.ToList(), tolerance, out var hPts, out var hUvs)) { var winArea = GetWindowArea(insert); var hullArea = PolygonArea(hUvs); if (hullArea > winArea * 0.5) { var outerEdges = face.GetEdgesAsCurveLoops().First(); foreach (var edge in outerEdges) { for (var i = 0; i < hPts.Count; i++) { var pt = hPts[i]; if (edge.Distance(pt) >= 0.01) { continue; } var direction = (edge.GetEndPoint(1) - edge.GetEndPoint(0)).Normalize(); var perpendicular = face.ComputeNormal(new Autodesk.Revit.DB.UV(0.5, 0.5)).CrossProduct(direction); var offset = 0.03 * perpendicular; var offsetPt = pt + offset; hPts[i] = offsetPt; } } gAreas.Add(PolygonArea(hUvs)); gPoints.Add(hPts.Select(x => x.ToPoint()).ToList()); } } } } } else if (bElement is Autodesk.Revit.DB.RoofBase roof) { var inserts = roof.FindInserts(true, false, true, true).Select(x => doc.GetElement(x)); foreach (var insert in inserts) { if (insert.Category.Id.IntegerValue == Autodesk.Revit.DB.BuiltInCategory.OST_Windows.GetHashCode()) { // (Konrad) We have a Window. var winPts = new List <Autodesk.Revit.DB.XYZ>(); using (var opt = new Autodesk.Revit.DB.Options()) { opt.IncludeNonVisibleObjects = true; using (var geom = insert.get_Geometry(opt)) { ExtractPtsRecursively(geom, ref winPts); } } var onSurface = new HashSet <Autodesk.Revit.DB.XYZ>(); var onSurfaceUvs = new HashSet <Autodesk.Revit.DB.UV>(); foreach (var pt in winPts) { var intResult = face.Project(pt); if (intResult == null) { continue; } if (onSurface.Add(intResult.XYZPoint)) { onSurfaceUvs.Add(intResult.UVPoint.Negate()); } } if (GetHull(onSurface.ToList(), onSurfaceUvs.ToList(), tolerance, out var hPts, out var hUvs)) { var winArea = GetWindowArea(insert); var hullArea = PolygonArea(hUvs); if (hullArea > winArea * 0.25) { gAreas.Add(hullArea); gPoints.Add(hPts.Select(x => x.ToPoint()).ToList()); } } } } } } var curve = face.GetEdgesAsCurveLoops().FirstOrDefault()?.FirstOrDefault(); if (curve == null) { continue; } var faceArea = curve.Length * height; glazingPoints[index] = gPoints; glazingRatios[index] = gAreas.Sum() / faceArea; } return(new Dictionary <string, object> { { "GlazingPoints", glazingPoints }, { "GlazingRatios", glazingRatios } }); }
public static Dictionary <string, object> GlazingInfo(Element room, string boundaryLocation = "Center") { if (room == null) { throw new ArgumentNullException(nameof(room)); } var doc = DocumentManager.Instance.CurrentDBDocument; var bLoc = (Autodesk.Revit.DB.SpatialElementBoundaryLocation)Enum.Parse(typeof(Autodesk.Revit.DB.SpatialElementBoundaryLocation), boundaryLocation); var bOptions = new Autodesk.Revit.DB.SpatialElementBoundaryOptions { SpatialElementBoundaryLocation = bLoc }; var tolerance = doc.Application.ShortCurveTolerance; var e = (Autodesk.Revit.DB.SpatialElement)room.InternalElement; var calculator = new Autodesk.Revit.DB.SpatialElementGeometryCalculator(doc, bOptions); var roomGeo = calculator.CalculateSpatialElementGeometry(e); var geo = roomGeo.GetGeometry(); var bb = geo.GetBoundingBox(); var height = bb.Max.Z - bb.Min.Z; var segments = e.GetBoundarySegments(bOptions); var faces = roomGeo.GetGeometry().Faces; var offset = e.get_Parameter(Autodesk.Revit.DB.BuiltInParameter.ROOM_LOWER_OFFSET).AsDouble(); var boundary = new List <Point>(); var holes = new List <List <Point> >(); var windows = new List <double>(); var walls = new List <List <Element> >(); var foundFaces = new List <Surface>(); for (var i = 0; i < segments.Count; i++) { if (i == 0) // outer boundary { foreach (var bs in segments[i]) { var boundaryCurve = bs.GetCurve().Offset(offset); if (boundaryCurve.Length < 0.01) { continue; // Exclude tiny curves, they don't produce faces. } var face = FindFace(faces, roomGeo, boundaryCurve); if (face == null) { continue; // Couldn't find a matching face. Not good. } GetGlazingInfo(face, doc, roomGeo, tolerance, out var unused, out var glazingAreas, out var boundingWalls); var faceArea = boundaryCurve.Length * height; var glazingArea = glazingAreas.Sum(); var glazingRatio = glazingArea / faceArea; // (Konrad) Number of Boundary points in the list has to match number of Window Parameters. var boundaryPts = GetPoints(boundaryCurve); boundary.AddRange(boundaryPts); windows.AddRange(boundaryPts.Select(x => glazingRatio)); walls.Add(boundingWalls); foundFaces.Add(face.ToProtoType().First()); } continue; } var hole = new List <Point>(); foreach (var bs in segments[i]) { //TODO: Floor Holes need Glazing info processed. var boundaryCurve = bs.GetCurve(); var segmentPts = GetPoints(boundaryCurve); hole.AddRange(segmentPts); windows.AddRange(segmentPts.Select(segmentPt => 0d)); } holes.Add(hole); } return(new Dictionary <string, object> { { "Boundary", boundary }, { "Holes", holes }, { "GlazingRatios", windows }, { "Height", height }, { "Walls", walls }, { "Faces", foundFaces } }); }