Replaced Axis.as_infinite_edge with Edge __init__ method Issue #648

This commit is contained in:
gumyr 2024-06-24 13:47:52 -04:00
parent b40bcf9a24
commit ce20991745
3 changed files with 107 additions and 107 deletions

View file

@ -37,6 +37,8 @@ from __future__ import annotations
import copy
import json
import logging
import numpy as np
from math import degrees, pi, radians
from typing import (
Any,
@ -798,9 +800,31 @@ class Axis(metaclass=AxisMeta):
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)

View file

@ -2570,7 +2570,7 @@ class Shape(NodeMixin):
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:
@ -2594,7 +2594,7 @@ class Shape(NodeMixin):
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):
@ -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)
@ -4513,14 +4584,10 @@ class Edge(Mixin1D, 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]:
@ -8665,98 +8732,3 @@ class SkipClean:
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

View file

@ -300,7 +300,7 @@ class TestAxis(DirectApiTestCase):
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)
@ -994,7 +994,7 @@ class TestEdge(DirectApiTestCase):
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):
@ -1068,6 +1068,10 @@ class TestEdge(DirectApiTestCase):
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):