Example #1
0
    def value(self, value):
        if self._revit_object.IsReadOnly:
            raise RpwException('Parameter is Read Only: {}'.format(
                self._revit_object.Definition.Name))

        # Check if value provided matches storage type
        if not isinstance(value, self.type):
            # If not, try to handle
            if self.type is str and value is None:
                value = ''
            if self.type is str and value is not None:
                value = str(value)
            elif self.type is DB.ElementId and value is None:
                value = DB.ElementId.InvalidElementId
            elif isinstance(value, int) and self.type is float:
                value = float(value)
            elif isinstance(value, float) and self.type is int:
                value = int(value)
            elif isinstance(value, bool) and self.type is int:
                value = int(value)
            else:
                raise RpwWrongStorageType(self.type, value)

        param = self._revit_object.Set(value)
        return param
Example #2
0
    def collect(cls, **kwargs):
        """
        Collect all elements of the wrapper using the default collector.
        This method is defined on the main Element wrapper, but the
        collector parameters are defined in each wrapper. For example,
        :any:`WallType` uses the `_collector_params`:
        {'of_class': DB.WallType, 'is_type': True}

        These default collector parameters can be overriden by passing keyword
        args to the collectors call.

        >>> from rpw import db
        >>> wall_types_collector = db.WallType.collect()
        <rpw:Collector % FilteredElementCollector [count:4]>
        >>> wall_types_collector.get_elements()  # All Wall Types
        [<rpw:WallType [name:Wall 1] [id:1557]>, ... ]
        >>> wall_types_collector.get_elements()
        [<rpw:Area % DB.Area | Rentable:30.2>]
        >>> rooms = db.WallInstance.collect(level="Level 1")
        [<rpw:WallInstance % DB.Wall symbol:Basic Wall>]

        """
        _collector_params = getattr(cls, '_collector_params', None)

        if _collector_params:
            kwargs.update(_collector_params)
            return rpw.db.Collector(**kwargs)
        else:
            raise RpwException('Wrapper cannot collect by class: {}'.format(cls.__name__))
Example #3
0
    def value(self):
        """
        Gets Parameter Value:

        Returns:
            type: parameter value in python type

        >>> desk.parameters['Height'].value
        >>> 3.0

        Sets Parameter Value (must be in Transaction Context):

        >>> desk.parameters['Height'].value = 3

        Note:

            `Parameter` value setter automatically handles a few type castings:

            * Storage is ``str`` and value is ``None``; value is converted to ``blank_string``
            * Storage is ``str`` and value is ``any``; value is converted to ``string``
            * Storage is ``ElementId`` and value is ``None``; value is converted to ``ElemendId.InvalidElementId``
            * Storage is ``int`` and value is ``float``; value is converted to ``int``
            * Storage is ``float`` and value is ``int``; value is converted to ``float``

        """
        if self.type is str:
            return self._revit_object.AsString()
        if self.type is float:
            return self._revit_object.AsDouble()
        if self.type is DB.ElementId:
            return self._revit_object.AsElementId()
        if self.type is int:
            return self._revit_object.AsInteger()

        raise RpwException('could not get storage type: {}'.format(self.type))
Example #4
0
    def __init__(self, **filters):
        """
        Args:
            **filters (``keyword args``): Scope and filters

        Returns:
            Collector (:any:`Collector`): Collector Instance

        Scope Options:
            * ``view`` `(DB.View)`: View Scope (Optional)
            * ``element_ids`` `([ElementId])`: List of Element Ids to limit Collector Scope
            * ``elements`` `([Element])`: List of Elements to limit Collector Scope

        Warning:
            Only one scope filter should be used per query. If more then one is used,
            only one will be applied, in this order ``view`` > ``elements`` > ``element_ids``

        Filter Options:
            * is_type (``bool``): Same as ``WhereElementIsElementType``
            * is_not_type (``bool``): Same as ``WhereElementIsNotElementType``
            * of_class (``Type``): Same as ``OfClass``. Type can be ``DB.SomeType`` or string: ``DB.Wall`` or ``'Wall'``
            * of_category (``BuiltInCategory``): Same as ``OfCategory``. Can be ``DB.BuiltInCategory.OST_Wall`` or ``'Wall'``
            * owner_view (``DB.ElementId, View`): ``WhereElementIsViewIndependent(True)``
            * is_view_independent (``bool``): ``WhereElementIsViewIndependent(True)``
            * family (``DB.ElementId``, ``DB.Element``): Element or ElementId of Family
            * symbol (``DB.ElementId``, ``DB.Element``): Element or ElementId of Symbol
            * level (``DB.Level``, ``DB.ElementId``, ``Level Name``): Level, ElementId of Level, or Level Name
            * not_level (``DB.Level``, ``DB.ElementId``, ``Level Name``): Level, ElementId of Level, or Level Name
            * parameter_filter (:any:`ParameterFilter`): Applies ``ElementParameterFilter``
            * exclude (`element_references`): Element(s) or ElementId(s) to exlude from result
            * and_collector (``collector``): Collector to intersect with. Elements must be present in both
            * or_collector (``collector``): Collector to Union with. Elements must be present on of the two.
            * where (`function`): function to test your elements against

        """
        # Define Filtered Element Collector Scope + Doc
        collector_doc = filters.pop('doc') if 'doc' in filters else revit.doc

        if 'view' in filters:
            view = filters.pop('view')
            view_id = view if isinstance(view, DB.ElementId) else view.Id
            collector = DB.FilteredElementCollector(collector_doc, view_id)
        elif 'elements' in filters:
            elements = filters.pop('elements')
            element_ids = to_element_ids(elements)
            collector = DB.FilteredElementCollector(collector_doc, List[DB.ElementId](element_ids))
        elif 'element_ids' in filters:
            element_ids = filters.pop('element_ids')
            collector = DB.FilteredElementCollector(collector_doc, List[DB.ElementId](element_ids))
        else:
            collector = DB.FilteredElementCollector(collector_doc)

        super(Collector, self).__init__(collector)

        for key in filters.keys():
            if key not in [f.keyword for f in FilterClasses.get_sorted()]:
                raise RpwException('Filter not valid: {}'.format(key))

        self._collector = self._collect(collector_doc, collector, filters)
Example #5
0
 def name(self):
     """ Returns:
         ``str``: name of the Family """
     # This BIP only exist in symbols, so we retrieve a symbol first.
     # The Alternative is to use Element.Name.GetValue(), but I am
     # avoiding it due to the import bug in ironpython
     # https://github.com/IronLanguages/ironpython2/issues/79
     try:
         symbol = self.symbols[0]
     except IndexError:
         raise RpwException('Family [{}] has no symbols'.format(self.name))
     return Element(
         symbol).parameters.builtins['SYMBOL_FAMILY_NAME_PARAM'].value
Example #6
0
 def __getattr__(self, attr):
     """
     Getter for original methods and properties or the element.
     This method is only called if the attribute name does not
     already exists.
     """
     try:
         return getattr(self.__dict__['_revit_object'], attr)
     # except AttributeError:
     # This lower/snake case to be converted.
     # This automatically gives acess to all names in lower case format
     # x.name (if was not already defined, will get x.Name)
     # Note: will not Work for setters, unless defined by wrapper
     # attr_pascal_case = rpw.utils.coerce.to_pascal_case(attr)
     # return getattr(self.__dict__['_revit_object'], attr_pascal_case)
     except KeyError:
         raise RpwException('BaseObjectWrapper is missing _revit_object')
Example #7
0
    def __new__(cls, element, **kwargs):
        """
        Factory Constructor will chose the best Class for the Element.
        This function iterates through all classes in the rpw.db module,
        and will find one that wraps the corresponding class. If and exact
        match is not found :any:`Element` is used
        """
        defined_wrapper_classes = rpw.db.__all__

        _revit_object_class = cls._revit_object_class

        if element is None:
            raise RpwTypeError('Element or Element Child', 'None')

        # TODO: Handle double wrapping
        if hasattr(element, 'unwrap'):
            raise RpwTypeError('revit element', 'wrapped element: {}'.format(element))

        # Ensure Wrapped Element is instance of Class Wrapper or decendent
        if not isinstance(element, _revit_object_class):
            raise RpwTypeError(_revit_object_class.__name__,
                               element.__class__.__name__)

        # Ensure Wrapped Element is instance of Class Wrapper or decendent
        if not isinstance(element, _revit_object_class):
            raise RpwTypeError(_revit_object_class, element.__class__)

        # If explicit constructor was called, use that and skip discovery
        if type(element) is _revit_object_class:
            return super(Element, cls).__new__(cls, element, **kwargs)

        for wrapper_class in defined_wrapper_classes:
            class_name = wrapper_class.__name__
            if type(element) is getattr(wrapper_class, '_revit_object_class', None):
                # Found Mathing Class, Use Wrapper
                # print('Found Mathing Class, Use Wrapper: {}'.format(class_name))
                return super(Element, cls).__new__(wrapper_class, element, **kwargs)
        else:
            # Could Not find a Matching Class, Use Element if related
            return super(Element, cls).__new__(cls, element, **kwargs)

        # No early return. Should not reach this point
        element_class_name = element.__class__.__name__
        raise RpwException('Factory does not support type: {}'.format(element_class_name))
Example #8
0
    def collect(cls, **kwargs):
        """ Collect all elements of the wrapper, using the default collector.

        Collector will use default params (ie: Room ``{'of_category': 'OST_rooms'}``).
        These can be overriden by passing keyword args to the collectors call.

        >>> rooms = rpw.db.Rooms.collect()
        [<rpw:Room % DB.Room | Room:1>]
        >>> rooms = rpw.db.Area.collect()
        [<rpw:Area % DB.Area | Rentable:30.2>]
        >>> rooms = rpw.db.WallInstance.collect(level="Level 1")
        [<rpw:WallInstance % DB.Wall symbol:Basic Wall>]

        """
        _collector_params = getattr(cls, '_collector_params', None)

        if _collector_params:
            kwargs.update(_collector_params)
            return rpw.db.Collector(**kwargs)
        else:
            raise RpwException('Wrapper cannot collect by class: {}'.format(
                cls.__name__))
Example #9
0
    def __new__(cls, element, **kwargs):
        """
        Factory Constructor will chose the best Class for the Element.
        This function iterates through all classes in the rpw.db module,
        and will find one that wraps the corresponding class. If and exact
        match is not found :any:`Element` is used
        """
        defined_wrapper_classes = inspect.getmembers(rpw.db, inspect.isclass)
        # [('Area', '<class Area>'), ... ]

        _revit_object_class = cls._revit_object_class

        if element is None:
            raise RpwTypeError('Element or Element Child', 'None')

        # Ensure Wrapped Element is instance of Class Wrapper or decendent
        # Must also check is element because isinstance(Element, Element) is False
        if not isinstance(element, _revit_object_class):
            #    or cls is not Element:
            raise RpwTypeError(_revit_object_class, type(element))

        # rpw.ui.forms.Console()
        for class_name, wrapper_class in defined_wrapper_classes:
            if type(element) is getattr(wrapper_class, '_revit_object_class',
                                        None):
                # Found Mathing Class, Use Wrapper
                # print('Found Mathing Class, Use Wrapper: {}'.format(class_name))
                return super(Element, cls).__new__(wrapper_class, element,
                                                   **kwargs)
                # new_obj._revit_object = element
                # return new_object
        else:
            # Could Not find a Matching Class, Use Element if related
            # print('Did not find a Matching Class, will use Element if related')
            if DB.Element in inspect.getmro(element.__class__):
                return super(Element, cls).__new__(cls, element, **kwargs)
        element_class_name = element.__class__.__name__
        raise RpwException(
            'Factory does not support type: {}'.format(element_class_name))
Example #10
0
    def __new__(cls, element, **kwargs):
        """
        Factory Constructor will chose the best Class for the Element.
        This function iterates through all classes in the rpw.db module,
        and will find one that wraps the corresponding class. If and exact
        match is not found :any:`Element` is used
        """
        defined_wrapper_classes = rpw.db.__all__

        _revit_object_class = cls._revit_object_class

        if element is None:
            raise RpwTypeError('Element or Element Child', 'None')

        # Ensure Wrapped Element is instance of Class Wrapper or decendent
        # Must also check is element because isinstance(Element, Element) is False
        if not isinstance(element, _revit_object_class):
            # or cls is not Element:
            raise RpwTypeError('DB.Element child', element.__class__.__name__)

        # TODO: OPtimize so if its right type, no need to iterate: rpw.db.Wall(wall)
        for wrapper_class in defined_wrapper_classes:
            class_name = wrapper_class.__name__
            if type(element) is getattr(wrapper_class, '_revit_object_class',
                                        None):
                # Found Mathing Class, Use Wrapper
                # print('Found Mathing Class, Use Wrapper: {}'.format(class_name))
                return super(Element, cls).__new__(wrapper_class, element,
                                                   **kwargs)
        else:
            # Could Not find a Matching Class, Use Element if related
            if DB.Element in inspect.getmro(element.__class__):
                return super(Element, cls).__new__(cls, element, **kwargs)

        # No early return. Should not reach this point
        element_class_name = element.__class__.__name__
        raise RpwException(
            'Factory does not support type: {}'.format(element_class_name))
Example #11
0
    def __init__(self, parameter_reference, **conditions):
        """
        Creates Parameter Filter Rule

        >>> param_rule = ParameterFilter(param_id, equals=2)
        >>> param_rule = ParameterFilter(param_id, not_equals='a', case_sensitive=True)
        >>> param_rule = ParameterFilter(param_id, not_equals=3, reverse=True)

        Args:
            param_id(DB.ElementID): ElementId of parameter
            **conditions: Filter Rule Conditions and options.

            conditions:
                | ``begins``, ``not_begins``
                | ``contains``, ``not_contains``
                | ``ends``, ``not_ends``
                | ``equals``, ``not_equals``
                | ``less``, ``not_less``
                | ``less_equal``, ``not_less_equal``
                | ``greater``, ``not_greater``
                | ``greater_equal``, ``not_greater_equal``

            options:
                | ``case_sensitive``: Enforces case sensitive, String only
                | ``reverse``: Reverses result of Collector

        """
        parameter_id = self.coerce_param_reference(parameter_reference)
        reverse = conditions.get('reverse', False)
        case_sensitive = conditions.get('case_sensitive', ParameterFilter.CASE_SENSITIVE)
        precision = conditions.get('precision', ParameterFilter.FLOAT_PRECISION)

        for condition in conditions.keys():
            if condition not in ParameterFilter.RULES:
                raise RpwException('Rule not valid: {}'.format(condition))

        rules = []
        for condition_name, condition_value in conditions.iteritems():

            # Returns on of the CreateRule factory method names above
            rule_factory_name = ParameterFilter.RULES.get(condition_name)
            filter_value_rule = getattr(DB.ParameterFilterRuleFactory,
                                        rule_factory_name)

            args = [condition_value]

            if isinstance(condition_value, str):
                args.append(case_sensitive)

            if isinstance(condition_value, float):
                args.append(precision)

            filter_rule = filter_value_rule(parameter_id, *args)
            if 'not_' in condition_name:
                filter_rule = DB.FilterInverseRule(filter_rule)

            logger.debug('ParamFilter Conditions: {}'.format(conditions))
            logger.debug('Case sensitive: {}'.format(case_sensitive))
            logger.debug('Reverse: {}'.format(reverse))
            logger.debug('ARGS: {}'.format(args))
            logger.debug(filter_rule)
            logger.debug(str(dir(filter_rule)))

            rules.append(filter_rule)
        if not rules:
            raise RpwException('malformed filter rule: {}'.format(conditions))

        _revit_object = DB.ElementParameterFilter(List[DB.FilterRule](rules),
                                                  reverse)
        super(ParameterFilter, self).__init__(_revit_object)
        self.conditions = conditions