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:
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user