Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add polygon shape #65

Merged
merged 31 commits into from
Sep 8, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
6f10b26
initial commit of polygon shape
Revathyvenugopal162 Sep 7, 2022
0490666
Merge branch 'main' into feat/add-polygon-shape
Revathyvenugopal162 Sep 7, 2022
b975266
Add properties to polygon
Revathyvenugopal162 Sep 7, 2022
b31fc31
initialise polygon tests
Revathyvenugopal162 Sep 7, 2022
bbdaa17
Modify polygon test
Revathyvenugopal162 Sep 7, 2022
a9b9226
Modify polygon points
Revathyvenugopal162 Sep 7, 2022
a9a197d
Modify polygon vertices
Revathyvenugopal162 Sep 7, 2022
df02379
Modify polygon vertices and test
Revathyvenugopal162 Sep 7, 2022
2cad08a
Apply suggestions from code review
Revathyvenugopal162 Sep 7, 2022
9e231a6
Modify type
Revathyvenugopal162 Sep 7, 2022
d87d94e
Merge branch 'feat/add-polygon-shape' of https://github.com/pyansys/p…
Revathyvenugopal162 Sep 7, 2022
5df61f7
Modify docstrings
Revathyvenugopal162 Sep 7, 2022
5d9d4c0
Apply suggestions from code review
Revathyvenugopal162 Sep 7, 2022
b82ba6b
Update tests/test_shapes.py
Revathyvenugopal162 Sep 7, 2022
db9180b
Modify attributes
Revathyvenugopal162 Sep 7, 2022
db391a0
Merge branch 'feat/add-polygon-shape' of https://github.com/pyansys/p…
Revathyvenugopal162 Sep 7, 2022
8ba4915
Merge branch 'main' into feat/add-polygon-shape
Revathyvenugopal162 Sep 8, 2022
d9dc99d
Apply suggestions from code review
Revathyvenugopal162 Sep 8, 2022
106edf3
Update src/ansys/geometry/core/shapes/polygon.py
Revathyvenugopal162 Sep 8, 2022
9e5a51b
Modify shapes package by removing implicit names
Revathyvenugopal162 Sep 8, 2022
8e607f7
Merge branch 'main' into feat/add-polygon-shape
Revathyvenugopal162 Sep 8, 2022
47cf5a1
Check for circle radius
Revathyvenugopal162 Sep 8, 2022
0f9572c
Merge branch 'main' into feat/add-polygon-shape
Revathyvenugopal162 Sep 8, 2022
717fad3
Apply suggestions from code review
Revathyvenugopal162 Sep 8, 2022
aaec665
Remove from radius method
Revathyvenugopal162 Sep 8, 2022
e866fe0
Merge branch 'feat/add-polygon-shape' of https://github.com/pyansys/p…
Revathyvenugopal162 Sep 8, 2022
fc1f7bb
Apply code sugesstion by @RobPasMe
Revathyvenugopal162 Sep 8, 2022
63e8fc6
Revert "Apply code suggession by @RobPasMue"
Revathyvenugopal162 Sep 8, 2022
c4f0a4c
return local points as Point3D
Revathyvenugopal162 Sep 8, 2022
bd4b1e4
return local points as Point3D in circle and elipse
Revathyvenugopal162 Sep 8, 2022
a4fb94f
Add assertion for local points
Revathyvenugopal162 Sep 8, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion src/ansys/geometry/core/shapes/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,6 @@
from ansys.geometry.core.shapes.circle import Circle
from ansys.geometry.core.shapes.ellipse import Ellipse
from ansys.geometry.core.shapes.line import Line, Segment
from ansys.geometry.core.shapes.polygon import Polygon

__all__ = ["BaseShape", "Circle", "Ellipse", "Line", "Segment"]
__all__ = ["BaseShape", "Circle", "Ellipse", "Line", "Polygon", "Segment"]
37 changes: 8 additions & 29 deletions src/ansys/geometry/core/shapes/circle.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ def __init__(
):
"""Initializes the circle shape."""
super().__init__(origin, dir_1=dir_1, dir_2=dir_2, is_closed=True)
if radius <= 0:
raise ValueError("Radius must be a real positive value.")
self._radius = radius

@property
Expand All @@ -51,17 +53,6 @@ def radius(self) -> Real:
"""
return self._radius

@property
def r(self) -> Real:
"""The radius of the circle.

Returns
-------
Real
The radius of the circle.
"""
return self.radius

@property
def diameter(self) -> Real:
"""The diameter of the circle.
Expand All @@ -71,18 +62,7 @@ def diameter(self) -> Real:
Real
The diameter of the circle.
"""
return 2 * self.r

@property
def d(self) -> Real:
"""The diameter of the circle.

Returns
-------
Real
The diameter of the circle.
"""
return self.diameter
return 2 * self.radius

@property
def perimeter(self) -> Real:
Expand All @@ -93,7 +73,7 @@ def perimeter(self) -> Real:
Real
The perimeter of the circle.
"""
return 2 * np.pi * self.r
return 2 * np.pi * self.radius

@property
def area(self) -> Real:
Expand All @@ -104,7 +84,7 @@ def area(self) -> Real:
Real
The area of the circle.
"""
return np.pi * self.r**2
return np.pi * self.radius**2

def local_points(self, num_points: Optional[int] = 100) -> List[Point3D]:
"""Returns a list containing all the points belonging to the shape.
Expand All @@ -122,10 +102,9 @@ def local_points(self, num_points: Optional[int] = 100) -> List[Point3D]:
A list of points representing the shape.
"""
theta = np.linspace(0, 2 * np.pi, num_points)
x_local = self.r * np.cos(theta)
y_local = self.r * np.sin(theta)
z_local = np.zeros(num_points)
return [x_local, y_local, z_local]
return [
Point3D([self.radius * np.cos(ang), self.radius * np.sin(ang), 0.0]) for ang in theta
]

@classmethod
def from_radius(
Expand Down
79 changes: 10 additions & 69 deletions src/ansys/geometry/core/shapes/ellipse.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,17 +56,6 @@ def semi_major_axis(self) -> Real:
"""
return self._semi_major_axis

@property
def a(self) -> Real:
"""Return the semi-major axis of the ellipse.

Returns
-------
Real
Semi-major axis of the ellipse.
"""
return self.semi_major_axis

@property
def semi_minor_axis(self) -> Real:
"""Return the semi-minor axis of the ellipse.
Expand All @@ -78,17 +67,6 @@ def semi_minor_axis(self) -> Real:
"""
return self._semi_minor_axis

@property
def b(self) -> Real:
"""Return the semi-minor axis of the ellipse.

Returns
-------
Real
Semi-minor axis of the ellipse.
"""
return self.semi_minor_axis

@property
def eccentricity(self) -> Real:
"""Return the eccentricity of the ellipse.
Expand All @@ -98,24 +76,13 @@ def eccentricity(self) -> Real:
Real
Eccentricity of the ellipse.
"""
ecc = (self.a**2 - self.b**2) ** 0.5 / self.a
ecc = (self.semi_major_axis**2 - self.semi_minor_axis**2) ** 0.5 / self.semi_major_axis
if ecc == 1:
raise ValueError("The curve defined is a parabola not an ellipse.")
elif ecc > 1:
raise ValueError("The curve defined is an hyperbola not an ellipse.")
return ecc

@property
def ecc(self) -> Real:
"""Return the eccentricity of the ellipse.

Returns
-------
Real
Eccentricity of the ellipse.
"""
return self.eccentricity

@property
def linear_eccentricity(self) -> Real:
"""Return the linear eccentricity of the ellipse.
Expand All @@ -129,22 +96,7 @@ def linear_eccentricity(self) -> Real:
-----
The linear eccentricity is the distance from the center to the focus.
"""
return (self.a**2 - self.b**2) ** 0.5

@property
def c(self) -> Real:
"""Return the linear eccentricity of the ellipse.

Returns
-------
Real
Linear eccentricity of the ellipse.

Notes
-----
The linear eccentricity is the distance from the center to the focus.
"""
return self.linear_eccentricity
return (self.semi_major_axis**2 - self.semi_minor_axis**2) ** 0.5

@property
def semi_latus_rectum(self) -> Real:
Expand All @@ -155,18 +107,7 @@ def semi_latus_rectum(self) -> Real:
Real
Semi-latus rectum of the ellipse.
"""
return self.b**2 / self.a

@property
def l(self) -> Real:
"""Return the semi-latus rectum of the ellipse.

Returns
-------
Real
Semi-latus rectum of the ellipse.
"""
return self.semi_latus_rectum
return self.semi_minor_axis**2 / self.semi_major_axis

@property
def perimeter(self) -> Real:
Expand All @@ -181,8 +122,8 @@ def perimeter(self) -> Real:
def integrand(theta, ecc):
return np.sqrt(1 - (ecc * np.sin(theta)) ** 2)

I, _ = quad(integrand, 0, np.pi / 2, args=(self.ecc,))
return 4 * self.a * I
I, _ = quad(integrand, 0, np.pi / 2, args=(self.eccentricity,))
return 4 * self.semi_major_axis * I

@property
def area(self) -> Real:
Expand All @@ -193,7 +134,7 @@ def area(self) -> Real:
Real
The area of the ellipse.
"""
return np.pi * self.a * self.b
return np.pi * self.semi_major_axis * self.semi_minor_axis

def local_points(self, num_points: Optional[int] = 100) -> List[Point3D]:
"""Returns a list containing all the points belonging to the shape.
Expand All @@ -209,10 +150,10 @@ def local_points(self, num_points: Optional[int] = 100) -> List[Point3D]:
A list of points representing the shape.
"""
theta = np.linspace(0, 2 * np.pi, num_points)
x_local = self.a * np.cos(theta)
y_local = self.b * np.sin(theta)
z_local = np.zeros(num_points)
return [x_local, y_local, z_local]
return [
Point3D([self.semi_major_axis * np.cos(ang), self.semi_minor_axis * np.sin(ang), 0.0])
for ang in theta
]

@classmethod
def from_axes(
Expand Down
144 changes: 144 additions & 0 deletions src/ansys/geometry/core/shapes/polygon.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
"""``Polygon`` class module."""

from typing import List, Optional

import numpy as np

from ansys.geometry.core.math import UNIT_VECTOR_X, UNIT_VECTOR_Y
from ansys.geometry.core.math.point import Point3D
from ansys.geometry.core.math.vector import UnitVector3D
from ansys.geometry.core.shapes.base import BaseShape
from ansys.geometry.core.typing import Real


class Polygon(BaseShape):
"""A class for modeling polygon.

Parameters
----------
radius : Real
The inradius(apothem) of the polygon.
sides : int
Number of sides of the polygon.
origin : Point3D
A :class:``Point3D`` representing the origin of the shape.
By default, [0, 0, 0].
dir_1 : UnitVector3D
A :class:``UnitVector3D`` representing the first fundamental direction
of the reference plane where the shape is contained.
By default, ``UNIT_VECTOR_X``.
dir_2 : UnitVector3D
A :class:``UnitVector3D`` representing the second fundamental direction
of the reference plane where the shape is contained.
By default, ``UNIT_VECTOR_Y``.
"""

def __init__(
self,
inner_radius: Real,
sides: int,
origin: Point3D,
Revathyvenugopal162 marked this conversation as resolved.
Show resolved Hide resolved
dir_1: Optional[UnitVector3D] = UNIT_VECTOR_X,
dir_2: Optional[UnitVector3D] = UNIT_VECTOR_Y,
):
"""Initializes the polygon shape."""
super().__init__(origin, dir_1=dir_1, dir_2=dir_2, is_closed=True)

if inner_radius <= 0:
raise ValueError("Radius must be a real positive value.")
self._radius = inner_radius
# Verify that the number of sides is valid with preferred range
if sides < 3:
raise ValueError("The minimum number of sides to construct a polygon should be 3.")
# TODO : raise warning if the number of sides greater than 64
# it cannot be handled server side
self._n_sides = sides

@property
def inner_radius(self) -> Real:
"""The inradius(apothem) of the polygon.

Returns
-------
Real
The inradius(apothem) of the polygon.

"""
return self._radius

@property
def n_sides(self) -> int:
"""The number of sides of the polygon.

Returns
-------
int
The sides of the polygon.

"""
return self._n_sides

@property
def length(self) -> Real:
"""The side length of the polygon.

Returns
-------
int
The side length of the polygon.

"""
return 2 * self.inner_radius * np.tan(np.pi / self.n_sides)

@property
def outer_radius(self) -> Real:
"""The outer radius of the polygon.

Returns
-------
int
The outer radius of the polygon.

"""
return self.inner_radius / np.cos(np.pi / self.n_sides)

@property
def perimeter(self) -> Real:
"""Return the perimeter of the polygon.

Returns
-------
Real
The perimeter of the polygon.

"""
return self.n_sides * self.length

@property
def area(self) -> Real:
"""Return the area of the polygon.

Returns
-------
Real
The area of the polygon.

"""
return (self.inner_radius * self.perimeter) / 2

def local_points(self) -> List[Point3D]:
RobPasMue marked this conversation as resolved.
Show resolved Hide resolved
"""Returns a list containing all the vertices of the polygon.

Vertices are given in the local space.

Returns
-------
list[Point3D]
A list of vertices representing the shape.

"""
theta = np.linspace(0, 2 * np.pi, self.n_sides + 1)
RobPasMue marked this conversation as resolved.
Show resolved Hide resolved
return [
Point3D([self.outer_radius * np.cos(ang), self.outer_radius * np.sin(ang), 0.0])
for ang in theta
]
Loading