Skip to content

Commit

Permalink
Add the arc shape. (#81)
Browse files Browse the repository at this point in the history
Co-authored-by: Maxjrey <113357288+Maxjrey@users.noreply.github.com>
Co-authored-by: Roberto Pastor Muela <roberto.pastormuela@ansys.com>
  • Loading branch information
3 people committed Sep 12, 2022
1 parent 7234632 commit 85f61a1
Show file tree
Hide file tree
Showing 3 changed files with 204 additions and 0 deletions.
152 changes: 152 additions & 0 deletions src/ansys/geometry/core/shapes/arc.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
"""``ArcSketch`` class module."""
from typing import List, Optional

import numpy as np

from ansys.geometry.core.math import Point, Vector
from ansys.geometry.core.math.vector import UnitVector
from ansys.geometry.core.shapes.base import BaseShape
from ansys.geometry.core.typing import Real


class Arc(BaseShape):
"""A class for modeling arcs."""

def __init__(
self,
origin: Point,
start_point: Point,
end_point: Point,
):
"""Initializes the arc shape.
Parameters
----------
origin : Point
A :class:``Point`` representing the center of the arc.
start_point : Point
A :class:``Point`` representing the start of the arc.
end_points : Point
A :class:``Point`` representing the end of the arc.
"""
# Verify both points are not the same
if start_point == end_point:
raise ValueError("Start and end points must be different.")
if origin == start_point:
raise ValueError("Center and start points must be different.")
if origin == end_point:
raise ValueError("Center and end points must be different.")

self._origin, self._start_point, self._end_point = (origin, start_point, end_point)

self._start_vector = Vector.from_points(self._origin, self._start_point)
self._end_vector = Vector.from_points(self._origin, self._end_point)

super().__init__(
origin,
dir_1=UnitVector(self._start_vector / self._start_vector.norm),
dir_2=UnitVector(self._end_vector / self._end_vector.norm),
)

self._radius = self._start_vector.norm

@property
def start_point(self) -> Point:
"""Return the start of the arc line.
Returns
-------
Point
Starting point of the arc line.
"""
return self._start_point

@property
def end_point(self) -> Point:
"""Return the end of the arc line.
Returns
-------
Point
Ending point of the arc line.
"""
return self._end_point

@property
def radius(self) -> Real:
"""The radius of the arc.
Returns
-------
Real
The radius of the arc.
"""
return self._radius

@property
def angle(self) -> Real:
"""The angle of the arc.
Returns
-------
Real
The angle of the arc.
"""

self._angle = np.arccos(self._start_vector * self._end_vector / self.radius**2)
return self._angle

@property
def length(self) -> Real:
"""Return the length of the arc.
Returns
-------
Real
The length of the arc.
"""
return 2 * np.pi * self.radius * self.angle

@property
def sector_area(self) -> Real:
"""Return the area of the sector of the arc.
Returns
-------
Real
The area of the sector of the arc.
"""
return self.radius**2 * self.angle / 2

def local_points(self, num_points: Optional[int] = 100) -> List[Point]:
"""Returns al list containing all the points belonging to the shape.
Parameters
----------
num_points : int
Desired number of points belonging to the shape.
Returns
-------
List[Point]
A list of points representing the shape.
"""
theta = np.linspace(0, self.angle, num_points)
return [
Point(
[
self.radius * np.cos(ang) + self.origin[0],
self.radius * np.sin(ang) + self.origin[1],
self.origin[2],
]
)
for ang in theta
]
28 changes: 28 additions & 0 deletions src/ansys/geometry/core/sketch.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from ansys.geometry.core.math import UNIT_VECTOR_X, UNIT_VECTOR_Y, ZERO_VECTOR3D
from ansys.geometry.core.math.point import Point
from ansys.geometry.core.math.vector import UnitVector, Vector
from ansys.geometry.core.shapes.arc import Arc
from ansys.geometry.core.shapes.base import BaseShape
from ansys.geometry.core.shapes.circle import Circle
from ansys.geometry.core.shapes.ellipse import Ellipse
Expand Down Expand Up @@ -232,3 +233,30 @@ def draw_polygon(
polygon = Polygon(radius, sides, origin, dir_1=dir_1, dir_2=dir_2)
self.append_shape(polygon)
return polygon

def draw_arc(
self,
center: Point,
start_point: Point,
end_point: Point,
):
"""Create an arc shape on the sketch.
Parameters
----------
center : Point
A :class:``Point`` representing the center of the arc.
start_point : Point
A :class:``Point`` representing the start of the shape.
end_points : Point
A :class:``Point`` representing the end of the shape.
Returns
-------
Arc
An object representing the arc added to the sketch.
"""
arc = Arc(center, start_point, end_point)
self.append_shape(arc)
return arc
24 changes: 24 additions & 0 deletions tests/test_shapes.py
Original file line number Diff line number Diff line change
Expand Up @@ -249,3 +249,27 @@ def test_errors_segment():
match="Parameters 'origin' and 'end' have the same values. No segment can be created.",
):
Segment(Point([10, 20, 30]), Point([10, 20, 30]))


def test_create_arc():
"""Test arc shape creation in a sketch."""

# Create a Sketch instance
sketch = Sketch()

# Draw an arc in previous sketch
origin = Point([1, 1, 0], unit=UNITS.meter)
start_point = Point([1, 3, 0], unit=UNITS.meter)
end_point = Point([3, 1, 0], unit=UNITS.meter)
arc = sketch.draw_arc(origin, start_point, end_point)

# Check attributes are expected ones
assert_allclose(arc.radius, 2)
assert_allclose(arc.sector_area, np.pi)
assert_allclose(arc.length, 2 * np.pi**2)

# Check points are expected ones
local_points = arc.local_points(num_points=5)
assert abs(all(local_points[0] - Point([3, 1, 0]))) <= DOUBLE_EPS
assert abs(all(local_points[1] - Point([2.8477, 1.7653, 0]))) <= DOUBLE_EPS
assert abs(all(local_points[4] - Point([1, 3, 0]))) <= DOUBLE_EPS

0 comments on commit 85f61a1

Please sign in to comment.