Draft: Add placement_from_points to geometry.py
Changed getPlacementFromPoints function in WorkingPlane.py to a compatibility function that calls placement_from_points.
This commit is contained in:
@@ -77,7 +77,8 @@ from draftgeoutils.geometry import (findPerpendicular,
|
||||
calculatePlacement,
|
||||
mirror,
|
||||
are_coplanar,
|
||||
is_straight_line)
|
||||
is_straight_line,
|
||||
placement_from_points)
|
||||
|
||||
from draftgeoutils.edges import (findEdge,
|
||||
orientEdge,
|
||||
|
||||
@@ -40,6 +40,7 @@ import lazy_loader.lazy_loader as lz
|
||||
import FreeCAD
|
||||
import DraftVecUtils
|
||||
from FreeCAD import Vector
|
||||
from draftutils import utils
|
||||
from draftutils.translate import translate
|
||||
|
||||
DraftGeomUtils = lz.LazyLoader("DraftGeomUtils", globals(), "DraftGeomUtils")
|
||||
@@ -1312,53 +1313,14 @@ class Plane:
|
||||
plane = Plane
|
||||
|
||||
|
||||
# Compatibility function:
|
||||
def getPlacementFromPoints(points):
|
||||
"""Return a placement from a list of 3 or 4 points.
|
||||
"""Return a placement from a list of 3 or 4 points. The 4th point is no longer used.
|
||||
|
||||
With these points a temporary `plane` is defined.
|
||||
|
||||
Then it returns the `Base::Placement` returned from `plane.getPlacement()`.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
points : list of Base::Vector3
|
||||
A list with 3 or 4 points to create a temporary plane
|
||||
from which to extract the placement.
|
||||
|
||||
The first point is the plane's `position`.
|
||||
The other two points are used to define the `u` and `v` axes,
|
||||
as originating from the first point.
|
||||
|
||||
If the fourth point exists, it is used to define the plane's `axis`
|
||||
as originating from the first point.
|
||||
If no fourth point is provided, the cross product bewtween
|
||||
the previously defined `u` and `v` is used as `axis`.
|
||||
|
||||
Return
|
||||
------
|
||||
Base::Placement
|
||||
A placement obtained from the temporary plane
|
||||
defined by `points`,
|
||||
or `None` is it fails to use the points.
|
||||
|
||||
See Also
|
||||
--------
|
||||
getPlacement
|
||||
Calls DraftGeomUtils.placement_from_points(). See there.
|
||||
"""
|
||||
pl = plane()
|
||||
try:
|
||||
pl.position = points[0]
|
||||
pl.u = (points[1].sub(points[0]).normalize())
|
||||
pl.v = (points[2].sub(points[0]).normalize())
|
||||
if len(points) == 4:
|
||||
pl.axis = (points[3].sub(points[0]).normalize())
|
||||
else:
|
||||
pl.axis = ((pl.u).cross(pl.v)).normalize()
|
||||
except Exception:
|
||||
return None
|
||||
p = pl.getPlacement()
|
||||
del pl
|
||||
return p
|
||||
utils.use_instead("DraftGeomUtils.placement_from_points")
|
||||
return DraftGeomUtils.placement_from_points(*points[:3])
|
||||
|
||||
|
||||
def getPlacementFromFace(face, rotated=False):
|
||||
|
||||
@@ -517,6 +517,60 @@ def mirror(point, edge):
|
||||
return None
|
||||
|
||||
|
||||
def placement_from_points(pt_pos, pt_x, pt_y, as_vectors=False, tol=-1):
|
||||
"""Return a placement from 3 points defining an origin, an X axis and a Y axis.
|
||||
|
||||
If the vectors calculated from the arguments are too short or parallel,
|
||||
the returned placement will have a default rotation.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
pt_pos : Base::Vector3
|
||||
Origin (Base of Placement).
|
||||
|
||||
pt_x : Base::Vector3
|
||||
Point on positive X axis. Or X axis vector if as_vectors is `True`.
|
||||
|
||||
pt_y : Base::Vector3
|
||||
Point on positive Y axis. Or Y axis vector if as_vectors is `True`.
|
||||
|
||||
as_vectors : bool
|
||||
If `True` treat pt_x and pt_y as axis vectors.
|
||||
|
||||
tol : float
|
||||
Internal tolerance. 1e-7 is used if tol <=0.
|
||||
|
||||
See also:
|
||||
---------
|
||||
DraftVecUtils.getRotation
|
||||
DraftGeomUtils.getRotation
|
||||
|
||||
Return
|
||||
------
|
||||
Base::Placement
|
||||
"""
|
||||
err = 1e-7 if tol <= 0 else tol
|
||||
if as_vectors is False:
|
||||
vec_u = pt_x - pt_pos
|
||||
vec_v = pt_y - pt_pos
|
||||
else:
|
||||
vec_u = App.Vector(pt_x)
|
||||
vec_v = App.Vector(pt_y)
|
||||
|
||||
if vec_u.Length < err or vec_v.Length < err:
|
||||
rot = App.Rotation()
|
||||
else:
|
||||
vec_u.normalize()
|
||||
vec_v.normalize()
|
||||
if vec_u.isEqual(vec_v, err) \
|
||||
or vec_u.isEqual(vec_v.negative(), err):
|
||||
rot = App.Rotation()
|
||||
else:
|
||||
rot = App.Rotation(vec_u, vec_v, App.Vector(), "XYZ")
|
||||
|
||||
return App.Placement(pt_pos, rot)
|
||||
|
||||
|
||||
#compatibility layer
|
||||
|
||||
getSplineNormal = get_spline_normal
|
||||
|
||||
@@ -1267,7 +1267,6 @@ class boxTracker(Tracker):
|
||||
|
||||
def update(self, line=None, normal=None):
|
||||
"""Update the tracker."""
|
||||
import WorkingPlane
|
||||
import DraftGeomUtils
|
||||
if not normal:
|
||||
normal = FreeCAD.DraftWorkingPlane.axis
|
||||
@@ -1283,16 +1282,18 @@ class boxTracker(Tracker):
|
||||
bp = self.baseline.Shape.Edges[0].Vertexes[0].Point
|
||||
else:
|
||||
return
|
||||
right = lvec.cross(normal)
|
||||
self.cube.width.setValue(lvec.Length)
|
||||
p = WorkingPlane.getPlacementFromPoints([bp,
|
||||
bp.add(lvec),
|
||||
bp.add(right)])
|
||||
if p:
|
||||
self.trans.rotation.setValue(p.Rotation.Q)
|
||||
bp = bp.add(lvec.multiply(0.5))
|
||||
bp = bp.add(DraftVecUtils.scaleTo(normal, self.cube.depth.getValue()/2.0))
|
||||
self.pos(bp)
|
||||
tol = 1e-6
|
||||
if lvec.Length > tol and normal.Length > tol:
|
||||
lvec.normalize()
|
||||
normal.normalize()
|
||||
if not lvec.isEqual(normal, tol) \
|
||||
and not lvec.isEqual(normal.negative(), tol):
|
||||
rot = FreeCAD.Rotation(lvec, FreeCAD.Vector(), normal, "XZY")
|
||||
self.trans.rotation.setValue(rot.Q)
|
||||
|
||||
def setRotation(self, rot):
|
||||
"""Set the rotation."""
|
||||
|
||||
Reference in New Issue
Block a user