Source code for shapepy.bool2d.primitive

"""
This file contains functions to create primitive shapes such as:
- Regular polygons
- Circle
- Square

"""

from __future__ import annotations

import math
from typing import Tuple

import numpy as np

from ..geometry.factory import FactoryJordan
from ..geometry.point import Point2D
from ..loggers import debug
from ..tools import Is, To
from .base import EmptyShape, WholeShape
from .shape import SimpleShape


[docs] class Primitive: """ Primitive class with functions to create classical shapes such as `circle`, `triangle`, `square`, `regular_polygon` and a generic `polygon` .. note:: This class also contains ``empty`` and ``whole`` instances to easy access """ empty = EmptyShape() whole = WholeShape()
[docs] @staticmethod @debug("shapepy.bool2d.primitive") def regular_polygon( nsides: int, radius: float = 1, center: Point2D = (0, 0) ) -> SimpleShape: """ Creates a regular polygon Parameters ---------- nsides : int Number of sides of regular polygon, >= 3 radius : float, default: 1 Radius of the external circle that contains the polygon. center : Point2D, default: (0, 0) The geometric center of the regular polygon ------------------------------------------- return : SimpleShape The simple shape that represents the regular polygon Example use ----------- >>> from shapepy import Primitive >>> triangle = Primitive.regular_polygon(nsides = 3) .. image:: ../img/primitive/regular3.svg .. image:: ../img/primitive/regular4.svg .. image:: ../img/primitive/regular5.svg """ if not Is.integer(nsides) or nsides < 3: raise ValueError if not Is.finite(radius) or radius <= 0: raise ValueError center = To.point(center) if nsides == 4: vertices = [(radius, 0), (0, radius), (-radius, 0), (0, -radius)] vertices = tuple(center + To.point(vertex) for vertex in vertices) else: vertices = np.empty((nsides, 2), dtype="float64") theta = np.linspace(0, math.tau, nsides, endpoint=False) vertices[:, 0] = radius * np.cos(theta) vertices[:, 1] = radius * np.sin(theta) vertices = tuple(center + To.point(vertex) for vertex in vertices) return Primitive.polygon(vertices)
[docs] @staticmethod @debug("shapepy.bool2d.primitive") def polygon(vertices: Tuple[Point2D]) -> SimpleShape: """ Creates a generic polygon vertices: tuple[Point2D] Vertices of the polygon ------------------------------------------- return : SimpleShape The simple shape that represents the polygon Example use ----------- >>> from shapepy import Primitive >>> vertices = [(1, 0), (0, 1), (-1, 1), (0, -1)] >>> shape = Primitive.polygon(vertices) .. image:: ../img/primitive/diamond.svg """ vertices = tuple(map(To.point, vertices)) jordan_curve = FactoryJordan.polygon(vertices) return SimpleShape(jordan_curve)
[docs] @staticmethod @debug("shapepy.bool2d.primitive") def triangle(side: float = 1, center: Point2D = (0, 0)) -> SimpleShape: """ Create a right triangle Parameters ---------- side : float, default: 1 Width and height of the triangle center : Point2D, default: (0, 0) Position of the vertex of right angle ------------------------------------------- return : SimpleShape The simple shape that represents the triangle Example use ----------- >>> from shapepy import Primitive >>> triangle = Primitive.triangle() .. image:: ../img/primitive/triangle.svg """ center = To.point(center) vertices = [(0, 0), (side, 0), (0, side)] vertices = tuple(center + To.point(vertex) for vertex in vertices) return Primitive.polygon(vertices)
[docs] @staticmethod @debug("shapepy.bool2d.primitive") def square(side: float = 1, center: Point2D = (0, 0)) -> SimpleShape: """ Creates a square with sides aligned with axis Parameters ---------- side : float, default: 1 Side of the square. center : Point2D, default: (0, 0) The geometric center of the square ------------------------------------------- return : SimpleShape The simple shape that represents the square Example use ----------- >>> from shapepy import Primitive >>> square = Primitive.square() .. image:: ../img/primitive/square.svg """ if not Is.finite(side) or side <= 0: raise ValueError center = To.point(center) if Is.integer(side): side = To.rational(side) side /= 2 vertices = [(side, side), (-side, side), (-side, -side), (side, -side)] vertices = [center + To.point(vertex) for vertex in vertices] return Primitive.polygon(vertices)
[docs] @staticmethod @debug("shapepy.bool2d.primitive") def circle( radius: float = 1, center: Point2D = (0, 0), ndivangle: int = 16 ) -> SimpleShape: """ Creates a circle Parameters ---------- radius : float, default: 1 Radius of the circle center : Point2D, default: (0, 0) Center of the circle ndivangle : int, 16 Number of divisions of the circle, minimum 4 ------------------------------------------- return : SimpleShape The simple shape that represents the circle Example use ----------- >>> from shapepy import Primitive >>> circle = Primitive.circle() .. image:: ../img/primitive/positive_circle.svg .. note:: We represent the circle by many quadratic segments. NURBS are not implemented in this code to represent exactly circles. You can choose the number of quadratic terms by changing ``ndivangle``. """ if not Is.finite(radius) or radius <= 0: raise ValueError if not Is.integer(ndivangle) or ndivangle < 4: raise ValueError jordan_curve = FactoryJordan.circle(ndivangle) return SimpleShape(jordan_curve).scale(radius).move(center)