def FindRegionEdges(filledRegion): view = filledRegion.Document.GetElement(filledRegion.OwnerViewId) options = Options() options.View = view options.ComputeReferences = True edges = [] for o in filledRegion.get_Geometry(options): edges.append(o.Edges) return edges
def get_geometry_instances(elem): geo_instance = [] geo = elem.get_Geometry(Options()) for g in geo: if g.GetType().Name == 'GeometryInstance': geo_instance.append(g) return geo_instance
def get_faces_from_solid(cls, elem): """Возвращает все поверхсти элемента.""" option = Options() faces = [] geometry = elem.get_Geometry(option) for geometry_intance in geometry: if isinstance(geometry_intance, Solid): faces += list(geometry_intance.Faces) return faces
def RemovePaintFromElement(el): solids = UnwrapElement(el).get_Geometry(Options()) # noqa if solids: for solid in solids: if hasattr(solid, "Faces"): for face in solid.Faces: elID = ElementId(el.Id) doc.RemovePaint(elID, face) if face.HasRegions: regions = face.GetRegions() for regFace in regions: doc.RemovePaint(elID, regFace)
def get_square_from_solid(element): square = 0 volume = 0 solids = element.get_Geometry(Options()) if solids: for solid in solids: volume += solid.Volume if hasattr(solid, 'Faces'): for face in solid.Faces: mat_id = face.MaterialElementId if mat_id.IntegerValue == -1: square += face.Area return square, volume
def set_value_at_point(collector, param_name): rooms = [] for r in collector: solids = r.get_Geometry(Options()) for solid in solids: point = solid.ComputeCentroid() room = doc.GetRoomAtPoint(point) if room: rooms.append(room) room_number = room.get_Parameter( BuiltInParameter.ROOM_NUMBER).AsString() set_value_to_parameter(r, param_name, room_number) return rooms
def RemovePaintFromElement(el): solids = UnwrapElement(el).get_Geometry(Options()) # noqa if solids: painted_face = [] for solid in solids: if hasattr(solid, "Faces"): for face in solid.Faces: elID = ElementId(el.Id) if doc.IsPainted(elID, face): painted_face.append(face) if face.HasRegions: for regFace in face.GetRegions(): if doc.IsPainted(elID, regFace): painted_face.append(regFace) return painted_face
def get_square_from_part(part_list, document): if part_list: square = 0 for item_id in part_list: stair_run = document.GetElement(item_id) geometry = stair_run.get_Geometry(Options()) if geometry: for geo in geometry: if geo.GetType().Name == 'Solid': for face in geo.Faces: square += get_square_from_face(face) if geo.GetType( ).Name == 'GeometryInstance' and square == 0: instance_geo = geo.GetInstanceGeometry() for solid in instance_geo: for face in solid.Faces: square += get_square_from_face(face) return square
class RB_Space: all_space = [] view_option = Options() all_spaces_numbers = None all_spaces_numbers_set = None def __init__(self, space): self._geometry = None self.all_space.append(self) self.space = space self.radiators = self.all_spaces_numbers.count(self.space.Number) self.all_spaces_numbers_set.discard(self.space.Number) @property def geometry(self): if self._geometry is None: self._geometry = list( self.space.Geometry[self.view_option].GetEnumerator()) return self._geometry
# print("ft cache: ", coord_tuple) return str(coord_tuple) stopwatch = Stopwatch() stopwatch.Start() ignored_durchbruch_ids = [ # "A001G01", ] # general revitapi options and constants ft_mm = 304.8 up = XYZ(0, 0, 1) non_struct = Structure.StructuralType.NonStructural geo_opt = Options() rvt_link_opt = RevitLinkOptions(False) selection = [doc.GetElement(elId) for elId in uidoc.Selection.GetElementIds()] # create level overviews lvl_elevations, next_lvl_elevations = get_lvl_dicts() raw_lvl_elevations, raw_next_lvl_elevations = get_lvl_dicts(building_story=0) # retrieve model elements local_gen = Fec(doc).OfCategory( Bic.OST_GenericModel).WhereElementIsNotElementType().ToElements() local_walls = Fec(doc).OfCategory( Bic.OST_Walls).WhereElementIsNotElementType().ToElements() fam_symbols = Fec(doc).OfClass(FamilySymbol).ToElements()
def getCoordinates(pbp, document): option = Options() option.ComputeReferences = True #PBP location as per revit center return pbp.get_BoundingBox(document.ActiveView).Min
import clr clr.AddReference("RevitAPI") from Autodesk.Revit.DB import FilteredElementCollector, ElementIntersectsSolidFilter, Options, FamilyInstance, \ ElementIntersectsElementFilter, Ceiling from Autodesk.Revit.DB.Mechanical import Duct el = UnwrapElement(IN[0]) doc = el.Document opt = Options() solid = el.get_Geometry(opt) el_filter = ElementIntersectsElementFilter(el) # solid_filter = ElementIntersectsSolidFilter(solid) cats = [] cats.append(Duct) cats.append(FamilyInstance) cats.append(Ceiling) col = [] for c in cats: intersectingInstances = FilteredElementCollector(doc).OfClass(c). \ WherePasses(el_filter) el_list = list(intersectingInstances) if el_list: col.append(el_list) OUT = col
class Captures(object): opt_1 = Options() opt_1.DetailLevel = ViewDetailLevel.Medium opt_1.IncludeNonVisibleObjects = True opt_2 = Options() opt_2.DetailLevel = ViewDetailLevel.Medium rebar_found_host = List[ElementId]() def __init__(self, doc, parent=None, transforms=None, uidoc=None): """ Начало параметризации. Параметрами передаются doc 1. Получить арматуру в текущем файле. 2. Распределить арматуру по типам: - Системная - IFC 3. Получить все хосты формообразующие текущего докоумента 4. Найти родителей арматуры . Найти либ документы . По разнному обработать арматуру на поиск хоста { doc: transform } """ self.transforms = transforms self.parent = parent self.doc = doc self.uidoc = uidoc echo("Начинаем работать с {}".format(self)) self.rebar_system, self.rebar_ifc = self.find_all_rebar() echo("Получили арматурные стержни и разделили на IFC {} штук и системную {} штук".format(len(self.rebar_ifc), len(self.rebar_system))) self.hosts = self.get_parts_and_floor() echo("Получили формы части и плиты {}".format(len(self.hosts))) self.find_rebar_capture_system(self.rebar_system) self.find_rebar_capture_ifc(self.rebar_ifc) echo("Отработал поиск хостов") # self.lib_documents = self.get_instance_document() # self.parametrizetion_lib() def __repr__(self): if self.doc: return self.doc.Title return str(self.doc) def get_instance_document(self): """ Находим все экзмепляры связей. Запихиваем в documents с их трансформатцией Сколько трансформаций. Столько и либов. """ documents = {} els = FilteredElementCollector(self.doc).\ OfClass(RevitLinkInstance).ToElements() for i in els: l_doc = i.GetLinkDocument() trans = i.GetTotalTransform() if l_doc not in documents.keys(): documents[l_doc] = set() documents[l_doc].add(trans) return documents def parametrizetion_lib(self): for key, i in self.lib_documents.items(): if key: self.__class__(key, parent=self, transforms=i) def find_all_rebar(self): """ Поиск арматуры. Ищем всю арматуру и разделяем ее на IFC и Системную """ system_rebar = set() ifc_rebar = set() rebars = FilteredElementCollector(self.doc).\ OfCategory(BuiltInCategory.OST_Rebar).\ WhereElementIsNotElementType().ToElements() for i in rebars: pog_met = i.LookupParameter("Рзм.ПогМетрыВкл") if i.LookupParameter("Рзм.ПогМетрыВкл") else self.doc.GetElement(i.GetTypeId()).LookupParameter("Рзм.ПогМетрыВкл") if pog_met and not pog_met.AsInteger(): if isinstance(i, FamilyInstance): ifc_rebar.add(i) else: system_rebar.add(i) return system_rebar, ifc_rebar def get_parts_and_floor(self): """ Получаем все возможные формообразующие в текущем документе. """ els = FilteredElementCollector(self.doc).\ WhereElementIsNotElementType().\ OfCategory(BuiltInCategory.OST_Floors).ToElementIds() sel = List[ElementId]() res = [] for i in els: parts = PartUtils.GetAssociatedParts(self.doc, i, True, True) fl = self.doc.GetElement(i) fl_par = fl.LookupParameter("Номер захватки") if parts.Count: fl_par.Set("Не учитывать") fl_gr = fl.LookupParameter("Орг.ГруппаВедомостьРасходаБетона").AsString() for j in parts: pt = self.doc.GetElement(j) if pt.LookupParameter("Номер захватки").AsString(): sel.Add(j) res.append(pt) pt.LookupParameter("Орг.ГруппаВедомостьРасходаБетона").Set(fl_gr) else: if fl_par.AsString() == "Не учитывать": fl_par.Set("") if fl_par.AsString(): res.append(fl) sel.Add(i) self.uidoc.Selection.SetElementIds(sel) return sorted(res, key=lambda x: x.LookupParameter("Номер захватки").AsString()) def select(self, elements): elements = List[ElementId]([i.Id for i in elements]) __revit__.ActiveUIDocument.Selection.SetElementIds(elements) def find_rebar_capture_system(self, elements): """ Находим захватки системной арматуры. """ # hosts = List[ElementId]([i.Id for i in self.hosts]) elements = List[ElementId]([i.Id for i in elements]) for host in self.hosts: elements_fec = FilteredElementCollector(self.doc, elements) bb = host.Geometry[self.opt_1].GetBoundingBox() filtered = BoundingBoxIntersectsFilter(Outline(bb.Min, bb.Max)) rebars = elements_fec.WherePasses(filtered).ToElements() for rebar in rebars: host_is_found = False for host_solid in self.get_solids(host, opt=self.opt_2): if host_is_found: break if isinstance(host_solid, Solid): cur_line = next(iter(rebar.Geometry[self.opt_1])) if host_solid.\ IntersectWithCurve(cur_line, None).\ SegmentCount: rebar.LookupParameter("Номер захватки").\ Set(host.LookupParameter("Номер захватки").AsString()) host_is_found = True # def find_rebar_host_system(self, elements, parent=None, transforms=None): # """ # Находим хосты системной арматуры. # """ # rebar_without_hosts = set() # for el in elements: # host_is_found = False # cur_line = next(iter(el.Geometry[self.opt_1])) # transform_host = {} # for host in self.hosts: # if host_is_found: # break # for host_solid in self.get_solids(host, opt=self.opt_2): # if isinstance(host_solid, Solid): # if transforms is not None: # for transform in transforms: # trans_line = cur_line.CreateTransformed(transform) # if host_solid.IntersectWithCurve(trans_line, None).SegmentCount: # # echo("У системной арматуры {} найдена захватка в родителе {}".format(el.Id, host.Id)) # transform_host[transform] = host.Id # else: # # echo("Ищем хост") # if host_solid.IntersectWithCurve(cur_line, None).SegmentCount: # # echo("У системной арматуры {} найден захватка {}".format(el.Id, host.Id)) # el.LookupParameter("Номер захватки").Set(host.LookupParameter("Номер захватки").AsString()) # host_is_found = True # if not host_is_found: # rebar_without_hosts.add(el) # echo("Для системной арматуры {} не найдена захватка".format(el.Id)) # if self.parent and rebar_without_hosts: # echo("Ищем захватку в родителе") # self.parent.find_rebar_host_system(rebar_without_hosts, transforms=self.transforms) def find_rebar_capture_ifc(self, elements): elements = List[ElementId]([i.Id for i in elements]) for host in self.hosts: elements_fec = FilteredElementCollector(self.doc, elements) bb = host.Geometry[self.opt_1].GetBoundingBox() filtered = BoundingBoxIntersectsFilter(Outline(bb.Min, bb.Max)) rebars = elements_fec.WherePasses(filtered).ToElements() for rebar in rebars: all_reb_solids = self.get_solids(rebar) host_is_found = False for rebar_solid in all_reb_solids: if host_is_found: break for host_solid in self.get_solids(host): if host_is_found: break try: union_solid = BooleanOperationsUtils.\ ExecuteBooleanOperation( rebar_solid, host_solid, BooleanOperationsType.Union) sum_area = rebar_solid.SurfaceArea +\ host_solid.SurfaceArea -\ union_solid.SurfaceArea except: sum_area = 1 if sum_area > 0.0001: host_is_found = True rebar.LookupParameter("Номер захватки").\ Set(host.LookupParameter("Номер захватки").\ AsString()) def find_rebar_host_ifc(self, elements): for el in elements: all_reb_solids = self.get_solids(el) host_is_found = False if all_reb_solids: for first_solid in all_reb_solids: if host_is_found: break for host in self.hosts: if host_is_found: break sum_area = 0 for host_solid in self.get_solids(host): if host_is_found: break union_solid = BooleanOperationsUtils.ExecuteBooleanOperation(first_solid, host_solid, BooleanOperationsType.Union) sum_area += ((first_solid.SurfaceArea + host_solid.SurfaceArea) - union_solid.SurfaceArea) if sum_area > 0.0001: host_is_found = True el.LookupParameter("Номер захватки").Set(host.LookupParameter("Номер захватки").AsString()) if not host_is_found: pass echo("Для IFC арматуры {} не найден host".format(el.Id)) else: # pass echo("Не найдено геометрии для IFC {}".format(self)) def get_solids(self, el, opt=None): opt = opt if opt is not None else self.opt_1 res = [] for geom in el.Geometry[opt]: if isinstance(geom, GeometryInstance): res += [i for i in geom.GetInstanceGeometry() if isinstance(i, Solid) and i.Volume > 0] elif isinstance(geom, Solid) and geom.Volume > 0: res.append(geom) return res
class Precast_geometry(object): "Примесь для поиска солидов." option_coarse = Options() option_coarse.DetailLevel = ViewDetailLevel.Coarse option_medium = Options() option_medium.DetailLevel = ViewDetailLevel.Medium option_fine = Options() option_fine.DetailLevel = ViewDetailLevel.Fine _default_option = option_medium def __init__(self): self._solids = None self._union_solid = None super(Precast_geometry, self).__init__() def get_solids(self, solids, res, transform=None): "Записываем солиды и записываем в res рекурсивно." if solids: for i in solids: if isinstance(i, Solid): res.append(Precast_solid(i, self.doc)) if isinstance(i, GeometryInstance): self.get_solids(i.GetInstanceGeometry(), res) @property def solids(self): "Все солиды элемента." if not hasattr(self, "_solids") or self._solids is None: self._solids = [] solids = self.element.Geometry[self._default_option] self.get_solids(solids, self._solids) return self._solids @property def real_solids(self): "Все солиды элемента." if not hasattr(self, "_real_solids"): self._real_solids = [] solids = self.element.Geometry[self.option_fine] self.get_solids(solids, self._real_solids) return self._real_solids @property def union_solid(self): "Объединение всех солидов." if not hasattr(self, "_union_solid") or self._union_solid is None: self._union_solid = None if self.solids: for i in self.solids: if self._union_solid is None: self._union_solid = i.element else: self._union_solid = BooleanOperationsUtils.ExecuteBooleanOperation( self._union_solid, i.element, BooleanOperationsType.Union) return self._union_solid def join_elements(self, elements_1, elements_2): "Присоединяет геометрию элементов" result = set() rebar_cat = Category.GetCategory(self.doc, BuiltInCategory.OST_Rebar).Name elements_1 = [ i for i in elements_1 if i.element.Category.Name != rebar_cat ] elements_2 = [ i for i in elements_2 if i.element.Category.Name != rebar_cat ] for element_1 in elements_1: for element_2 in elements_2: try: res = BooleanOperationsUtils.ExecuteBooleanOperation( element_2.union_solid, element_1.union_solid, BooleanOperationsType.Difference) if res.Volume < element_2.union_solid.Volume: result.add(element_1) try: if not JoinGeometryUtils.AreElementsJoined( self.doc, element_2.element, element_1.element): JoinGeometryUtils.JoinGeometry( self.doc, element_2.element, element_1.element) if not JoinGeometryUtils.IsCuttingElementInJoin( self.doc, element_2.element, element_1.element): JoinGeometryUtils.SwitchJoinOrder( self.doc, element_2.element, element_1.element) except: # echo("Ошибка в объединении {} с {}".format(element_1, element_2)) pass except InvalidOperationException: result.add(element_1) return result @property def center_point(self): if not hasattr(self, "_center_point"): bb = self.element.Geometry[self._default_option].GetBoundingBox() delta = bb.Max - bb.Min delta = delta / 2 self._center_point = bb.Min + delta return self._center_point @property def height(self): if not hasattr(self, "_height"): bb = self.element.Geometry[self._default_option].GetBoundingBox() delta = bb.Max - bb.Min self._height = delta.GetLength() return self._height @property def vect_abscis(self): "Ветор X." if not hasattr(self, "_vect_abscis"): self._vect_abscis = self.element.FacingOrientation return self._vect_abscis @property def vect_ordinat(self): "Ветор Y." if not hasattr(self, "_vect_ordinat"): self._vect_ordinat = self.element.HandOrientation return self._vect_ordinat @property def vect_applicat(self): "Ветор Z." if not hasattr(self, "_vect_applicat"): self._vect_applicat = XYZ(0, 0, 1) return self._vect_applicat @staticmethod def project_on_plane(point, origin=None, normal=None, plane=None): "Проекция точки на плоскость." if plane is None: plane = Plane.CreateByNormalAndOrigin(normal, origin) normal = plane.Normal * plane.Project(point)[1] return point - normal @classmethod def project_line_on_plane(cls, line, origin=None, normal=None, plane=None): p1 = line.GetEndPoint(0) p1 = cls.project_on_plane(p1, origin=origin, normal=normal, plane=plane) p2 = line.GetEndPoint(1) p2 = cls.project_on_plane(p2, origin=origin, normal=normal, plane=plane) # echo(p1.IsAlmostEqualTo(p2)) if not p1.IsAlmostEqualTo(p2): try: return Line.CreateBound(p1, p2) except: pass
if old_Mat == doc.GetElement(face.MaterialElementId).Name: doc.Paint(ElementId(elem.Id), face, GetMaterail(new_Mat).Id) return "Готово!" else: return "Нет - {}".format(old_Mat) sel = IN[1] # noqa old_Mat = IN[2] # noqa new_Mat = IN[3] # noqa all_mat = list() TransactionManager.Instance.EnsureInTransaction(doc) if isinstance(sel, list): for s in sel: solid_list = UnwrapElement(s).get_Geometry(Options()) # noqa for solid in solid_list: if hasattr(solid, "Faces"): for face in solid.Faces: all_mat.append(doc.GetElement(face.MaterialElementId).Name) AddPaint(old_Mat, new_Mat, face, s) if face.HasRegions: regions = face.GetRegions() for regFace in regions: all_mat.append( doc.GetElement(regFace.MaterialElementId).Name) AddPaint(old_Mat, new_Mat, regFace, s) TransactionManager.Instance.TransactionTaskDone() OUT = all_mat
# -*- coding: utf-8 -*- import clr clr.AddReference("RevitAPI") from Autodesk.Revit.DB import FilteredElementCollector, Options, BuiltInCategory, XYZ, UnitUtils, DisplayUnitType clr.AddReference("RevitNodes") from Revit.GeometryConversion import RevitToProtoCurve clr.AddReference("RevitServices") from RevitServices.Persistence import DocumentManager from RevitServices.Transactions import TransactionManager doc = DocumentManager.Instance.CurrentDBDocument room_col = FilteredElementCollector(doc).OfCategory( BuiltInCategory.OST_Rooms).ToElements() opt = Options() opt.View = doc.ActiveView opt.IncludeNonVisibleObjects = True lines = [] for r in room_col: for g in r.get_Geometry(opt): if 'Line' in g.ToString(): vector = (g.GetEndPoint(1) - g.GetEndPoint(0)).Normalize() degrees = UnitUtils.ConvertFromInternalUnits(vector.AngleTo(XYZ.BasisX), \ DisplayUnitType.DUT_DECIMAL_DEGREES) if round(degrees) == 135: lines.append(RevitToProtoCurve.ToProtoType(g)) OUT = room_col, lines
def convertRoomsToHBZones(rooms, boundaryLocation=1): """Convert rooms to honeybee zones. This script will only work from inside Dynamo nodes. for a similar script forRrevit check this link for more details: https://github.com/jeremytammik/SpatialElementGeometryCalculator/ blob/master/SpatialElementGeometryCalculator/Command.cs """ rooms = tuple(_getInternalElements(rooms)) if not rooms: return [] # create a spatial element calculator to calculate room data doc = rooms[0].Document options = SpatialElementBoundaryOptions() options.SpatialElementBoundaryLocation = getBoundaryLocation( boundaryLocation) calculator = SpatialElementGeometryCalculator(doc, options) opt = Options() _ids = [] _zones = range(len(rooms)) _surfaces = {} # collect hbSurfaces so I can set adjucent surfaces for zoneCount, room in enumerate(rooms): # initiate zone based on room id _zone = HBZone(room.Id) # assert False, room.Id elementsData = calculator.CalculateSpatialElementGeometry(room) _roomGeo = elementsData.GetGeometry() # This can be the same as finish wall or in the center of the wall roomDSFaces = tuple(face.ToProtoType()[0] for face in _roomGeo.Faces) assert _roomGeo.Faces.Size == len(roomDSFaces), \ "Number of rooms elements ({}) doesn't match number of faces ({}).\n" \ "Make sure the Room is bounded.".format(_roomGeo.Faces.Size, len(roomDSFaces)) for count, face in enumerate(_roomGeo.Faces): # base face is useful to project the openings to room boundary _baseFace = roomDSFaces[count] # Revit is strange! if two roofs have a shared wall then it will be # duplicated! By checking the values inside the _collector _collector = [] _boundaryFaces = elementsData.GetBoundaryFaceInfo(face) if len(_boundaryFaces) == 0: # initiate honeybee surface _ver = tuple(v.PointGeometry for v in _baseFace.Vertices) _hbSurface = HBSurface("%s:%s" % (_zone.name, createUUID()), _ver) _zone.addSurface(_hbSurface) continue for boundaryFace in _boundaryFaces: # boundaryFace is from type SpatialElementBoundarySubface # get the element (Wall, Roof, etc) boundaryElement = doc.GetElement( boundaryFace.SpatialBoundaryElement.HostElementId) # initiate honeybee surface _ver = tuple(v.PointGeometry for v in _baseFace.Vertices) if _ver in _collector: continue _hbSurface = HBSurface( "%s:%s" % (_zone.name, boundaryElement.Id), _ver) _collector.append(_ver) if boundaryElement.Id not in _surfaces: _surfaces[boundaryElement.Id] = _hbSurface else: # TODO: set adjacent surface pass # Take care of curtain wall systems # I'm not sure how this will work with custom Curtain Wall if getParameter(boundaryElement, 'Family') == 'Curtain Wall': _elementIds, _coordinates = \ extractPanelsVertices(boundaryElement, _baseFace, opt) for count, coordinate in enumerate(_coordinates): if not coordinate: print "{} has an opening with less than " \ "two coordinates. It has been removed!" \ .format(childElements[count].Id) continue # create honeybee surface - use element id as the name _hbfenSurface = HBFenSurface(_elementIds[count], coordinate) # add fenestration surface to base honeybee surface _hbSurface.addFenestrationSurface(_hbfenSurface) else: # check if there is any child elements childElements = getChildElemenets(boundaryElement) if childElements: _coordinates = exctractGlazingVertices( boundaryElement, _baseFace, opt) for count, coordinate in enumerate(_coordinates): if not coordinate: print "{} has an opening with less than " \ "two coordinates. It has been removed!" \ .format(childElements[count].Id) continue # create honeybee surface - use element id as the name _hbfenSurface = HBFenSurface( childElements[count].Id, coordinate) # add fenestration surface to base honeybee surface _hbSurface.addFenestrationSurface(_hbfenSurface) # add hbsurface to honeybee zone _zone.addSurface(_hbSurface) boundaryElement.Dispose() _zones[zoneCount] = _zone # clean up! elementsData.Dispose() calculator.Dispose() return _zones
if param: if param.CanAssignFormula: val = UnitUtils.ConvertFromInternalUnits(value, param.DisplayUnitType) f_manager.SetFormula(param, str(val)) return '{} - {}'.format(param_name, val) else: return 'Not OK' sel = UnwrapElement(IN[1]) # noqa faces = [] square = 0 vol1 = 0 solids = sel.get_Geometry(Options()) if solids: for solid in solids: a = RevitToProtoSolid.ToProtoType(solid) vol1 += solid.Volume if hasattr(solid, 'Faces'): for face in solid.Faces: mat_id = face.MaterialElementId if mat_id.IntegerValue == -1: square += face.Area vol2 = GetVolumeFromBBox(sel) TransactionManager.Instance.EnsureInTransaction(doc) sq = SetParameterByName(square, 'ARH_sr')
currentChoice = [] for i in get_selected_elements(doc): currentChoice.append(Reference(i)) result = 'Retry' while result == 'Retry': pipFilter = PipeandFittingsSelectionFilter() choices = uidoc.Selection try: pipeRef = choices.PickObjects(ObjectType.Element, pipFilter, "Pick Pipe", currentChoice) currentChoice = pipeRef overallLength = 0.00 for i in pipeRef: pipe = doc.GetElement(i.ElementId) # Pipe try: overallLength += pipe.Location.Curve.Length except: overallLength += pipe.GetOriginalGeometry( Options()).GetBoundingBox().Max.DistanceTo( pipe.GetOriginalGeometry( Options()).GetBoundingBox().Min) result = str( TaskDialog.Show( "Measure", "Overall Length " + str(FeettoInch(overallLength)) + " feet", TaskDialogCommonButtons.Retry)) uidoc.RefreshActiveView() except: result = "Cancel"
except: results = 0 return results def get_geometys(element): if element.get_Geometry(geo_options): for geometry_inst in element.get_Geometry(geo_options): if geometry_inst.GetType() == Autodesk.Revit.DB.GeometryInstance: for geometry in geometry_inst.SymbolGeometry: if geometry.GetType() == Autodesk.Revit.DB.Solid and Math.Round(geometry.Volume,3) != 0: return geometry else: if geometry_inst.GetType() == Autodesk.Revit.DB.Solid and Math.Round(geometry_inst.Volume,3) != 0: return geometry_inst #endregion #region параметры для объединения opt = Options() items1 = flatten_List(elements) catIdlist = [id_name[0] for id_name in cats_ids_names] ids = [i.Id for i in items1] i_list_ids = List[ElementId](ids) inter = [] aliter = [] alliter = [] geo_options = Options() geo_options.ComputeReferences = False geo_options.IncludeNonVisibleObjects = False # for i in items1: # ids.append(i.Id) #endregion #region main итерации, что-то можно заменить на генераторы списков для TransactionManager.Instance.EnsureInTransaction(doc)
class RB_Radiator: all_spaces = set() view_option = Options() all_radiators = [] csv_data = None guids = None message = [] def __init__(self, radiator): self.all_radiators.append(self) self.radiator = radiator self._space = None self.info = False self._random_line = None self._geom = None if self.space: self.space_number = None self.symbol = None self.length = None self.diameter = None self.producer = None self.description = None self.get_radiator_info() else: self.__class__.message.append( "Для конвектора с id {} не найдено пространство в таблице". format(self.radiator.Id)) def get_radiator_info(self): for i in self.csv_data: if to_str(i[1]).lower().strip() == to_str( self.space.space.Number).lower().strip(): self.riser = i[0] self.space_number = i[1] self.symbol = to_str(i[2]) try: self.length = float(to_str(i[3]).replace(",", ".")) / 0.3048 self.diameter = float(to_str(i[4]).replace( ",", ".")) / 0.3048 / 1000 except ValueError: self.__class__.message.append( "Для конвектора с id {} в пространстве {} не заданы длина или диаметр \n" .format(self.radiator.Id, self.space_number)) self.length = float() self.diameter = float() self.producer = to_str(i[5]) self.description = to_str(i[6]) try: # echo(i[7]) self.clap = float(to_str(i[7]).replace(",", ".")) except ValueError: self.__class__.message.append( "Для конвектора с id {} в пространстве {} не найдены настройки клапана \n" .format(self.radiator.Id, self.space_number)) self.clap = float(0) self.info = True break # else: # self.__class__.message += "Для конвектора с id {} не найдены настройки в таблице \n".format(self.radiator.Id) if self.info: self.csv_data.remove(i) @property def space(self): if self._space is None: for space in self.all_spaces: if self._space: break for space_geometry in space.geometry: # echo("Ищем радиатор через линию") if self._space: break l_c = 0 for i in self.random_line: l_c += 1 res = space_geometry.IntersectWithCurve(i, None) if res.SegmentCount: self._space = space # self.__class__.message.append("Найдено через линии {} \n".format(l_c)) break # else: # echo("Все плохо") # for cur_geometry in self.geometry: # sum_area = 0 # if self._space: # break # union_solid = BooleanOperationsUtils.ExecuteBooleanOperation(cur_geometry, space_geometry, BooleanOperationsType.Union) # sum_area += ((cur_geometry.SurfaceArea + space_geometry.SurfaceArea) - union_solid.SurfaceArea) # if sum_area > 0.0001: # self._space = space # echo("Найдено через объем") # break # else: # echo("Не найдено") if self._space: self._space.radiators -= 1 return self._space @property def geometry(self): if self._geom is None: geom = list( list(self.radiator.Geometry[self.view_option].GetEnumerator()) [0].GetInstanceGeometry().GetEnumerator()) self._geom = filter( lambda el: isinstance(el, Solid) and el.Volume > 0, geom) return self._geom @property def random_line(self): if self._random_line is None: self._random_line = set() tt = 0 for g in self.geometry: if tt > 10: break for i_c in range(g.Edges.Size): if tt > 10: break tt += 1 i = g.Edges.Item[i_c].AsCurve() self._random_line.add(i) return self._random_line def set_parameter(self, parameter, value): p = self.radiator.get_Parameter(self.guids[parameter]) if p: if not p.IsReadOnly: p.Set(value) else: self.__class__.message.append( "Параметр {} заблокирован у элемента с id {}".format( parameter, self.radiator.Id)) else: self.__class__.message.append( "Параметр {} не найден у элемента с id {}".format( parameter, self.radiator.Id)) def set_parameters(self): if self.info: self.set_parameter("BS_Изготовитель", self.producer) self.set_parameter("BS_Наименование", self.description) self.set_parameter("MEP_Габаритная длина", self.length) self.set_parameter("BS_Маркировка", self.symbol) self.set_parameter("MEP_Стояк_номер", self.riser) self.set_parameter("OV_Номер пространства", self.space_number) self.set_parameter("MEP_Диаметр 1", self.diameter) self.set_parameter("OV_Настройка клапана", self.clap)
clr.AddReference("RevitServices") from RevitServices.Persistence import DocumentManager from RevitServices.Transactions import TransactionManager import Revit clr.ImportExtensions(Revit.GeometryConversion) doc = DocumentManager.Instance.CurrentDBDocument uiapp = DocumentManager.Instance.CurrentUIApplication app = uiapp.Application element = UnwrapElement(IN[1]) # noqa opt = Options() opt.ComputeReferences = True opt.IncludeNonVisibleObjects = True opt.View = doc.ActiveView element_type = doc.GetElement(element.GetTypeId()) geo = element_type.get_Geometry(opt) geometry_instance = [ g for g in geo if g.GetType().Name == 'Solid' and g.Volume > 0 ][0] new_list = [] edges = geometry_instance.Edges for e in edges: curve = e.AsCurve()
class Line_by_room(IExternalEventHandler): """Линии в комнате по примыкающим стенам """ __all_walls = {} __wall_levels = {} view_option = Options() intersect_option_inside = SolidCurveIntersectionOptions() intersect_option_outside = SolidCurveIntersectionOptions() intersect_option_outside.ResultType = SolidCurveIntersectionMode.CurveSegmentsOutside __graphic_syles = {} offset_length = to_feet(100) tollerance = to_feet(25) @property def graphic_syles(self): """Графические стили проекта """ if not self.__graphic_syles: els = FilteredElementCollector(doc).OfClass( GraphicsStyle).ToElements() els = {el.Name: el for el in els} self.__graphic_syles = els return self.__graphic_syles @property def walls(self): """Получаем стены Сейчас берем все стены в проекте. Нужно бы придумать как брать стены которые рядышком. """ if not self.__all_walls: walls = {} for i in FilteredElementCollector( doc, curview.Id).OfClass(Wall).ToElements(): walls.setdefault(i.Name, set()) walls[i.Name].add(i) self.__all_walls = walls return self.__all_walls @property def wall_levels(self): """Уровни стен Считаем уровень стен через поиск центра тела После этого берем оттуда координату Z. """ if not self.__wall_levels: for i in self.walls.keys(): self.__wall_levels.setdefault(i, 0) e = next(iter(self.walls[i])) e = next(e.Geometry[ self.view_option].GetEnumerator()).ComputeCentroid().Z self.__wall_levels[i] = e return self.__wall_levels def __init__(self, rooms): """Начинаем работу """ self.room_lines = [] for room in rooms: if isinstance(room, Room): self.room_faces = self.get_element_faces(room) intersect_walls = self.get_intersect_wall(room) intersect_walls = { i: k for i, k in intersect_walls.items() if k } offset = 0 for type_name, lines in intersect_walls.items(): offset += 1 lines = self.line_trimming(lines) lines = self.create_rings(lines) lines = self.add_offset(lines, offset) self.room_lines.append(intersect_walls) wall_names = set() for room in self.room_lines: for i in room.keys(): wall_names.add(i) FORM.Start(len(wall_names) + 2) pp = 1 self.form_val = {} for k in wall_names: cur = FORM.GetLines(pp).add_textbox(k, '') cur.Height = 24 FORM.GetLines(pp).add_label("Смещение для {}".format(k)) self.form_val.setdefault(k, cur) pp += 1 but_create = FORM.GetLines(pp).add_button('Выполнить') but_cancel = FORM.GetLines(pp + 1).add_button('Отмена') exEvent = ExternalEvent.Create(self) but_cancel.AddFunction(FORM.Close) but_create.AddFunction(self.start) FORM.calculate_size() FORM.Create(exEvent) def start(self): FORM.exEvent.Raise() def Execute(self, app): try: self.form_val = { i: to_feet(int(self.form_val[i].GetValue())) for i in self.form_val.keys() if self.form_val[i].GetValue().isdigit() } with Transaction(doc, 'Рисуем линии') as t: t.Start() for room in self.room_lines: # echo(room) for type_name, lines in room.items(): if type_name in self.form_val.keys(): lines = self.add_offset(lines, self.form_val[type_name]) # echo(self.get_graphic_styles(type_name)) self.print_line_by_face( lines, self.get_graphic_styles(type_name), type_name) else: message( 'Не задан отступ для типоразмера {} линия создана не будте' .format(type_name)) t.Commit() except: echo(sys.exc_info()[1]) FORM.Close() def GetName(self): return 'Рисуем линии отделки' def line_trimming(self, lines): """Обрезка линий, которые выступают друг за друга формируем линии путем попытки пересечения их. Если линии пересекается с другими два раза два пересечения и есть точки этой линии если линия пересекается один раз. То ближняя точка заменяется той, которая пересеклась если линия не пересекается - оставляем без изменений """ new_lines = [] for line_1 in lines: new_points = list() p1 = line_1.GetEndPoint(0) p2 = line_1.GetEndPoint(1) for line_2 in lines: intersect_result = StrongBox[IntersectionResultArray]() intersect_result_text = line_1.Intersect( line_2, intersect_result) intersect_result = intersect_result.Value if intersect_result_text == SetComparisonResult.Overlap and intersect_result: for i in intersect_result: new_points.append(i.XYZPoint) if len(new_points) == 2: new_lines.append(Line.CreateBound(new_points[0], new_points[1])) elif len(new_points) == 1: if p1.DistanceTo(new_points[0]) > p2.DistanceTo(new_points[0]): new_lines.append(Line.CreateBound(p1, new_points[0])) else: new_lines.append(Line.CreateBound(p2, new_points[0])) else: new_lines.append(line_1) return new_lines def add_offset(self, lines, offset): """Добавляем отступ линии """ new_lines = [] for line in lines: points = [line.GetEndPoint(0), line.GetEndPoint(1)] for point_pos in range(0, 2): point = points[point_pos] faces = set() for face in self.room_faces: plane = face.GetSurface() project_point = plane.Project(point) # echo(project_point) if project_point: if project_point[1] < self.tollerance: faces.add(face) normal_sum = XYZ(0, 0, 0) for face in faces: normal_sum += face.ComputeNormal(UV()) if abs(normal_sum.X) > 0.0001: dev_x = abs(normal_sum.X) else: dev_x = 1 if abs(normal_sum.Y) > 0.0001: dev_y = abs(normal_sum.Y) else: dev_y = 1 normal_sum = XYZ(normal_sum.X / dev_x, normal_sum.Y / dev_y, 0) point -= normal_sum * offset points[point_pos] = point new_lines.append(Line.CreateBound(points[0], points[1])) return new_lines def have_pair(self, point, lines): count = 0 for line in lines: p1 = line.GetEndPoint(0) p1 = line.GetEndPoint(1) def get_element_faces(self, elem): geom = elem.Geometry[self.view_option] faces = [] for i in geom: faces += list(i.Faces) return faces def get_graphic_styles(self, type_name): """Получаем графический стиль исходя из имени типоразмера стены """ for i in self.graphic_syles.keys(): if i in type_name and i != '0': return self.graphic_syles[i] def get_intersect_wall(self, room): """Получаем конаты и находим все стены которые с ними пересекаются потом получаем общие грани. get_common_edges возвращает линии если общие линии найдены - объединяем их рекурсивно. необходимо создавать изначально массив good_lines т.к. concate_lines ничего не возвращает. в good_lines запишутся все линии, которые нам необходимы добавляем в словарь walls все линии с ключем = типоразмеру стены. """ walls = {} for wall_name, cur_walls in self.walls.items(): wall_solids, room_solid = self.get_wall_intersect(room, cur_walls) lines = self.get_common_edges(room_solid, wall_solids) if lines: good_lines = [] self.concate_lines(lines, good_lines=good_lines) lines = good_lines walls.setdefault(wall_name, lines) return walls def concate_lines(self, lines, good_lines=None, depth=0): """Объеденяет линии рекрсивно. в good_line Необходимо передавать массив. В него как раз будет записываться уже объедененные линии Как вариант найти как вернуть good_lines. Пока что не заморачивался """ if lines: line = lines.pop() new_line = None p1 = line.GetEndPoint(0) p2 = line.GetEndPoint(1) unbound_line = line.Clone() unbound_line.MakeUnbound() chean = [] for cur_line in lines: intersection_result_type = unbound_line.Intersect(cur_line) if intersection_result_type == SetComparisonResult.Superset and self.common_end_points( cur_line, line): chean.append(cur_line) if chean: for i in chean: lines.remove(i) new_line = self.create_longest_lines(chean + [line]) lines.append(new_line) else: good_lines.append(line) self.concate_lines(lines, good_lines=good_lines, depth=depth) def common_end_points(self, line_1, line_2): """Проверяем совпадает ли какой-нибудь конец у двух линий. """ cp1 = line_1.GetEndPoint(0) cp2 = line_1.GetEndPoint(1) p1 = line_2.GetEndPoint(0) p2 = line_2.GetEndPoint(1) if cp1.DistanceTo(p1) < self.tollerance or cp1.DistanceTo( p2) < self.tollerance or cp2.DistanceTo( p1) < self.tollerance or cp2.DistanceTo( p2) < self.tollerance: return True else: cp1_to_line_2 = line_1.Project(p1) cp2_to_line_2 = line_1.Project(p2) p1_to_line_1 = line_2.Project(p1) p2_to_line_1 = line_2.Project(p2) if ( (cp1_to_line_2 and cp1_to_line_2.Distance < self.tollerance) and (cp2_to_line_2 and cp2_to_line_2.Distance < self.tollerance) ) or ((p1_to_line_1 and p1_to_line_1.Distance < self.tollerance) and (p2_to_line_1 and p2_to_line_1.Distance < self.tollerance)): return True def get_new_line(self, line_1, line_2): cp1 = line_1.GetEndPoint(0) cp2 = line_1.GetEndPoint(1) p1 = line_2.GetEndPoint(0) p2 = line_2.GetEndPoint(1) line_1_unbound = line_1.Clone() line_1_unbound.MakeUnbound() line_2_unbound = line_2.Clone() line_2_unbound.MakeUnbound() inter_res = StrongBox[IntersectionResultArray]() inter_res_text = line_1_unbound.Intersect(line_2_unbound, inter_res) if inter_res_text == SetComparisonResult.Overlap: inter_point = next(iter(inter_res)).XYZPoint if cp1.DistanceTo( inter_point) < self.tollerance and cp2.DistanceTo( inter_point) > self.tollerance: return Line.CreateBound(cp2, inter_point) elif cp2.DistanceTo( inter_point) < self.tollerance and cp1.DistanceTo( inter_point) > self.tollerance: return Line.CreateBound(cp1, inter_point) def create_longest_lines(self, lines): """Делаем из поданных линий максимально длинную. """ all_points = self.all_lines_points(lines) p1, p2 = self.max_distance(all_points) return Line.CreateBound(p1, p2) def max_distance(self, points): """Из массива точек возвращаем две точки, которые находятся на максимальном расстоянии.""" max_distance = (0, 0, 0) args = [] for i in points: for b in points: distance = i.DistanceTo(b) if distance > max_distance[2]: max_distance = (i, b, distance) return (max_distance[0], max_distance[1]) def print_line_by_face(self, lines, graphic_syles, name): """Рисует линии для которых есть типоразмер На вход подаем: lines - массив линий graphic_syles - элемент графического стиля name - имя типоразмера стены """ if lines: line_set = set() test = CurveArray() if not graphic_syles: message("Не найден стиль для типоразмера {}".format(name)) return for i in lines: # if i.ApproximateLength > self.tollerance: test.Append(i) res = doc.Create.NewDetailCurveArray(curview, test) for i in res: i.LineStyle = graphic_syles def get_common_edges(self, room_solid, solids): """Получает общие грани у солидов. Логика получения: находим геометрический центр каждого солида из solids проходим по всем поверхностям данного солида проецируем на Face этот центр масс проверяем лежит ли данная точка на какой-либо из поверхностей room_solid. Если лижит - добавляем поверхность в faces проходим по всем выбранным поверхностям, по ее граням если линия не вертикальна - добавляем ее в lines - set() приводим все линии к горизонтальной Z - которых соответствует origin текущего вида убираем все null из массива возвращаем массив линий. """ lines = set() faces = set() for solid in solids: wall_cenroid = solid.ComputeCentroid() for face in solid.Faces: if isinstance(face, PlanarFace): for general_face in room_solid.Faces: centroid_project = face.Project(wall_cenroid) if centroid_project: center = centroid_project.XYZPoint result = general_face.Project(center) if result and result.Distance < 0.00001: # echo(face) faces.add(face) for face in faces: for edge_loop in face.EdgeLoops: for line in edge_loop: line = line.AsCurve() if self.is_not_vertical(line): intersection_result_inside = room_solid.IntersectWithCurve( line, self.intersect_option_inside) intersection_result_outside = room_solid.IntersectWithCurve( line, self.intersect_option_outside) if intersection_result_inside.SegmentCount > 0: max_distance_outside = 0 if intersection_result_outside.SegmentCount: max_distance_outside = intersection_result_outside.GetCurveSegment( 0).ApproximateLength # if max_distance_outside > 1: # self.print_line(intersection_result_inside.GetCurveSegment(0)) for i in range( 0, intersection_result_inside.SegmentCount): inter_line = intersection_result_inside.GetCurveSegment( i) if inter_line.ApproximateLength > max_distance_outside + 0.0001: lines.add(inter_line) lines = [self.line_z_to_curview(line) for line in lines] lines = [i for i in lines if i is not None] return lines def print_line(self, line): """Рисуем линию.""" doc.Create.NewDetailCurve(curview, self.line_z_to_curview(line)) def line_z_to_curview(self, line): """Обнуляет координату Z у линии.""" z = curview.Origin.Z p1 = line.GetEndPoint(0) p2 = line.GetEndPoint(1) p1 = XYZ(p1.X, p1.Y, z) p2 = XYZ(p2.X, p2.Y, z) return Line.CreateBound(p1, p2) def is_not_vertical(self, line): """Проверяет не является ли линия вертикальной.""" vec = (line.GetEndPoint(0) - line.GetEndPoint(1)).Normalize() if not (vec.IsAlmostEqualTo(XYZ(0, 0, 1)) or vec.IsAlmostEqualTo(XYZ(0, 0, -1))): return True def get_wall_intersect(self, room, walls): """Находим стены которые пересекаются с текущим помещением""" room_geometries = room.Geometry[self.view_option].GetEnumerator() walls_intersect = [] for room_geometry in room_geometries: for i in walls: wall_geometries = i.Geometry[self.view_option].GetEnumerator() for wall_geometry in wall_geometries: union_solid = BooleanOperationsUtils.ExecuteBooleanOperation( room_geometry, wall_geometry, BooleanOperationsType.Union) sum_area = ((room_geometry.SurfaceArea + wall_geometry.SurfaceArea) - union_solid.SurfaceArea) if sum_area > 0.0001: walls_intersect.append(wall_geometry) return (walls_intersect, room_geometry) def all_lines_points(self, lines): """Все точки линий """ all_points = [] for i in lines: all_points.append(i.GetEndPoint(0)) all_points.append(i.GetEndPoint(1)) return all_points def create_rings(self, lines): """Создание колец """ # echo('является ли {} кольцом?'.format(line_name)) # echo(self.is_ring(lines)) new_lines = [] for line_1 in lines: for line_2 in lines: inter_res = self.get_new_line(line_1, line_2) if inter_res: line_1 = inter_res new_lines.append(line_1) return new_lines def is_ring(self, lines): """Являются ли заданные линии кольцом У каждого кольца должно быть парное количество одинаковых точек. иначе это не кольцо """ points = self.all_lines_points(lines) for point_1 in points: count = 0 for point_2 in points: echo(count) if point_1.IsAlmostEqualTo(point_2): count += 1 # if count < 2: # return return True
from Autodesk.Revit.DB import DatumExtentType, FilteredElementCollector, BuiltInCategory, Line, Reference, ReferenceArray, Options, XYZ import rpw from rpw import revit doc = revit.doc uidoc = revit.uidoc selection = FilteredElementCollector(doc).OfCategory( BuiltInCategory.OST_Levels).WhereElementIsNotElementType() # All reference in reference will be dimensioned reference_array = ReferenceArray() options = Options(ComputeReferences=True, IncludeNonVisibleObjects=True) for element in selection: reference_array.Append(Reference(element)) crvs = [] ends = [] for element in selection: crvs.extend( element.GetCurvesInView(DatumExtentType.ViewSpecific, doc.ActiveView)) for crv in crvs: ends.append(crv.GetEndPoint(0))
def analyze_rooms(rooms, boundary_location=1): """Convert revit rooms to dynosaur rooms. This script will only work from inside Dynamo nodes. for a similar script forRrevit check this link for more details: https://github.com/jeremytammik/SpatialElementGeometryCalculator/ blob/master/SpatialElementGeometryCalculator/Command.cs """ # unwrap room elements # this is not the right way of logging in python and probably any other language log = [] rooms = tuple(_get_internalelement_collector(rooms)) if not rooms: return [] # create a spatial element calculator to calculate room data doc = rooms[0].Document options = SpatialElementBoundaryOptions() options.SpatialElementBoundaryLocation = get_boundary_location(boundary_location) calculator = SpatialElementGeometryCalculator(doc, options) opt = Options() element_collector = [] room_collector = range(len(rooms)) # surface_collector = {} # collect hbSurfaces so I can set adjucent surfaces for room_count, revit_room in enumerate(rooms): # initiate zone based on room id element_collector.append([]) new_room = room.create_room(revit_room.Id) # calculate spatial data for revit room revit_room_spatial_data = calculator.CalculateSpatialElementGeometry(revit_room) # get the geometry of the room revit_room_geometry = revit_room_spatial_data.GetGeometry() # Cast revit room faces to dynamo geometry using ToProtoType method room_faces_dyn = \ tuple(face.ToProtoType()[0] for face in revit_room_geometry.Faces) assert revit_room_geometry.Faces.Size == len(room_faces_dyn), \ "Number of rooms elements ({}) doesn't match number of faces ({}).\n" \ "Make sure the Room is bounded.".format(revit_room_geometry.Faces.Size, len(room_faces_dyn)) for count, face in enumerate(revit_room_geometry.Faces): # base face is useful to project the openings to room boundary base_face_dyn = room_faces_dyn[count] # Revit is strange! if two roofs have a shared wall then it will be # duplicated! By checking the values inside the _collector I try to avoid # that. _collector = [] boundary_faces = revit_room_spatial_data.GetBoundaryFaceInfo(face) if len(boundary_faces) == 0: # There is no boundary face! I don't know what does this exactly mean # in the Revit world but now that there is no boundary face we can just # use the dynamo face and create the surface! face_vertices = tuple(v.PointGeometry for v in base_face_dyn.Vertices) new_surface = surface.create_surface( "%s_%s" % (new_room['name'], create_uuid()), new_room['name'], face_vertices ) room.add_surface_to_room(new_room, new_surface) continue for boundary_face in boundary_faces: # boundary_face is a SpatialElementBoundarySubface # we need ti get the element (Wall, Roof, etc) first boundary_element = doc.GetElement( boundary_face.SpatialBoundaryElement.HostElementId ) # initiate honeybee surface face_vertices = tuple(v.PointGeometry for v in base_face_dyn.Vertices) # TODO(mostapha) This should be done once when all the surfaces are # created. if face_vertices in _collector: continue new_surface = surface.create_surface( "%s_%s" % (new_room['name'], boundary_element.Id), new_room['name'], face_vertices ) # TODO(mostapha) This should be done once when all the surfaces are # created. _collector.append(face_vertices) # collect element id for each face. # this can be part of the object itself. I need to think about it before # adding it to the object. Trying to keep it as light as possible element_collector[room_count].append(doc.GetElement( boundary_face.SpatialBoundaryElement.HostElementId )) # I'm not sure how this works in Revit but I assume there is an easy # way to find the adjacent surface for an element. Let's hope this time # revit doesn't let me down! # if boundary_element.Id not in surface_collector: # surface_collector[boundary_element.Id] = new_surface # else: # # TODO(mostapha): set adjacent surface # pass # ----------------------- child surfaces --------------------------- # # time to find child surfaces (e.g. windows!) # this is the reason dynosaur exists in the first place # Take care of curtain wall systems # This will most likely fail for custom curtain walls if get_parameter(boundary_element, 'Family') == 'Curtain Wall': # get cooredinates and element ids for this curtain wall. _elementIds, _coordinates = extract_panels_vertices( boundary_element, base_face_dyn, opt) for count, coordinate in enumerate(_coordinates): if not coordinate: log.append("{} has an opening with less than " "two coordinates. It has been removed!" .format(_elementIds[count])) continue # create honeybee surface - use element id as the name new_fen_surface = surface.create_fen_surface( _elementIds[count], new_surface['name'], coordinate) # get element and add it to the collector elm = boundary_element.Document.GetElement(_elementIds[count]) element_collector[room_count].append(elm) # add fenestration surface to base surface surface.add_fenestration_to_surface(new_surface, new_fen_surface) else: # collect child elements for non-curtain wall systems childelement_collector = get_child_elemenets(boundary_element) if childelement_collector: _coordinates = exctract_glazing_vertices( boundary_element, base_face_dyn, opt ) for count, coordinate in enumerate(_coordinates): if not coordinate: log.append("{} in {} has an opening with less than " "two coordinates. It has been removed!" .format( childelement_collector[count].Id, new_room['name'] )) # create honeybee surface - use element id as the name new_fen_surface = surface.create_fen_surface( childelement_collector[count].Id, new_room['name'], coordinate ) # add fenestration surface to base honeybee surface element_collector[room_count].append( childelement_collector[count] ) # add fenestration surface to base surface surface.add_fenestration_to_surface(new_surface, new_fen_surface) # add surface to dynosaur room room.add_surface_to_room(new_room, new_surface) # clean up! boundary_element.Dispose() room_collector[room_count] = new_room # clean up! revit_room_spatial_data.Dispose() calculator.Dispose() return room_collector, element_collector, log