Skip to content

Commit

Permalink
Replaced Axis.as_infinite_edge with Edge __init__ method Issue gumyr#648
Browse files Browse the repository at this point in the history
  • Loading branch information
gumyr committed Jun 24, 2024
1 parent b40bcf9 commit ce20991
Show file tree
Hide file tree
Showing 3 changed files with 107 additions and 107 deletions.
30 changes: 27 additions & 3 deletions src/build123d/geometry.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@
import copy
import json
import logging
import numpy as np

from math import degrees, pi, radians
from typing import (
Any,
Expand Down Expand Up @@ -798,9 +800,31 @@ def intersect(self, *args, **kwargs):
if self.is_coaxial(axis):
return self
else:
pnt = self.as_infinite_edge().intersect(axis.as_infinite_edge())
if pnt is not None:
return Vector(pnt)
# Extract points and directions to numpy arrays
p1 = np.array([*self.position])
d1 = np.array([*self.direction])
p2 = np.array([*axis.position])
d2 = np.array([*axis.direction])

# Compute the cross product of directions
cross_d1_d2 = np.cross(d1, d2)
cross_d1_d2_norm = np.linalg.norm(cross_d1_d2)

if cross_d1_d2_norm < TOLERANCE:
# The directions are parallel
return None

# Solve the system of equations to find the intersection
system_of_equations = np.array([d1, -d2, cross_d1_d2]).T
origin_diff = p2 - p1
try:
t1, t2, _ = np.linalg.solve(system_of_equations, origin_diff)
except np.linalg.LinAlgError:
return None # The lines do not intersect

# Calculate the intersection point
intersection_point = p1 + t1 * d1
return Vector(*intersection_point)

elif plane is not None:
return plane.intersect(self)
Expand Down
176 changes: 74 additions & 102 deletions src/build123d/topology.py
Original file line number Diff line number Diff line change
Expand Up @@ -2570,7 +2570,7 @@ def fuse(self, *to_fuse: Shape, glue: bool = False, tol: float = None) -> Self:
return return_value

def _intersect_with_axis(self, *axes: Axis) -> Shape:
lines = [a.as_infinite_edge() for a in axes]
lines = [Edge(a) for a in axes]
return self.intersect(*lines)

def _intersect_with_plane(self, *planes: Plane) -> Shape:
Expand All @@ -2594,7 +2594,7 @@ def intersect(self, *to_intersect: Union[Shape, Axis, Plane]) -> Shape:
if isinstance(obj, Vector):
objs.append(Vertex(obj))
elif isinstance(obj, Axis):
objs.append(obj.as_infinite_edge())
objs.append(Edge(obj))
elif isinstance(obj, Plane):
objs.append(Face.make_plane(obj))
elif isinstance(obj, Location):
Expand Down Expand Up @@ -4401,6 +4401,77 @@ class Edge(Mixin1D, Shape):

_dim = 1

@overload
def __init__(
self,
obj: TopoDS_Shape,
label: str = "",
color: Color = None,
parent: Compound = None,
):
"""Build an Edge from an OCCT TopoDS_Shape/TopoDS_Edge
Args:
obj (TopoDS_Shape, optional): OCCT Face.
label (str, optional): Defaults to ''.
color (Color, optional): Defaults to None.
parent (Compound, optional): assembly parent. Defaults to None.
"""

@overload
def __init__(
self,
axis: Axis,
label: str = "",
color: Color = None,
parent: Compound = None,
):
"""Build an infinite Edge from an Axis
Args:
axis (Axis): Axis to be converted to an infinite Edge
label (str, optional): Defaults to ''.
color (Color, optional): Defaults to None.
parent (Compound, optional): assembly parent. Defaults to None.
"""

def __init__(self, *args, **kwargs):
axis, obj, label, color, parent = (None,) * 5

if args:
l_a = len(args)
if isinstance(args[0], TopoDS_Shape):
obj, label, color, parent = args[:4] + (None,) * (4 - l_a)
elif isinstance(args[0], Axis):
axis, label, color, parent = args[:4] + (None,) * (4 - l_a)

unknown_args = ", ".join(
set(kwargs.keys()).difference(["axis", "obj", "label", "color", "parent"])
)
if unknown_args:
raise ValueError(f"Unexpected argument(s) {unknown_args}")

obj = kwargs.get("obj", obj)
axis = kwargs.get("axis", axis)
label = kwargs.get("label", label)
color = kwargs.get("color", color)
parent = kwargs.get("parent", parent)

if axis is not None:
obj = BRepBuilderAPI_MakeEdge(
Geom_Line(
axis.position.to_pnt(),
axis.direction.to_dir(),
)
).Edge()

super().__init__(
obj=obj,
label="" if label is None else label,
color=color,
parent=parent,
)

def _geom_adaptor(self) -> BRepAdaptor_Curve:
""" """
return BRepAdaptor_Curve(self.wrapped)
Expand Down Expand Up @@ -4513,14 +4584,10 @@ def _intersect_with_axis(self, axis: Axis) -> Shape:

# Find Edge/Edge overlaps
intersect_op = BRepAlgoAPI_Common()
edge_intersections = self._bool_op(
(self,), (axis.as_infinite_edge(),), intersect_op
).edges()
edge_intersections = self._bool_op((self,), (Edge(axis),), intersect_op).edges()

return Compound(vertex_intersections + edge_intersections)

# return self._intersect_with_edge(axis.as_infinite_edge())

def find_intersection_points(
self, edge: Union[Axis, Edge] = None, tolerance: float = TOLERANCE
) -> ShapeList[Vector]:
Expand Down Expand Up @@ -8665,98 +8732,3 @@ def __enter__(self):

def __exit__(self, exception_type, exception_value, traceback):
SkipClean.clean = True


# Monkey-patched Axis and Plane methods that take Shapes as arguments
def _axis_as_infinite_edge(self: Axis) -> Edge:
"""return an edge with infinite length along self"""
return Edge(
BRepBuilderAPI_MakeEdge(
Geom_Line(
self.position.to_pnt(),
self.direction.to_dir(),
)
).Edge()
)


Axis.as_infinite_edge = _axis_as_infinite_edge


# def _axis_intersect(self: Axis, *to_intersect: Union[Shape, Axis, Plane]) -> Shape:
# """axis intersect

# Args:
# to_intersect (sequence of Union[Shape, Axis, Plane]): objects to intersect
# with Axis.

# Returns:
# Shape: result of intersection
# """
# self_i_edge: Edge = self.as_infinite_edge()
# self_as_curve = Geom_Line(self.position.to_pnt(), self.direction.to_dir())

# intersections = []
# for intersector in to_intersect:
# if isinstance(intersector, Axis):
# intersector_as_edge: Edge = intersector.as_infinite_edge()
# distance, point1, _point2 = self_i_edge.distance_to_with_closest_points(
# intersector_as_edge
# )
# if distance <= TOLERANCE:
# intersections.append(Vertex(*point1.to_tuple()))
# elif isinstance(intersector, Plane):
# geom_plane: Geom_Surface = Face.make_plane(intersector)._geom_adaptor()

# # Create a GeomAPI_IntCS object and compute the intersection
# int_cs = GeomAPI_IntCS(self_as_curve, geom_plane)
# # Check if there is an intersection point
# if int_cs.NbPoints() > 0:
# intersections.append(Vertex(*Vector(int_cs.Point(1)).to_tuple()))
# elif isinstance(intersector, Shape):
# intersections.extend(self_i_edge.intersect(intersector))

# return (
# intersections[0]
# if len(intersections) == 1
# else Compound(children=intersections)
# )


# Axis.intersect = _axis_intersect


# def _axis_and(self: Axis, other: Union[Shape, Axis, Plane]) -> Shape:
# """intersect shape with self operator &"""
# return self.intersect(other)


# Axis.__and__ = _axis_and


# def _plane_intersect(self: Plane, *to_intersect: Union[Shape, Axis, Plane]) -> Shape:
# """plane intersect

# Args:
# to_intersect (sequence of Union[Shape, Axis, Plane]): objects to intersect
# with Plane.

# Returns:
# Shape: result of intersection
# """
# self_as_face: Face = Face.make_plane(self)
# intersections = [
# self_as_face.intersect(intersector) for intersector in to_intersect
# ]
# return Compound(children=intersections)


# Plane.intersect = _plane_intersect


# def _plane_and(self: Plane, other: Union[Shape, Axis, Plane]) -> Shape:
# """intersect shape with self operator &"""
# return self.intersect(other)


# Plane.__and__ = _plane_and
8 changes: 6 additions & 2 deletions tests/test_direct_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -300,7 +300,7 @@ def test_axis_reverse_op(self):
self.assertVectorAlmostEquals(axis.direction, (-1, 0, 0), 5)

def test_axis_as_edge(self):
edge = Axis.X.as_infinite_edge()
edge = Edge(Axis.X)
self.assertTrue(isinstance(edge, Edge))
common = (edge & Edge.make_line((0, 0, 0), (1, 0, 0))).edge()
self.assertAlmostEqual(common.length, 1, 5)
Expand Down Expand Up @@ -994,7 +994,7 @@ def test_trim_to_length(self):
self.assertAlmostEqual(e3_trim.length, 7, 5)

a4 = Axis((0, 0, 0), (1, 1, 1))
e4_trim = a4.as_infinite_edge().trim_to_length(0.5, 2)
e4_trim = Edge(a4).trim_to_length(0.5, 2)
self.assertAlmostEqual(e4_trim.length, 2, 5)

def test_bezier(self):
Expand Down Expand Up @@ -1068,6 +1068,10 @@ def test_reverse(self):
e2r = e2.reversed()
self.assertAlmostEqual((e2 @ 0.1).X, -(e2r @ 0.1).X, 5)

def test_init(self):
with self.assertRaises(ValueError):
Edge(direction=(1, 0, 0))


class TestFace(DirectApiTestCase):
def test_make_surface_from_curves(self):
Expand Down

0 comments on commit ce20991

Please sign in to comment.