Esempio n. 1
0
class PI(np.ndarray):
    """
    A class representing a point of intersection (PI) of an alignment.

    Parameters
    ----------
    x, y, z : float
        The x, y, and z coordinates.
    radius : float
        The radius of the horizontal curve. Use zero if a curve does not
        exist.
    """
    # Custom properties
    x = propy.index_property(0)
    y = propy.index_property(1)
    z = propy.index_property(2)

    def __new__(cls, x, y, z=0, radius=0):
        obj = np.array([x, y, z], dtype='float').view(cls)
        obj.radius = radius
        return obj

    def __array_finalize__(self, obj):
        if obj is None: return
        self.radius = getattr(obj, 'radius', 0)

    __repr__ = propy.repr_method('x', 'y', 'z', 'radius')
Esempio n. 2
0
class SurveyPoint(np.ndarray):
    """
    A class representing a survey point.

    Parameters
    ----------
    x, y, z : float
        The x, y, and z coordinates.
    """
    # Custom properties
    x = propy.index_property(0)
    y = propy.index_property(1)
    z = propy.index_property(2)

    def __new__(cls, x, y, z, **kwargs):
        obj = np.array([x, y, z], dtype='float').view(cls)
        obj.meta = dict(**kwargs)
        return obj

    def __array_finalize__(self, obj):
        if obj is None: return
        self.meta = getattr(obj, 'meta', {})

    __repr__ = propy.repr_method('x', 'y', 'z', 'meta')
Esempio n. 3
0
class ElementLoad(np.ndarray):
    """
    A class representing an element load.

    Parameters
    ----------
    element : str
        The name of the element to which the loads are applied.
    fx, fy, fz : float
        The global forces applied to the element.
    mx, my, mz : float
        The global moments applied to the element.
    ix, : float
        The distance from the i node at where the loads are applied.
    dx : float
        The distance from the ix position toward the j node over which
        the loads are applied.
    """
    # Custom properties
    element = propy.str_property('element')
    fx = propy.index_property(0)
    fy = propy.index_property(1)
    fz = propy.index_property(2)
    mx = propy.index_property(3)
    my = propy.index_property(4)
    mz = propy.index_property(5)
    _element_ref = propy.weakref_property('_element_ref')

    def __new__(cls, element, fx=0, fy=0, fz=0, mx=0, my=0, mz=0, ix=0, dx=-1):
        obj = np.array([fx, fy, fz, mx, my, mz], dtype='float').view(cls)
        obj.element = element
        obj.ix = ix
        obj.dx = dx
        return obj

    def __array_finalize__(self, obj):
        if obj is None: return
        self.element = getattr(obj, 'element', '')
        self.ix = getattr(obj, 'ix', 0)
        self.dx = getattr(obj, 'dx', 0)
        self._element_ref = None

    def __repr__(self):
        s = [
            'element={!r}'.format(self.element), 'forces={!r}'.format(
                (self.fx, self.fy, self.fz)), 'moments={!r}'.format(
                    (self.mx, self.my, self.mz)), 'ix={!r}'.format(self.ix),
            'dx={!r}'.format(self.dx)
        ]

        return '{}({})'.format(type(self).__name__, ', '.join(s))

    def forces(self):
        """Returns the force vector."""
        return self[:3]

    def moments(self):
        """Returns the moment vector."""
        return self[3:6]

    def get_element(self):
        """Gets the referenced element."""
        if self._element_ref is None:
            raise ValueError('Element has not been set.')
        return self._element_ref

    def set_element(self, edict):
        """
        Sets the element reference.

        Parameters
        ----------
        edict : dict
            A dictionary mapping node names to node objects.
        """
        self._element_ref = edict[self.element]

    def local_reactions(self, di=(0, 0, 0), dj=(0, 0, 0)):
        """
        Returns the local end reactions for the element.

        Parameters
        ----------
        di, dj : array
            The deflections at the i and j ends of the element.
        """
        di, dj = np.asarray(di), np.asarray(dj)
        e = self.get_element()
        xi, xj = e.get_nodes()

        dx, dy, dz = (xj - xi) + (dj - di)
        fx, fy, fz = self.forces()
        mx, my, mz = self.moments()

        r = local_reactions(fx, fy, fz, mx, my, mz, dx, dy, dz, e.roll,
                            self.ix, self.dx, e.imx_free, e.imy_free,
                            e.imz_free, e.jmx_free, e.jmy_free, e.jmz_free)

        return r

    def global_reactions(self, di=(0, 0, 0), dj=(0, 0, 0)):
        """
        Returns the global end reactions for the element.

        Parameters
        ----------
        di, dj : array
            The deflections at the i and j ends of the element.
        """
        di, dj = np.asarray(di), np.asarray(dj)
        e = self.get_element()
        t = e.transformation_matrix(di, dj)
        q = self.local_reactions(di, dj)
        return t.T.dot(q)
Esempio n. 4
0
class NodeLoad(np.ndarray):
    """
    A class representing a load applied to a node.

    Parameters
    ----------
    node : str
        The name of the node to which the load will be applied.
    fx, fy, fz : float
        The applied global node forces.
    mx, my, mz : float
        The applied global moments.
    dx, dy, dz : float
        The applied node deflections.
    rx, ry, rz : float
        The applied node rotations.
    """
    # Custom properties
    node = propy.str_property('node')
    _node_ref = propy.weakref_property('_node_ref')
    fx = propy.index_property(0)
    fy = propy.index_property(1)
    fz = propy.index_property(2)
    mx = propy.index_property(3)
    my = propy.index_property(4)
    mz = propy.index_property(5)
    dx = propy.index_property(6)
    dy = propy.index_property(7)
    dz = propy.index_property(8)
    rx = propy.index_property(9)
    ry = propy.index_property(10)
    rz = propy.index_property(11)

    def __new__(cls,
                node,
                fx=0,
                fy=0,
                fz=0,
                mx=0,
                my=0,
                mz=0,
                dx=0,
                dy=0,
                dz=0,
                rx=0,
                ry=0,
                rz=0):
        obj = np.array([fx, fy, fz, mx, my, mz, dx, dy, dz, rx, ry, rz],
                       dtype='float').view(cls)
        obj.node = node
        return obj

    def __array_finalize__(self, obj):
        if obj is None: return
        self.node = getattr(obj, 'node', '')
        self._node_ref = None

    def __repr__(self):
        s = [
            'node={!r}'.format(self.node), 'forces={!r}'.format(
                (self.fx, self.fy, self.fz)), 'moments={!r}'.format(
                    (self.mx, self.my, self.mz)), 'defl={!r}'.format(
                        (self.dx, self.dy, self.dz)), 'rot={!r}'.format(
                            (self.rx, self.ry, self.rz))
        ]

        return '{}({})'.format(type(self).__name__, ', '.join(s))

    def forces(self):
        """Returns the applied force and moment matrix."""
        return self[:6]

    def deflections(self):
        """Returns the applied deflection and rotation matrix."""
        return self[6:]

    def get_node(self):
        """Gets the referenced node."""
        if self._node_ref is None:
            raise ValueError('Node has not been set.')
        return self._node_ref

    def set_node(self, ndict):
        """
        Sets the node reference.

        Parameters
        ----------
        ndict : dict
            A dictionary mapping node names to node objects.
        """
        self._node_ref = ndict[self.node]
Esempio n. 5
0
class Node(np.ndarray):
    """
    A class representing a structural node.

    Parameters
    ----------
    name : str
        A unique name for the node.
    x, y, z : float
        The x, y, and z coordinates of the node.
    symmetry : {None, 'x', 'y', 'xy'}
        The symmetry of the node.
    fx_free, fy_free, fz_free : bool
        The force fixities of the node in the x, y, and z directions.
    mx_free, my_free, mz_free : bool
        The moment fixities of the node about the x, y, and z axes.
    """
    SYMMETRIES = (None, 'x', 'y', 'xy')

    # Custom properties
    name = propy.str_property('name')
    x = propy.index_property(0)
    y = propy.index_property(1)
    z = propy.index_property(2)
    symmetry = propy.enum_property('symmetry', set(SYMMETRIES))

    fx_free = propy.bool_property('fx_free')
    fy_free = propy.bool_property('fy_free')
    fz_free = propy.bool_property('fz_free')

    mx_free = propy.bool_property('mx_free')
    my_free = propy.bool_property('my_free')
    mz_free = propy.bool_property('mz_free')

    def __new__(cls,
                name,
                x=0,
                y=0,
                z=0,
                symmetry=None,
                fx_free=True,
                fy_free=True,
                fz_free=True,
                mx_free=True,
                my_free=True,
                mz_free=True):
        obj = np.array([x, y, z], dtype='float').view(cls)

        obj.name = name
        obj.symmetry = symmetry

        obj.fx_free = fx_free
        obj.fy_free = fy_free
        obj.fz_free = fz_free

        obj.mx_free = mx_free
        obj.my_free = my_free
        obj.mz_free = mz_free

        return obj

    def __array_finalize__(self, obj):
        if obj is None: return

        self.name = getattr(obj, 'name', '')
        self.symmetry = getattr(obj, 'symmetry', None)

        self.fx_free = getattr(obj, 'fx_free', True)
        self.fy_free = getattr(obj, 'fy_free', True)
        self.fz_free = getattr(obj, 'fz_free', True)

        self.mx_free = getattr(obj, 'mx_free', True)
        self.my_free = getattr(obj, 'my_free', True)
        self.mz_free = getattr(obj, 'mz_free', True)

    __repr__ = propy.repr_method('name', 'x', 'y', 'z', 'symmetry', 'fx_free',
                                 'fy_free', 'fz_free', 'mx_free', 'my_free',
                                 'mz_free')

    def __str__(self):
        return self.name

    def copy(self):
        """Returns a copy of the node."""
        return copy.copy(self)

    def f_fixed(self):
        """Sets the node force reactions to fixed."""
        self.fx_free = self.fy_free = self.fz_free = False
        return self

    def m_fixed(self):
        """Sets the node moment reactions to fixed."""
        self.mx_free = self.my_free = self.mz_free = False
        return self

    def fixed(self):
        """Sets the node force and moment reactions to fixed."""
        return self.f_fixed().m_fixed()

    def fixities(self):
        """Returns the force and moment fixities for the node."""
        return [
            self.fx_free, self.fy_free, self.fz_free, self.mx_free,
            self.my_free, self.mz_free
        ]

    def sym_nodes(self):
        """Returns the symmetric nodes for the node."""
        def primary():
            n = self.copy()
            n.name = '{}_p'.format(self.name)
            return n

        def x_sym():
            n = self.copy()
            n.name = '{}_x'.format(self.name)
            n[1] *= -1
            return n

        def y_sym():
            n = self.copy()
            n.name = '{}_y'.format(self.name)
            n[0] *= -1
            return n

        def xy_sym():
            n = self.copy()
            n.name = '{}_xy'.format(self.name)
            n[:2] *= -1
            return n

        if self.symmetry is None:
            return primary(),

        elif self.symmetry == 'x':
            return primary(), x_sym()

        elif self.symmetry == 'y':
            return primary(), y_sym()

        elif self.symmetry == 'xy':
            return primary(), x_sym(), y_sym(), xy_sym()
Esempio n. 6
0
class SurveyStake(np.ndarray):
    """
    A class representing a survey stake. This method should be initialized
    using the :meth:`SurveyStake.init_xy` or :meth:`SurveyStake.init_station`
    class methods.
    """
    TYPES = ('xy', 'station')

    # Custom properties
    x = propy.index_property(0)
    y = propy.index_property(1)
    z = propy.index_property(2)
    lock_z = propy.bool_property('lock_z')
    _type = propy.enum_property('_type', TYPES)

    def __new__(cls,
                x,
                y,
                z,
                station,
                offset,
                height,
                rotation,
                lock_z,
                _type,
                _init=False,
                **kwargs):
        if not _init:
            raise ValueError(
                'SurveyStake should be initialized using the '
                '`SurveyStake.init_xy` or `SurveyStake.init_station` methods '
                'in lieu of the standard initializer.')

        obj = np.array([x, y, z], dtype='float').view(cls)
        obj.station = station
        obj.offset = offset
        obj.height = height
        obj.rotation = rotation
        obj.lock_z = lock_z
        obj._type = _type
        obj.meta = dict(**kwargs)
        return obj

    def __array_finalize__(self, obj):
        if obj is None: return
        self.station = getattr(obj, 'station', 0)
        self.offset = getattr(obj, 'offset', 0)
        self.height = getattr(obj, 'height', 0)
        self.rotation = getattr(obj, 'rotation', 0)
        self.lock_z = getattr(obj, 'lock_z', False)
        self._type = getattr(obj, '_type', 'xy')
        self.meta = getattr(obj, 'meta', {})

    __repr__ = propy.repr_method('_type', 'x', 'y', 'z', 'station', 'offset',
                                 'lock_z', 'meta')

    @classmethod
    def init_xy(cls, x, y, z=0, height=0, rotation=0, lock_z=False, **kwargs):
        """
        Initializes a survey stake based on an (x, y) global coordinate.

        Parameters
        ----------
        x, y, z : float
            The x, y, and z coordinates.
        height : float
            The height of the point above z.
        rotation : float
            The rotation of the point about its base point.
        lock_z : float
            If False, the alignment will be snapped to the TIN (if applicable)
            during certain updates. Otherwise, the z coordinate will remain
            fixed.
        """
        return cls(x=x,
                   y=y,
                   z=z,
                   station=0,
                   offset=0,
                   height=height,
                   rotation=rotation,
                   lock_z=lock_z,
                   _type='xy',
                   _init=True,
                   **kwargs)

    @classmethod
    def init_station(cls,
                     station,
                     offset=0,
                     z=0,
                     height=0,
                     rotation=0,
                     lock_z=False,
                     **kwargs):
        """
        Initializes a survey stake based on a survey station and offset.

        Parameters
        ----------
        station : float
            The alignment survey station.
        offset : float
            The offset from the alignment.
        z : float
            The z coordinate.
        height : float
            The height of the point above z.
        rotation : float
            The rotation of the point about its base point.
        lock_z : float
            If False, the alignment will be snapped to the TIN (if applicable)
            during certain updates. Otherwise, the z coordinate will remain
            fixed.
        """
        return cls(x=0,
                   y=0,
                   z=z,
                   height=height,
                   rotation=rotation,
                   station=station,
                   offset=offset,
                   lock_z=lock_z,
                   _type='station',
                   _init=True,
                   **kwargs)