"""Generate geometric objects as indexed face sets."""
import ddg.indexedfaceset._ifs as ifs
import ddg.math.discrete_objects as dis_obj
import ddg.math.grids as grids
[docs]def tetrahedron(co_attr="co"):
"""
Create a tetrahedron as an indexed face set.
By default, standard coordinates of a unit tetrahedron, centered at
(0, 0, 0), will be assigned to the vertices.
Parameters
----------
co_attr : str or None (default="co")
Name of the vertex attribute that stores the coordinates.
If `co_attr=None`, don't assign any coordinates.
Returns
-------
obj : ddg.indexedfaceset.IndexedFaceSet
A tetrahedron.
"""
obj = ifs.IndexedFaceSet(dis_obj.tetrahedron_faces())
if co_attr:
obj.set_attribute(co_attr, "verts", dis_obj.tetrahedron_coordinates())
return obj
[docs]def cube(co_attr="co"):
"""
Create a cube as an indexed face set
By default, standard coordinates of a unit cube, centered at
(0, 0, 0), will be assigned to the vertices.
Parameters
----------
co_attr : str or None (default="co")
Name of the vertex attribute that stores the coordinates.
If `co_attr=None`, don't assign any coordinates.
Returns
-------
obj : ddg.indexedfaceset.IndexedFaceSet
A cube.
"""
obj = ifs.IndexedFaceSet(dis_obj.cube_faces())
if co_attr:
obj.set_attribute(co_attr, "verts", dis_obj.cube_coordinates())
return obj
[docs]def octahedron(co_attr="co"):
"""
Create an octahedron as an indexed face set.
By default, standard coordinates of a unit octahedron, centered at
(0, 0, 0), will be assigned to the vertices.
Parameters
----------
co_attr : str or None (default="co")
Name of the vertex attribute that stores the coordinates.
If `co_attr=None`, don't assign any coordinates.
Returns
-------
obj : ddg.indexedfaceset.IndexedFaceSet
An octahedron.
"""
obj = ifs.IndexedFaceSet(dis_obj.octahedron_faces())
if co_attr:
obj.set_attribute(co_attr, "verts", dis_obj.octahedron_coordinates())
return obj
[docs]def dodecahedron(co_attr="co"):
"""
Create a dodecahedron as an indexed face set.
By default, standard coordinates of a unit dodecahedron, centered at
(0, 0, 0), will be assigned to the vertices.
Parameters
----------
co_attr : str or None (default="co")
Name of the vertex attribute that stores the coordinates.
If `co_attr=None`, don't assign any coordinates.
Returns
-------
obj : ddg.indexedfaceset.IndexedFaceSet
A dodecahedron.
"""
obj = ifs.IndexedFaceSet(dis_obj.dodecahedron_faces())
if co_attr:
obj.set_attribute(co_attr, "verts", dis_obj.dodecahedron_coordinates())
return obj
[docs]def icosahedron(co_attr="co"):
"""
Create an icosahedron as an indexed face set.
By default, standard coordinates of a unit icosahedron, centered at
(0, 0, 0), will be assigned to the vertices.
Parameters
----------
co_attr : str or None (default="co")
Name of the vertex attribute that stores the coordinates.
If `co_attr=None`, don't assign any coordinates.
Returns
-------
obj : ddg.indexedfaceset.IndexedFaceSet
An icosahedron.
"""
obj = ifs.IndexedFaceSet(dis_obj.icosahedron_faces())
if co_attr:
obj.set_attribute(co_attr, "verts", dis_obj.icosahedron_coordinates())
return obj
[docs]def disc(
resolution=20,
center=(0, 0, 0),
normal=(0, 0, 1),
radius=1,
co_attr="co",
):
"""
Create a disc as an indexed face set.
By default, the disc is centered at (0, 0, 0), the normal is (0, 0, 1)
and the radius is 1.
Parameters
----------
resolution : int (default=20)
The amount of vertices of the disc
center : array_like of shape (3,) (default=(0, 0, 0))
The center of the disc as a list in 3D space.
normal : array_like of shape (3,) (default=(0, 0, 1))
The normal vector of the disc.
radius : float (default=1)
The radius of the disc.
co_attr : str or None (default="co")
Name of the vertex attribute that stores the coordinates.
If `co_attr=None`, don't assign any coordinates.
Returns
-------
obj : ddg.indexedfaceset.IndexedFaceSet
A disc.
"""
face = dis_obj.disc_face(resolution)
obj = ifs.IndexedFaceSet(face)
if co_attr:
obj.set_attribute(
co_attr,
"verts",
dis_obj.disc_coordinates(resolution, center, normal, radius),
)
return obj
[docs]def cone(
resolution=20,
fill_caps=True,
radius=1,
length=1,
center=(0, 0, 0),
normal=(0, 0, 1),
co_attr="co",
):
"""
Create a cone as an indexed face set.
By default, the cone's base will be at (0, 0, 0) and its tip at
(0, 0, 1).
Parameters
----------
resolution : int (default=20)
The number of vertices of the base.
fill_caps: bool (default=True)
If `True`, include the face of the base.
radius : float (default=1)
The radius of the base of the cone.
length : float (default=1)
The length of the cone.
center : array_like of shape (3,) (default=(0, 0, 0))
The center of the base of the cone.
normal : array_like of shape (3,) (default=(0, 0, 1))
The normal of the cone's base face.
co_attr : str or None (default="co")
Name of the vertex attribute that stores the coordinates.
If `co_attr=None`, don't assign any coordinates.
Returns
-------
obj : ddg.indexedfaceset.IndexedFaceSet
A cone.
"""
faces = dis_obj.cone_faces(resolution)
if not fill_caps:
faces = faces[1:]
obj = ifs.IndexedFaceSet(faces)
if co_attr:
obj.set_attribute(
co_attr,
"verts",
dis_obj.cone_coordinates(resolution, radius, length, center, normal),
)
return obj
[docs]def cylinder(
resolution=20,
fill_caps=True,
top_radius=1,
bot_radius=1,
length=1,
center=(0, 0, 0),
normal=(0, 0, 1),
co_attr="co",
):
"""
Create a cylinder as an indexed face set.
By default, the cylinder's bottom will be at (0, 0, 0) and its top at
(0, 0, 1).
Parameters
----------
resolution : int (default=20)
The number of vertices on each side.
fill_caps : bool (default=True)
If `True`, include the faces of the bottom and the top.
top_radius : float (default=1)
The radius of the top of the cylinder.
bot_radius : float (default=1)
The radius of the bottom of the cylinder
length : float (default=1)
The length of the cylinder.
center : array_like of shape (3,) (default=(0, 0, 0))
The center of the bottom of the cylinder.
normal : array_like of shape (3,) (default=(0, 0, 1))
The normal of the cylinder's top and bottom faces.
co_attr : str or None (default="co")
Name of the vertex attribute that stores the coordinates.
If `co_attr=None`, don't assign any coordinates.
Returns
-------
obj : ddg.indexedfaceset.IndexedFaceSet
A cylinder.
"""
faces = dis_obj.cylinder_faces(resolution)
if not fill_caps:
faces = faces[2:]
obj = ifs.IndexedFaceSet(faces)
if co_attr:
obj.set_attribute(
co_attr,
"verts",
dis_obj.cylinder_coordinates(
resolution, top_radius, bot_radius, length, center, normal
),
)
return obj
[docs]def arrow(
resolution=20,
heights=(0, 0.7, 0.7, 1),
radii=(0.05, 0.05, 0.125),
co_attr="co",
):
"""
Create an arrow as an indexed face set.
This is useful to visualise vectors.
By default, the arrow will point up. The bottom will be at (0, 0, 0) and
the tip at (0, 0, 1).
Parameters
----------
resolution : int (default=20)
The amount of vertices at the base of the tip
heights : float sequence of length 4 (default=(0, 0.7, 0.7, 1))
First element defines height of the bottom of the stick, the
second the height of the top of the stick, the third the
height of the base of the head and the fourth the height of
the tip.
radii : float sequence of length 3 (default=(0.05, 0.05, 0.125))
First element defines the radius of the bottom of the stick,
second the radius of the top of the stick and the third the
radius of the base of the tip.
co_attr : str or None (default="co")
Name of the vertex attribute that stores the coordinates.
If `co_attr=None`, don't assign any coordinates.
Returns
-------
obj : ddg.indexedfaceset.IndexedFaceSet
An arrow.
"""
obj = ifs.IndexedFaceSet(dis_obj.arrow_faces(resolution))
if co_attr:
obj.set_attribute(
co_attr, "verts", dis_obj.arrow_coordinates(resolution, heights, radii)
)
return obj
[docs]def grid(shape, co_attr="co"):
"""
Create a quad grid as an indexed face set.
The `shape` defines the number of vertices in each direction.
Both 2D and 3D grids are supported.
Parameters
----------
shape : tuple of length 2 or 3
Shape of the grid. The first entry is the number of vertices in the
x-direction, the second the number of vertices in the y-direction
and the third (if given) the number of vertices in the z-direction.
co_attr : str or None (default="co")
Name of the vertex attribute that stores the coordinates.
If `co_attr=None`, don't assign any coordinates.
Returns
-------
obj : ddg.indexedfaceset.IndexedFaceSet
A quad grid.
Examples
--------
>>> import ddg
>>> quad_grid = ddg.indexedfaceset.grid((2, 3))
>>> quad_grid.vertex_attributes["co"]
array([[0, 0],
[1, 0],
[0, 1],
[1, 1],
[0, 2],
[1, 2]])
>>> quad_grid = ddg.indexedfaceset.grid((2, 3, 1))
>>> quad_grid.vertex_attributes["co"]
array([[0, 0, 0],
[1, 0, 0],
[0, 1, 0],
[1, 1, 0],
[0, 2, 0],
[1, 2, 0]])
>>> quad_grid = ddg.indexedfaceset.grid((2, 3, 2))
>>> quad_grid.vertex_attributes["co"]
array([[0, 0, 0],
[1, 0, 0],
[0, 1, 0],
[1, 1, 0],
[0, 2, 0],
[1, 2, 0],
[0, 0, 1],
[1, 0, 1],
[0, 1, 1],
[1, 1, 1],
[0, 2, 1],
[1, 2, 1]])
"""
faces, coords = grids.quad_grid(shape)
obj = ifs.IndexedFaceSet(faces)
if co_attr:
obj.set_attribute(co_attr, "verts", coords)
return obj
[docs]def triangle_grid(shape, co_attr="co"):
"""
Create a triangle grid as an indexed face set.
The `shape` defines the number of vertices in each direction.
Currently only supports 2D grids and planar grids in 3D.
Parameters
----------
shape : tuple of length 2 or 3
Shape of the grid. The first entry is the number of vertices in the
x-direction, the second the number of vertices in the y-direction
and the third (if given) the number of vertices in the z-direction.
co_attr : str or None (default="co")
Name of the vertex attribute that stores the coordinates.
If `co_attr=None`, don't assign any coordinates.
Returns
-------
obj : ddg.indexedfaceset.IndexedFaceSet
A triangle grid.
Examples
--------
>>> import ddg
>>> tri_grid = ddg.indexedfaceset.triangle_grid((2, 3))
>>> tri_grid.vertex_attributes["co"]
array([[0, 0],
[2, 0],
[1, 2],
[3, 2],
[2, 4],
[4, 4]])
>>> tri_grid = triangle_grid((2, 3, 1))
>>> tri_grid.vertex_attributes["co"]
array([[0, 0, 0],
[2, 0, 0],
[1, 2, 0],
[3, 2, 0],
[2, 4, 0],
[4, 4, 0]])
"""
faces, coords = grids.triangle_grid(shape)
obj = ifs.IndexedFaceSet(faces)
if co_attr:
obj.set_attribute(co_attr, "verts", coords)
return obj
def triangulated_quad_grid(shape, co_attr="co"):
"""
Create a triangulated quad grid as an indexed face set.
The `shape` defines the number of vertices in each direction.
Both 2D and 3D grids are supported.
Parameters
----------
shape : tuple of length 2 or 3
Shape of the grid. The first entry is the number of vertices in the
x-direction, the second the number of vertices in the y-direction
and the third (if given) the number of vertices in the z-direction.
co_attr : str or None (default="co")
Name of the vertex attribute that stores the coordinates.
If `co_attr=None`, don't assign any coordinates.
Returns
-------
obj : ddg.indexedfaceset.IndexedFaceSet
A triangulated quad grid.
Examples
--------
>>> from ddg.indexedfaceset import triangulated_quad_grid
>>> tri_grid = triangulated_quad_grid((2, 3))
>>> tri_grid.vertex_attributes["co"]
array([[0, 0],
[1, 0],
[0, 1],
[1, 1],
[0, 2],
[1, 2]])
>>> tri_grid = triangulated_quad_grid((2, 3, 1))
>>> tri_grid.vertex_attributes["co"]
array([[0, 0, 0],
[1, 0, 0],
[0, 1, 0],
[1, 1, 0],
[0, 2, 0],
[1, 2, 0]])
>>> tri_grid = triangulated_quad_grid((2, 3, 2))
>>> tri_grid.vertex_attributes["co"]
array([[0, 0, 0],
[1, 0, 0],
[0, 1, 0],
[1, 1, 0],
[0, 2, 0],
[1, 2, 0],
[0, 0, 1],
[1, 0, 1],
[0, 1, 1],
[1, 1, 1],
[0, 2, 1],
[1, 2, 1]])
"""
faces, coords = grids.triangulated_quad_grid(shape)
obj = ifs.IndexedFaceSet(faces)
if co_attr:
obj.set_attribute(co_attr, "verts", coords)
return obj
[docs]def grid_with_periodicity(shape, periodicity=(0, 0), co_attr="co"):
"""
Create a quad grid with a periodicity as an indexed face set.
A quad grid with periodicity `(0, 0)` is the box in
Z^2 with lower-left corner `(0, 0)` and upper-right corner
`(shape[0] - 1, shape[1] - 1)`. In other words, the vertices are
`(i_0, i_1)` with `0 <= i_0 <= shape[0] - 1` and `0 <= i_1 <= shape[1] - 1`.
A quad grid with periodicity not equal to `(0, 0)` is obtained from the
quad grid with periodicity `(0, 0)` by gluing the boundary edges as
described in the table below.
Parameters
----------
shape : tuple of length 2
Shape of the grid. The first entry is the number of vertices in the
x-direction, the second the number of vertices in the y-direction.
periodicity : tuple of length 2 (default=(0,0))
The periodicity of the grid. This is only meaningful in case of 2D
grid. For 3D shape this attribute doesn't have any effect.
+-------------+---------------+-----------------------------------------------+
| Periodicity | Topology | Gluing Axis |
+=============+===============+===============================================+
| (0, 0) | Disk | None |
+-------------+---------------+-----------------------------------------------+
| (1, 0) | Cylinder | along the first axis |
+-------------+---------------+-----------------------------------------------+
| (0, 1) | Cylinder | along the second axis |
+-------------+---------------+-----------------------------------------------+
| (1, 1) | Torus | along both axes |
+-------------+---------------+-----------------------------------------------+
| (-1, 0) | Moebius Band | along the first axis in reversed orientation |
+-------------+---------------+-----------------------------------------------+
| (0, -1) | Moebius Band | along the second axis in reversed orientation |
+-------------+---------------+-----------------------------------------------+
co_attr : str or None (default="co")
Name of the vertex attribute that stores the coordinates.
If `co_attr=None`, don't assign any coordinates.
Returns
-------
obj : ddg.indexedfaceset.IndexedFaceSet
A quad grid.
Examples
--------
>>> import ddg
>>> grid = ddg.indexedfaceset.grid_with_periodicity((2, 3), periodicity=(1, 0))
>>> grid.face_list()
[(0, 1, 3, 2), (2, 3, 5, 4), (0, 1, 3, 2), (2, 3, 5, 4)]
>>> grid.vertex_attributes["co"]
array([[ 1.0000000e+00, 0.0000000e+00, 0.0000000e+00],
[-1.0000000e+00, 0.0000000e+00, 1.2246468e-16],
[ 1.0000000e+00, 1.0000000e+00, 0.0000000e+00],
[-1.0000000e+00, 1.0000000e+00, 1.2246468e-16],
[ 1.0000000e+00, 2.0000000e+00, 0.0000000e+00],
[-1.0000000e+00, 2.0000000e+00, 1.2246468e-16]])
"""
faces, coords = grids.quad_grid_with_periodicity(shape, periodicity)
obj = ifs.IndexedFaceSet(faces)
if co_attr:
obj.set_attribute(co_attr, "verts", coords)
return obj