mirror of
https://github.com/gumyr/build123d.git
synced 2025-12-06 02:30:55 -08:00
Wire.param_at_point improved
This commit is contained in:
parent
a1b20c582d
commit
735f4ffb4d
4 changed files with 46 additions and 21 deletions
|
|
@ -80,7 +80,7 @@ from OCP.BRepBuilderAPI import (
|
|||
BRepBuilderAPI_MakeWire,
|
||||
BRepBuilderAPI_NonManifoldWire,
|
||||
)
|
||||
from OCP.BRepExtrema import BRepExtrema_DistShapeShape
|
||||
from OCP.BRepExtrema import BRepExtrema_DistShapeShape, BRepExtrema_SupportType
|
||||
from OCP.BRepFilletAPI import BRepFilletAPI_MakeFillet2d
|
||||
from OCP.BRepGProp import BRepGProp, BRepGProp_Face
|
||||
from OCP.BRepLib import BRepLib, BRepLib_FindSurface
|
||||
|
|
@ -2266,7 +2266,11 @@ class Edge(Mixin1D, Shape[TopoDS_Edge]):
|
|||
param = projector.LowerDistanceParameter()
|
||||
# Note that for some periodic curves the LowerDistanceParameter might
|
||||
# be outside the given range
|
||||
u_value = ((param - param_min) % param_range) / param_range
|
||||
curve_adaptor = BRepAdaptor_Curve(self.wrapped)
|
||||
if curve_adaptor.IsPeriodic():
|
||||
u_value = ((param - param_min) % curve_adaptor.Period()) / param_range
|
||||
else:
|
||||
u_value = (param - param_min) / param_range
|
||||
# Validate that GeomAPI_ProjectPointOnCurve worked correctly
|
||||
if (self.position_at(u_value) - pnt).length < TOLERANCE:
|
||||
return u_value
|
||||
|
|
@ -3180,14 +3184,46 @@ class Wire(Mixin1D, Shape[TopoDS_Wire]):
|
|||
raise ValueError("Can't find point on empty wire")
|
||||
|
||||
point_on_curve = Vector(point)
|
||||
closest_edge = min(self.edges(), key=lambda e: e.distance_to(point_on_curve))
|
||||
assert closest_edge.wrapped is not None
|
||||
distance_along_wire = (
|
||||
closest_edge.param_at_point(point_on_curve) * closest_edge.length
|
||||
|
||||
separation = self.distance_to(point)
|
||||
if not isclose_b(separation, 0, abs_tol=TOLERANCE):
|
||||
raise ValueError(f"point ({point}) is {separation} from wire")
|
||||
|
||||
extrema = BRepExtrema_DistShapeShape(
|
||||
Vertex(point_on_curve).wrapped, self.wrapped
|
||||
)
|
||||
# Compensate for different directionss
|
||||
# if closest_edge.is_forward ^ self.is_forward: # opposite directions
|
||||
# distance_along_wire = closest_edge.length - distance_along_wire
|
||||
extrema.Perform()
|
||||
if not extrema.IsDone() or extrema.NbSolution() == 0:
|
||||
raise ValueError("point is not on Wire")
|
||||
|
||||
supp_type = extrema.SupportTypeShape2(1)
|
||||
|
||||
if supp_type == BRepExtrema_SupportType.BRepExtrema_IsOnEdge:
|
||||
closest_topods_edge = downcast(extrema.SupportOnShape2(1))
|
||||
closest_topods_edge_param = extrema.ParOnEdgeS2(1)[0]
|
||||
elif supp_type == BRepExtrema_SupportType.BRepExtrema_IsVertex:
|
||||
v_hit = downcast(extrema.SupportOnShape2(1))
|
||||
vertex_edge_map = TopTools_IndexedDataMapOfShapeListOfShape()
|
||||
TopExp.MapShapesAndAncestors_s(
|
||||
self.wrapped, ta.TopAbs_VERTEX, ta.TopAbs_EDGE, vertex_edge_map
|
||||
)
|
||||
closest_topods_edge = downcast(vertex_edge_map.FindFromKey(v_hit).First())
|
||||
closest_topods_edge_param = BRep_Tool.Parameter_s(
|
||||
v_hit, closest_topods_edge
|
||||
)
|
||||
|
||||
curve_adaptor = BRepAdaptor_Curve(closest_topods_edge)
|
||||
param_min, param_max = BRep_Tool.Range_s(closest_topods_edge)
|
||||
if curve_adaptor.IsPeriodic():
|
||||
closest_topods_edge_param = (
|
||||
(closest_topods_edge_param - param_min) % curve_adaptor.Period()
|
||||
) + param_min
|
||||
param_pair = (
|
||||
(param_min, closest_topods_edge_param)
|
||||
if closest_topods_edge.Orientation() == TopAbs_Orientation.TopAbs_FORWARD
|
||||
else (closest_topods_edge_param, param_max)
|
||||
)
|
||||
distance_along_wire = GCPnts_AbscissaPoint.Length_s(curve_adaptor, *param_pair)
|
||||
|
||||
# Find all of the edges prior to the closest edge
|
||||
wire_explorer = BRepTools_WireExplorer(self.wrapped)
|
||||
|
|
@ -3198,7 +3234,7 @@ class Wire(Mixin1D, Shape[TopoDS_Wire]):
|
|||
wire_explorer.Next()
|
||||
continue
|
||||
# Stop when we find the closest edge
|
||||
if topods_edge.IsEqual(closest_edge.wrapped):
|
||||
if topods_edge.IsEqual(closest_topods_edge):
|
||||
break
|
||||
# Add the length of the current edge to the running total
|
||||
distance_along_wire += GCPnts_AbscissaPoint.Length_s(
|
||||
|
|
|
|||
|
|
@ -30,8 +30,6 @@ import unittest
|
|||
from math import sqrt, pi
|
||||
from build123d import *
|
||||
|
||||
from ocp_vscode import show
|
||||
|
||||
|
||||
def _assertTupleAlmostEquals(self, expected, actual, places, msg=None):
|
||||
"""Check Tuples"""
|
||||
|
|
@ -675,9 +673,6 @@ class BuildLineTests(unittest.TestCase):
|
|||
|
||||
# Check coincidence, tangency with each arc
|
||||
_, p1, p2 = start_arc.distance_to_with_closest_points(l1)
|
||||
a1 = Axis(p1, start_arc.tangent_at(p1))
|
||||
a2 = Axis(p2, l1.tangent_at(p2))
|
||||
show(start_arc, l1, p1, p2, a1, a2)
|
||||
self.assertTupleAlmostEquals(tuple(p1), tuple(p2), 5)
|
||||
self.assertAlmostEqual(
|
||||
start_arc.tangent_at(p1).cross(l1.tangent_at(p2)).length, 0, 5
|
||||
|
|
|
|||
|
|
@ -680,7 +680,5 @@ class TestGlobalLocation(unittest.TestCase):
|
|||
)
|
||||
|
||||
|
||||
from ocp_vscode import show
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
|
|
|||
|
|
@ -49,9 +49,6 @@ class DirectApiTestCase(unittest.TestCase):
|
|||
self.assertAlmostEqual(first.Z, second_vector.Z, places, msg=msg)
|
||||
|
||||
|
||||
from ocp_vscode import show, show_all
|
||||
|
||||
|
||||
class TestTopoExplore(DirectApiTestCase):
|
||||
|
||||
def test_topo_explore_connected_edges(self):
|
||||
|
|
@ -122,7 +119,6 @@ class TestTopoExplore(DirectApiTestCase):
|
|||
connected_c0 = topo_explore_connected_edges(
|
||||
extracted_e1, continuity=ContinuityLevel.C0
|
||||
)
|
||||
show_all()
|
||||
self.assertEqual(len(connected_c0), 2)
|
||||
self.assertTrue(
|
||||
connected_c0.filter_by(GeomType.LINE, reverse=True)[0].is_same(extracted_e2)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue