def Pyramid(points=None): """Create a pyramid defined by 5 points. Parameters ---------- points : sequence, optional Points of the pyramid. Points are ordered such that the first four points are the four counterclockwise points on the quadrilateral face, and the last point is the apex. Defaults to pyramid in example. Returns ------- pyvista.UnstructuredGrid Unstructured grid containing a single pyramid cell. Examples -------- >>> import pyvista >>> pointa = [1.0, 1.0, 0.0] >>> pointb = [-1.0, 1.0, 0.0] >>> pointc = [-1.0, -1.0, 0.0] >>> pointd = [1.0, -1.0, 0.0] >>> pointe = [0.0, 0.0, 1.608] >>> pyramid = pyvista.Pyramid([pointa, pointb, pointc, pointd, pointe]) >>> pyramid.plot(show_edges=True, line_width=5) """ if points is None: points = [[1.0, 1.0, 0.0], [-1.0, 1.0, 0.0], [-1.0, -1.0, 0.0], [1.0, -1.0, 0.0], [0.0, 0.0, (4 - 2**0.5)**0.5]] if len(points) != 5: raise TypeError('Points must be given as length 5 np.ndarray or list') check_valid_vector(points[0], 'points[0]') check_valid_vector(points[1], 'points[1]') check_valid_vector(points[2], 'points[2]') check_valid_vector(points[3], 'points[3]') check_valid_vector(points[4], 'points[4]') pyramid = _vtk.vtkPyramid() pyramid.GetPointIds().SetId(0, 0) pyramid.GetPointIds().SetId(1, 1) pyramid.GetPointIds().SetId(2, 2) pyramid.GetPointIds().SetId(3, 3) pyramid.GetPointIds().SetId(4, 4) ug = _vtk.vtkUnstructuredGrid() ug.SetPoints(pyvista.vtk_points(np.array(points), False)) ug.InsertNextCell(pyramid.GetCellType(), pyramid.GetPointIds()) return pyvista.wrap(ug)
def Pyramid(points): """Create a pyramid defined by 5 points. Parameters ---------- points : np.ndarray or list Points of the pyramid. Points are ordered such that the first four points are the four counterclockwise points on the quadrilateral face, and the last point is the apex. Returns ------- pyramid : pyvista.UnstructuredGrid Examples -------- >>> import pyvista >>> pointa = [1.0, 1.0, 1.0] >>> pointb = [-1.0, 1.0, 1.0] >>> pointc = [-1.0, -1.0, 1.0] >>> pointd = [1.0, -1.0, 1.0] >>> pointe = [0.0, 0.0, 0.0] >>> pyramid = pyvista.Pyramid([pointa, pointb, pointc, pointd, pointe]) >>> pyramid.plot() # doctest:+SKIP """ if len(points) != 5: raise TypeError('Points must be given as length 5 np.ndarray or list') check_valid_vector(points[0], 'points[0]') check_valid_vector(points[1], 'points[1]') check_valid_vector(points[2], 'points[2]') check_valid_vector(points[3], 'points[3]') check_valid_vector(points[4], 'points[4]') pyramid = _vtk.vtkPyramid() pyramid.GetPointIds().SetId(0, 0) pyramid.GetPointIds().SetId(1, 1) pyramid.GetPointIds().SetId(2, 2) pyramid.GetPointIds().SetId(3, 3) pyramid.GetPointIds().SetId(4, 4) ug = _vtk.vtkUnstructuredGrid() ug.SetPoints(pyvista.vtk_points(np.array(points), False)) ug.InsertNextCell(pyramid.GetCellType(), pyramid.GetPointIds()) return pyvista.wrap(ug)
def Triangle(points=None): """Create a triangle defined by 3 points. Parameters ---------- points : sequence, optional Points of the triangle. Defaults to a right isosceles triangle (see example). Returns ------- pyvista.PolyData Triangle mesh. Examples -------- >>> import pyvista >>> pointa = [0, 0, 0] >>> pointb = [1, 0, 0] >>> pointc = [0.5, 0.707, 0] >>> triangle = pyvista.Triangle([pointa, pointb, pointc]) >>> triangle.plot(show_edges=True, line_width=5) """ if points is None: points = [[0, 0, 0], [1, 0, 0], [0.5, 0.5**0.5, 0]] if len(points) != 3: raise TypeError('Points must be given as length 3 np.ndarray or list') check_valid_vector(points[0], 'points[0]') check_valid_vector(points[1], 'points[1]') check_valid_vector(points[2], 'points[2]') cells = np.array([[3, 0, 1, 2]]) return pyvista.wrap(pyvista.PolyData(points, cells))
def Rectangle(points=None): """Create a rectangle defined by 4 points. Parameters ---------- points : sequence, optional Points of the rectangle. Defaults to a simple example. Returns ------- pyvista.PolyData Rectangle mesh. Examples -------- >>> import pyvista >>> pointa = [1.0, 0.0, 0.0] >>> pointb = [1.0, 1.0, 0.0] >>> pointc = [0.0, 1.0, 0.0] >>> pointd = [0.0, 0.0, 0.0] >>> rectangle = pyvista.Rectangle([pointa, pointb, pointc, pointd]) >>> rectangle.plot(show_edges=True, line_width=5) """ if points is None: points = [[1.0, 0.0, 0.0], [1.0, 1.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 0.0]] if len(points) != 4: raise TypeError('Points must be given as length 4 np.ndarray or list') check_valid_vector(points[0], 'points[0]') check_valid_vector(points[1], 'points[1]') check_valid_vector(points[2], 'points[2]') check_valid_vector(points[3], 'points[3]') cells = np.array([[4, 0, 1, 2, 3]]) return pyvista.wrap(pyvista.PolyData(points, cells))
def CircularArc(pointa, pointb, center, resolution=100, normal=None, polar=None, angle=None, negative=False): """Create a circular arc defined by two endpoints and a center. The number of segments composing the polyline is controlled by setting the object resolution. Alternatively, one can use a better API (that does not allow for inconsistent nor ambiguous inputs), using a starting point (polar vector, measured from the arc's center), a normal to the plane of the arc, and an angle defining the arc length. Parameters ---------- pointa : np.ndarray or list Position of the first end point. pointb : np.ndarray or list Position of the other end point. center : np.ndarray or list Center of the circle that defines the arc. resolution : int, optional The number of segments of the polyline that draws the arc. Resolution of 1 will just create a line. normal : np.ndarray or list The normal vector to the plane of the arc. By default it points in the positive Z direction. polar : np.ndarray or list (starting point of the arc). By default it is the unit vector in the positive x direction. Note: This is only used when normal has been input. angle : float Arc length (in degrees), beginning at the polar vector. The direction is counterclockwise by default; a negative value draws the arc in the clockwise direction. Note: This is only used when normal has been input. negative : bool, optional By default the arc spans the shortest angular sector point1 and point2. By setting this to true, the longest angular sector is used instead (i.e. the negative coterminal angle to the shortest one). This is only used when normal has not been input Examples -------- Quarter arc centered at the origin in the xy plane >>> import pyvista >>> arc = pyvista.CircularArc([-1, 0, 0], [0, 1, 0], [0, 0, 0]) >>> pl = pyvista.Plotter() >>> _ = pl.add_mesh(arc, color='k', line_width=4) >>> _ = pl.show_bounds(location='all') >>> _ = pl.view_xy() >>> pl.show() # doctest:+SKIP Quarter arc centered at the origin in the xz plane >>> arc = pyvista.CircularArc([-1, 0, 0], [1, 0, 0], [0, 0, 0], normal=[0, 0, 1]) >>> arc.plot() # doctest:+SKIP """ check_valid_vector(pointa, 'pointa') check_valid_vector(pointb, 'pointb') check_valid_vector(center, 'center') # fix half-arc bug: if a half arc travels directly through the # center point, it becomes a line pointb = list(pointb) pointb[0] -= 1E-10 pointb[1] -= 1E-10 arc = vtk.vtkArcSource() arc.SetPoint1(*pointa) arc.SetPoint2(*pointb) arc.SetCenter(*center) arc.SetResolution(resolution) arc.SetNegative(negative) if normal is not None: arc.UseNormalAndAngleOn() check_valid_vector(normal, 'normal') arc.SetNormal(*normal) if polar is not None: check_valid_vector(polar, 'polar') arc.SetPolarVector(*polar) if angle is not None: arc.SetAngle(angle) arc.Update() return pyvista.wrap(arc.GetOutput())
def test_check_valid_vector(): with pytest.raises(TypeError, match="length three"): check_valid_vector([0, 1]) check_valid_vector([0, 1, 2])
def CircularArcFromNormal(center, resolution=100, normal=None, polar=None, angle=None): """Create a circular arc defined by normal to the plane of the arc, and an angle. The number of segments composing the polyline is controlled by setting the object resolution. Parameters ---------- center : np.ndarray or list Center of the circle that defines the arc. resolution : int, optional The number of segments of the polyline that draws the arc. Resolution of 1 will just create a line. normal : np.ndarray or list, optional The normal vector to the plane of the arc. By default it points in the positive Z direction. polar : np.ndarray or list, optional Starting point of the arc in polar coordinates. By default it is the unit vector in the positive x direction. angle : float, optional Arc length (in degrees) beginning at the polar vector. The direction is counterclockwise. By default it is 360. Examples -------- Quarter arc centered at the origin in the xy plane. >>> import pyvista >>> normal = [0, 0, 1] >>> polar = [-1, 0, 0] >>> arc = pyvista.CircularArcFromNormal([0, 0, 0], normal=normal, polar=polar) >>> pl = pyvista.Plotter() >>> _ = pl.add_mesh(arc, color='k', line_width=4) >>> _ = pl.show_bounds(location='all') >>> _ = pl.view_xy() >>> pl.show() # doctest:+SKIP """ check_valid_vector(center, 'center') if normal is None: normal = [0, 0, 1] if polar is None: polar = [1, 0, 0] if angle is None: angle = 90.0 arc = _vtk.vtkArcSource() arc.SetCenter(*center) arc.SetResolution(resolution) arc.UseNormalAndAngleOn() check_valid_vector(normal, 'normal') arc.SetNormal(*normal) check_valid_vector(polar, 'polar') arc.SetPolarVector(*polar) assert np.allclose(np.array(arc.GetPolarVector()), np.array(polar)) arc.SetAngle(angle) arc.Update() angle = np.deg2rad(arc.GetAngle()) arc = pyvista.wrap(arc.GetOutput()) # Compute distance of every point along circular arc center = np.array(center) radius = np.sqrt(np.sum((arc.points[0] - center)**2, axis=0)) angles = np.arange(0.0, 1.0 + 1.0/resolution, 1.0/resolution) * angle arc['Distance'] = radius * angles return arc
def CircularArc(pointa, pointb, center, resolution=100, negative=False): """Create a circular arc defined by two endpoints and a center. The number of segments composing the polyline is controlled by setting the object resolution. Parameters ---------- pointa : np.ndarray or list Position of the first end point. pointb : np.ndarray or list Position of the other end point. center : np.ndarray or list Center of the circle that defines the arc. resolution : int, optional The number of segments of the polyline that draws the arc. Resolution of 1 will just create a line. negative : bool, optional By default the arc spans the shortest angular sector between ``pointa`` and ``pointb``. By setting this to ``True``, the longest angular sector is used instead (i.e. the negative coterminal angle to the shortest one). Examples -------- Create a quarter arc centered at the origin in the xy plane. >>> import pyvista >>> arc = pyvista.CircularArc([-1, 0, 0], [0, 1, 0], [0, 0, 0]) >>> pl = pyvista.Plotter() >>> _ = pl.add_mesh(arc, color='k', line_width=4) >>> _ = pl.show_bounds(location='all') >>> _ = pl.view_xy() >>> pl.show() # doctest:+SKIP """ check_valid_vector(pointa, 'pointa') check_valid_vector(pointb, 'pointb') check_valid_vector(center, 'center') if not np.isclose( np.linalg.norm(np.array(pointa) - np.array(center)), np.linalg.norm(np.array(pointb) - np.array(center)), ): raise ValueError("pointa and pointb are not equidistant from center") # fix half-arc bug: if a half arc travels directly through the # center point, it becomes a line pointb = list(pointb) pointb[0] -= 1E-10 pointb[1] -= 1E-10 arc = _vtk.vtkArcSource() arc.SetPoint1(*pointa) arc.SetPoint2(*pointb) arc.SetCenter(*center) arc.SetResolution(resolution) arc.SetNegative(negative) arc.Update() angle = np.deg2rad(arc.GetAngle()) arc = pyvista.wrap(arc.GetOutput()) # Compute distance of every point along circular arc center = np.array(center) radius = np.sqrt(np.sum((arc.points[0]-center)**2, axis=0)) angles = np.arange(0.0, 1.0 + 1.0/resolution, 1.0/resolution) * angle arc['Distance'] = radius * angles return arc
def PlatonicSolid(kind='tetrahedron', radius=1.0, center=(0.0, 0.0, 0.0)): """Create a Platonic solid of a given size. Parameters ---------- kind : str or int, optional The kind of Platonic solid to create. Either the name of the polyhedron or an integer index: * ``'tetrahedron'`` or ``0`` * ``'cube'`` or ``1`` * ``'octahedron'`` or ``2`` * ``'icosahedron'`` or ``3`` * ``'dodecahedron'`` or ``4`` radius : float, optional The radius of the circumscribed sphere for the solid to create. center : sequence, optional Three-length sequence defining the center of the solid to create. Returns ------- pyvista.PolyData One of the five Platonic solids. Cell scalars are defined that assign integer labels to each face (with array name ``"FaceIndex"``). Examples -------- Create and plot a dodecahedron. >>> import pyvista >>> dodeca = pyvista.PlatonicSolid('dodecahedron') >>> dodeca.plot(categories=True) See :ref:`platonic_example` for more examples using this filter. """ kinds = { 'tetrahedron': 0, 'cube': 1, 'octahedron': 2, 'icosahedron': 3, 'dodecahedron': 4, } if isinstance(kind, str): if kind not in kinds: raise ValueError(f'Invalid Platonic solid kind "{kind}".') kind = kinds[kind] elif isinstance(kind, int) and kind not in range(5): raise ValueError(f'Invalid Platonic solid index "{kind}".') elif not isinstance(kind, int): raise ValueError('Invalid Platonic solid index type ' f'"{type(kind).__name__}".') check_valid_vector(center, 'center') solid = _vtk.vtkPlatonicSolidSource() solid.SetSolidType(kind) solid.Update() solid = pyvista.wrap(solid.GetOutput()) solid.scale(radius) solid.points += np.asanyarray(center) - solid.center # rename and activate cell scalars cell_data = solid.get_array(0) solid.clear_data() solid.cell_data['FaceIndex'] = cell_data return solid