Draft: Add distance_to_plane and project_point_on_plane to geometry.py

The functions have been copied from the WorkingPlane class. It makes sense to also have them available outside that class. The WorkingPlane class will later be updated to use these functions so that duplicate code is avoided.

Note that the default tolerance of the project_point_on_plane function is 1e-7. In the original projectPoint function it is sys.float_info.epsilon (too small for FreeCAD IMO).
This commit is contained in:
Roy-043
2023-09-19 16:02:59 +02:00
parent 9ae03a5e87
commit 68276d20ad
2 changed files with 84 additions and 9 deletions

View File

@@ -81,7 +81,9 @@ from draftgeoutils.geometry import (findPerpendicular,
mirror_matrix,
uv_vectors_from_face,
placement_from_face,
placement_from_points)
placement_from_points,
distance_to_plane,
project_point_on_plane)
from draftgeoutils.edges import (findEdge,
orientEdge,

View File

@@ -529,8 +529,8 @@ def mirror_matrix(mtx, pos, nor):
nor: Base::Vector3
Normal of mirror plane.
Return
------
Returns
-------
Base::Matrix
"""
# Code by Jolbas:
@@ -563,8 +563,8 @@ def uv_vectors_from_face(face, vec_z=App.Vector(0, 0, 1), tol=-1):
Defaults to -1.
Internal tolerance. 1e-7 is used if tol <=0.
Return
------
Returns
-------
tuple
U and v vector (Base::Vector3).
"""
@@ -608,8 +608,8 @@ def placement_from_face(face, vec_z=App.Vector(0, 0, 1), rotated=False, tol=-1):
Defaults to -1.
Internal tolerance. 1e-7 is used if tol <=0.
Return
------
Returns
-------
Base::Placement
See also
@@ -645,8 +645,8 @@ def placement_from_points(pt_pos, pt_x, pt_y, as_vectors=False, tol=-1):
Defaults to -1.
Internal tolerance. 1e-7 is used if tol <=0.
Return
------
Returns
-------
Base::Placement
See also
@@ -675,6 +675,79 @@ def placement_from_points(pt_pos, pt_x, pt_y, as_vectors=False, tol=-1):
return App.Placement(pt_pos, rot)
# Code separated from WorkingPlane.py (offsetToPoint function).
# Note that the return value of this function has the opposite sign.
def distance_to_plane(point, base, normal):
"""Return the signed distance from a plane to a point.
The distance is positive if the point lies on the +normal side of the plane.
Parameters
----------
point: Base::Vector3
Point to project.
base: Base::Vector3
Point on plane.
normal: Base::Vector3
Normal of plane.
Returns
-------
float
"""
return (point - base).dot(normal)
# Code separated from WorkingPlane.py (projectPoint function).
# See: https://github.com/FreeCAD/FreeCAD/pull/5307
def project_point_on_plane(point, base, normal, direction=None, force_projection=False, tol=-1):
"""Project a point onto a plane.
Parameters
----------
point: Base::Vector3
Point to project.
base: Base::Vector3
Point on plane.
normal: Base::Vector3
Normal of plane.
direction: Base::Vector3, optional
Defaults to `None` in which case the normal is used.
Direction of projection.
force_projection: Bool, optional
Defaults to `False`.
If `True` forces the projection if the deviation between the direction
and the normal is less than tol from the orthogonality. The direction
of projection is then modified to a tol deviation between the direction
and the orthogonal.
tol: float, optional
Defaults to -1.
Internal tolerance. 1e-7 is used if tol <=0.
Returns
-------
Base::Vector3 or `None`
"""
err = 1e-7 if tol <= 0 else tol
normal = App.Vector(normal).normalize()
if direction is None:
direction = normal
else:
direction = App.Vector(direction).normalize()
cos = direction.dot(normal)
delta_ax_proj = (point - base).dot(normal)
# check the only conflicting case: direction orthogonal to normal
if abs(cos) < err:
if force_projection:
cos = math.copysign(err, delta_ax_proj)
direction = normal.cross(direction).cross(normal) - cos * normal
else:
return None
return point - delta_ax_proj / cos * direction
#compatibility layer
getSplineNormal = get_spline_normal