-
Notifications
You must be signed in to change notification settings - Fork 19
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Rigid Transformations #39
Changes from 1 commit
324b850
af401d8
aff57bf
7f069da
79d85ec
cb9e9ed
bf65d33
fa7fda9
173106e
65245d9
5d4b036
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -291,26 +291,34 @@ def intersect(self, other, abs_tol=ABS_TOL): | |
return reduce(Polytope(iA, ib), abs_tol=abs_tol) | ||
|
||
def translation(self, d): | ||
"""Translate the Polytope by a given vector. | ||
"""Returns a copy of C{self} translated by the vector C{d}. | ||
|
||
Consult L{polytope.polytope._translate} for implementation details. | ||
|
||
@type d: 1d array | ||
@param d: The translation vector. | ||
|
||
@rtype: L{Polytope} | ||
@return: A translated copy of the Polytope. | ||
""" | ||
newpoly = self.copy() | ||
_translate(newpoly, d) | ||
return newpoly | ||
|
||
def rotation(self, u, v, theta=None): | ||
"""Rotate the Polytope. Only simple rotations are implemented at this | ||
"""Returns a rotated copy of C{self}. | ||
|
||
Use one of two methods that to describe the plane of rotation and the | ||
angle of rotation (in radians) with u, v, and theta. | ||
|
||
(1) u and v are the indicies (0, N] of two basis vectors, and theta is | ||
the angle of rotation. | ||
|
||
(2) u and v are two unit vectors, angle of rotation is the angle | ||
between them from u to v. NOTE: This method is not implemented at this | ||
time. | ||
|
||
@rtype: L{Polytope} | ||
@return: A rotated copy of the Polytope. | ||
Consult L{polytope.polytope._rotate} for more detail. | ||
|
||
@type u: number, 1d array | ||
@type v: number, 1d array | ||
@type theta: number | ||
""" | ||
newpoly = self.copy() | ||
_rotate(newpoly, u, v, theta) | ||
|
@@ -469,13 +477,9 @@ def text(self, txt, ax=None, color='black'): | |
|
||
|
||
def _translate(polyreg, d): | ||
"""Translate a polyreg by a vector in place. Does not return a copy. | ||
"""Translate C{polyreg} by the vector C{d}. Modifies C{polyreg} in-place. | ||
|
||
@type d: 1d array | ||
@param d: The translation vector. | ||
|
||
@type polyreg: L{Polytope} or L{Region} | ||
@param polyreg: The polytope or region to be translated. | ||
""" | ||
|
||
if isinstance(polyreg, Polytope): | ||
|
@@ -495,43 +499,47 @@ def _translate(polyreg, d): | |
|
||
|
||
def _rotate(polyreg, u=None, v=None, theta=None, R=None): | ||
"""Rotate this polyreg in place. Return the rotation matrix. | ||
|
||
Simple rotations, by definition, occur only in 2 of the N dimensions; the | ||
other N-2 dimensions are invariant with the rotation. Any rotations thus | ||
require specification of the plane(s) of rotation. This function has three | ||
different ways to specify this plane: | ||
|
||
(1) Providing the indices [0, N) of the orthogonal basis vectors which | ||
define the plane of rotation and an angle of rotation (theta) between them. | ||
This allows easy construction of the Givens rotation matrix. The right hand | ||
rule defines the positive rotation direction. | ||
|
||
(2) Providing two unit vectors with no angle. The two vectors are contained | ||
within a plane and the degree of rotation is the angle which moves the | ||
first vector, u, into alignment with the second vector, v. NOTE: This | ||
method is not implemented at this time. | ||
|
||
(3) Providing an NxN rotation matrix, R. WARNING: No checks are made to | ||
"""Rotate C{polyreg} in-place. Return the rotation matrix. | ||
|
||
There are two types of rotation: simple and compound. For simple rotations, | ||
by definition, all motion can be projected as circles in a single plane; | ||
the other N-2 dimensions are invariant. Therefore any simple rotation can | ||
be parameterized by its plane of rotation. Compound rotations are the | ||
combination of multiple simple rotations; they have more than one plane of | ||
rotation. For N > 3 dimensions, a compound rotation may be necessary to map | ||
one orientation to another (Euler's rotation theory no longer applies). | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. would "Euler's rotation theorem" be more appropriate here, rather than "Euler's rotation theory"? |
||
|
||
Use one of the following three methods to specify rotation. The first two | ||
can only express simple rotation, but simple rotations may be applied in a | ||
sequence to acheive a compound rotation. | ||
|
||
(1) Provide the indices [0, N) of the orthogonal basis vectors, u and v, | ||
which define the plane of rotation and a radian angle of rotation, theta, | ||
between them. This method contructs the Givens rotation matrix. The right | ||
hand rule defines the positive rotation direction. | ||
|
||
(2) Provide two unit vectors, The two vectors define the plane of rotation | ||
and angle of rotation is the angle which moves the first vector, u, into | ||
alignment with the second vector, v. NOTE: This method is not implemented | ||
at this time. | ||
|
||
(3) Provide an NxN rotation matrix, R. WARNING: No checks are made to | ||
determine whether the provided transformation matrix is a valid rotation. | ||
|
||
Further Reading | ||
https://en.wikipedia.org/wiki/Plane_of_rotation | ||
|
||
@type polyreg: L{Polytope} or L{Region} | ||
@param polyreg: The polytope or region to be rotated. | ||
@type u: number, 1d array | ||
@type polyreg: L{Polytope} or L{Region} | ||
@param u: The first index or vector describing the plane of rotation. | ||
@type v: number, 1d array | ||
@param u: The second index or vector describing the plane of rotation. | ||
@type theta: number | ||
@type u: number, 1d array | ||
@param u: The second index or vector describing the plane of rotation | ||
@type v: number, 1d array. | ||
@param theta: The radian angle to rotate the polyreg in the plane defined | ||
by u and v. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should the description for There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good catch! I have fixed this. |
||
@type R: 2d array | ||
@type theta: number | ||
@param R: A predefined rotation matrix. | ||
|
||
@rtype: 2d array | ||
@return: The matrix used to rotate the polyreg. | ||
@type R: 2d array | ||
""" | ||
# determine the rotation matrix based on inputs | ||
if R is not None: | ||
|
@@ -775,26 +783,34 @@ def intersect(self, other, abs_tol=ABS_TOL): | |
return P | ||
|
||
def rotation(self, u, v, theta=None): | ||
"""Rotate this Region. Only simple rotations are implemented at this | ||
"""Returns a rotated copy of C{self}. | ||
|
||
Use one of two methods that to describe the plane of rotation and the | ||
angle of rotation (in radians) with u, v, and theta. | ||
|
||
(1) u and v are the indicies (0, N] of two basis vectors, and theta is | ||
the angle of rotation. | ||
|
||
(2) u and v are two unit vectors, angle of rotation is the angle | ||
between them from u to v. NOTE: This method is not implemented at this | ||
time. | ||
|
||
@rtype: L{Region} | ||
@return: A translated copy of the Region. | ||
Consult L{polytope.polytope._rotate} for more detail. | ||
|
||
@type u: number, 1d array | ||
@type v: number, 1d array | ||
@type theta: number | ||
""" | ||
newreg = self.copy() | ||
_rotate(newreg, u, v, theta) | ||
return newreg | ||
|
||
def translation(self, d): | ||
"""Translate this Region by a given vector. | ||
"""Returns a copy of C{self} translated by the vector C{d}. | ||
|
||
Consult L{polytope.polytope._translate} for implementation details. | ||
|
||
@type d: 1d array | ||
@param d: The translation vector. | ||
|
||
@rtype: L{Region} | ||
@return: A translated copy of the Region. | ||
""" | ||
newreg = self.copy() | ||
_translate(newreg, d) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should that be [0, N)? I am also happy with [0,N[.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
or 0..N-1 (as in TLA+)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think that
0..(N-1)
or0..N-1
are correct, but[0, N)
is ambiguous, because the indices should be integers. In a typed formalism, one could claim to have declared thatu, v
are of "integer type" (whatever that may mean). However, inpolytope
we have neither type declarations of any form, nor are integers the norm. So, I think that0..(N-1)
avoids this ambiguity. Explicit is better than implicit (PEP 20).In a context that involves real numbers, I prefer
[0, N)
to[0, N[
, because I find it easier to distinguish a a closing parentheses)
from a closing bracket]
, than an opening bracket[
from a closing bracket]
. I do appreciate the symmetry of the latter notation though.I believe that "indicies" is a typo. Both "indices" and "indexes" appear to be used as plural form of "index". A remark about the same was made earlier.
Also, I think that if one method is supported now, then No.2 should be omitted. Why have the user read two items, and then find out the 2nd isn't available?
I am opposed to the polymorphism of
u, v
. I had to read No.1 multiple times to convince myself that I understand correctly.u, v
should better have one type in each signature. If they are integer indices, it is more familiar to name themi, j
orm, n
."basis" could be ambiguous. We could specify that the basis is the same as that used to express the coordinates.
Relevant for those interested in untypeness:
omega
is in transition from typed to untyped (cf tulip-control/omega#3).There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Special cases aren't special enough to break the rules [PEP 20]. It seems more uniform to let
u, v
be vectors. This way:UnimplementedError
is raised if vectors outside the intended basis are passedDefining the basis vectors
u0, u1
etc in user code is relatively simple, and it also names them, so it is probably easier to read (as opposed to some integers 0, 1, ...).There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@slivingston That is correct, I meant to type 0..N-1.
@johnyf "indicies" is a typo. I keep spelling it wrong. I agree that polymorphic
u, v
probably isn't the best. However, I'm not going to get rid of rotation by indexed basis vector because the current implementation is based around that special case. What I will do is rename the parameters toi, j
, and hide the second method. When I figure out how to implement the second option, the parametersu, v
will reappear.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What I had in mind was raising an error if either
u
orv
isn't a basis vector. If both are basis vectors, then convert them to indices, and proceed with the rest of the computation as currently done. Your current decision yields a simpler interface, and simple is better than complex (PEP 20).