From 5eaa98629dc058ab2e25f40053f50e15636ebb8f Mon Sep 17 00:00:00 2001 From: vocx-fc Date: Wed, 7 Aug 2019 18:10:27 -0500 Subject: [PATCH] Draft: WorkingPlane, Pythonic style, improved the docstrings, in particular offsetToPoint(); I have some doubts about the implementation in 3D space as it seems to calculate a projected distance, and not the real distance; I don't think this is very helpful when the direction is different from perpendicular (normal); perpendicular distance is certainly the most common case, so I don't know if there is any problem at all in practice. --- src/Mod/Draft/WorkingPlane.py | 120 ++++++++++++++++++++++++++-------- 1 file changed, 94 insertions(+), 26 deletions(-) diff --git a/src/Mod/Draft/WorkingPlane.py b/src/Mod/Draft/WorkingPlane.py index 63f07c3657..11dce5f2d0 100644 --- a/src/Mod/Draft/WorkingPlane.py +++ b/src/Mod/Draft/WorkingPlane.py @@ -61,7 +61,8 @@ class plane: A vector that is supposed to be perpendicular to `u` and `v`; it is helpful although redundant. position : Base::Vector3 - A vector that helps define the working plane. + A point throught which the plane goes through, + that helps define the working plane. stored : bool A placeholder for a stored state. """ @@ -82,7 +83,7 @@ class plane: it is redundant. It defaults to `(0, 0, 1)`, or the +Z axis. pos : Base::Vector3, optional - The position of the working plane. + A point through which the plane goes through. It defaults to the origin `(0, 0, 0)`. """ # keep track of active document. Reset view when doc changes. @@ -96,40 +97,107 @@ class plane: self.stored = None def __repr__(self): + """Show the string representation of the object.""" return "Workplane x="+str(DraftVecUtils.rounded(self.u))+" y="+str(DraftVecUtils.rounded(self.v))+" z="+str(DraftVecUtils.rounded(self.axis)) def copy(self): + """Return a new plane that is a copy of the present object.""" return plane(u=self.u, v=self.v, w=self.axis, pos=self.position) def offsetToPoint(self, p, direction=None): - ''' - Return the signed distance from p to the plane, such - that p + offsetToPoint(p)*direction lies on the plane. - direction defaults to -plane.axis - ''' + """Return the signed distance from a point to the plane. - ''' - A picture will help explain the computation: + Parameters + ---------- + p : Base::Vector3 + The external point to consider. + direction : Base::Vector3, optional + The unit vector that indicates the direction of the distance. - p - //| - / / | - / / | - / / | - / / | - -------------------- plane -----c-----x-----a-------- + It defaults to `None`, which then uses the `plane.axis` (normal) + value, meaning that the measured distance is perpendicular + to the plane. - Here p is the specified point, - c is a point (in this case plane.position) on the plane - x is the intercept on the plane from p in the specified direction, and - a is the perpendicular intercept on the plane (i.e. along plane.axis) + Returns + ------- + float + The distance from the point to the plane. - Using vertival bars to denote the length operator, - |ap| = |cp| * cos(apc) = |xp| * cos(apx) - so - |xp| = |cp| * cos(apc) / cos(apx) - = (cp . axis) / (direction . axis) - ''' + Notes + ----- + The signed distance `d`, from `p` to the plane, is such that + :: + x = p + d*direction, + + where `x` is a point that lies on the plane. + + The `direction` is a unit vector that specifies the direction + in which the distance is measured. + It defaults to `plane.axis`, + meaning that it is the perpendicular distance. + + A picture will help explain the computation + :: + p + //| + / / | + d / / | axis + / / | + / / | + -------- plane -----x-----c-----a-------- + + The points are as follows + + * `p` is an arbitraty point outside the plane. + * `c` is a known point on the plane, + for example, `plane.position`. + * `x` is the intercept on the plane from `p` in + the desired `direction`. + * `a` is the perpendicular intercept on the plane, + i.e. along `plane.axis`. + + The distance is calculated through the dot product + of the vector `pc` (going from point `p` to point `c`, + both of which are known) with the unit vector `direction` + (which is provided or defaults to `plane.axis`). + :: + d = pc . direction + d = (c - p) . direction + + **Warning:** this implementation doesn't calculate the entire + distance `|xp|`, only the distance `|pc|` projected onto `|xp|`. + + Trigonometric relationships + --------------------------- + In 2D the distances can be calculated by trigonometric relationships + :: + |ap| = |cp| cos(apc) = |xp| cos(apx) + + Then the desired distance is `d = |xp|` + :: + |xp| = |cp| cos(apc) / cos(apx) + + The cosines can be obtained from the definition of the dot product + :: + A . B = |A||B| cos(angleAB) + + If one vector is a unit vector + :: + A . uB = |A| cos(angleAB) + cp . axis = |cp| cos(apc) + + and if both vectors are unit vectors + :: + uA . uB = cos(angleAB). + direction . axis = cos(apx) + + Then + :: + d = (cp . axis) / (direction . axis) + + **Note:** for 2D these trigonometric operations + produce the full `|xp|` distance. + """ if direction == None: direction = self.axis return direction.dot(self.position.sub(p))