.. _domains: Domains ======= Domains are mainly used when creating :ref:`nets `. There are different types that all inherit from the :py:class:`~ddg.datastructures.nets.domain.Domain` class, for example - :py:class:`~ddg.datastructures.nets.domain.EmptyDomain` - :py:class:`~ddg.datastructures.nets.domain.SmoothDomain` - :py:class:`~ddg.datastructures.nets.domain.DiscreteDomain` - :py:class:`~ddg.datastructures.nets.domain.SmoothInterval` - :py:class:`~ddg.datastructures.nets.domain.DiscreteInterval` or domains specified by their shape, for example - :py:class:`~ddg.datastructures.nets.domain.SmoothRectangularDomain` - :py:class:`~ddg.datastructures.nets.domain.DiscreteRectangularDomain` - :py:class:`~ddg.datastructures.nets.domain.DiscreteTriangularDomain` - :py:class:`~ddg.datastructures.nets.domain.DiscreteDiagonalDomain` These classes are located in :py:mod:`ddg.datastructures.nets.domain`. Creating a smooth domain ------------------------ A smooth domain is given by an interval for each of its direction. .. doctest:: >>> import ddg >>> import numpy as np >>> domain = ddg.nets.SmoothDomain([[0,4],[-np.pi, np.pi]]) >>> domain.bounded True >>> domain.intervals [[0.0, 4.0], [-3.141592653589793, 3.141592653589793]] >>> domain.periodicity set() Note that :py:class:`~ddg.datastructures.nets.domain.SmoothDomain` always expects a list of intervals to be passed to it, even if the domain is supposed to be 1-dimensional. To circumvent this, use :py:class:`~ddg.datastructures.nets.domain.SmoothInterval` instead: .. doctest:: >>> import ddg >>> domain = ddg.nets.SmoothInterval([0.0, 4.0]) >>> domain.interval [0.0, 4.0] You can also create both unbounded and periodic domains. .. doctest:: >>> import ddg >>> import numpy as np >>> domain = ddg.nets.SmoothDomain([[-np.inf, 0], [0, 2]]) >>> domain.bounded False >>> domain.unbounded_directions [0] To mark a direction as periodic, simply add ``True`` as the third entry of its interval: .. doctest:: >>> import ddg >>> domain = ddg.nets.SmoothDomain([[0, 3], [0, 2*np.pi, True]]) >>> domain.periodicity {1} Creating a discrete domain -------------------------- A :py:class:`~ddg.datastructures.nets.domain.DiscreteDomain` behaves very much the same as a smooth one. They have all properties of a smooth domain, but additionally contain the combinatorial information of themselves, i.e. their edge and face data. These are used primarily in the conversion to a blender mesh. .. doctest:: >>> import ddg >>> domain = ddg.nets.DiscreteDomain([[0,4], [-1,10]]) >>> domain.intervals [[0, 4], [-1, 10]] Moreover we can iterate over all points inside of a discrete domain with the help of its traverser: .. doctest:: >>> import ddg >>> domain = ddg.nets.DiscreteDomain([[0,1],[0,1]]) >>> for i in domain.traverser: ... print(i) (0, 0) (0, 1) (1, 0) (1, 1) >>> for i in domain.traverser: ... print(domain.traverser.idx(*i)) 0 1 2 3 >>> for i in domain.edge_data: ... print(i) (0, 2) (0, 1) (1, 3) (2, 3) >>> for i in domain.face_data: ... print(i) (0, 2, 3, 1) Modifying a domain ------------------ A domain can be modifyied by utility functions located at :py:mod:`ddg.datastructures.nets.utils`. Possibilities are - :py:func:`~ddg.datastructures.nets.utils.shrink_domain` - :py:func:`~ddg.datastructures.nets.utils.bound_domain` - :py:func:`~ddg.datastructures.nets.utils.create_subdomain` - :py:func:`~ddg.datastructures.nets.utils.delete_direction` - :py:func:`~ddg.datastructures.nets.utils.modify_direction` Converting a domain ------------------- Bounded discrete domains of dimension 2 or less can be converted to a :ref:`half_edge` object using the function :py:func:`ddg.conversion.halfedge.nets.discrete_domain_to_halfedge`. The vertices of the resulting halfedge object will have an attribute `co` containing the value from domain.traverser and the order will be the same. .. doctest:: >>> from ddg.conversion.halfedge.nets import discrete_domain_to_halfedge >>> domain = ddg.nets.DiscreteDomain([[0,1],[0,1]]) >>> surface = discrete_domain_to_halfedge(domain) >>> for c in domain.traverser: ... print(c) (0, 0) (0, 1) (1, 0) (1, 1) >>> for v in surface.verts: ... print(v.co) (0, 0) (0, 1) (1, 0) (1, 1) The name of the coordinate attribute can be changed using the `co_attr` argument of the conversion function.