/[escript]/trunk/pycad/py_src/transformations.py
ViewVC logotype

Contents of /trunk/pycad/py_src/transformations.py

Parent Directory Parent Directory | Revision Log Revision Log


Revision 6939 - (show annotations)
Mon Jan 20 03:37:18 2020 UTC (8 months, 1 week ago) by uqaeller
File MIME type: text/x-python
File size: 5064 byte(s)
Updated the copyright header.


1
2 ##############################################################################
3 #
4 # Copyright (c) 2003-2020 by The University of Queensland
5 # http://www.uq.edu.au
6 #
7 # Primary Business: Queensland, Australia
8 # Licensed under the Apache License, version 2.0
9 # http://www.apache.org/licenses/LICENSE-2.0
10 #
11 # Development until 2012 by Earth Systems Science Computational Center (ESSCC)
12 # Development 2012-2013 by School of Earth Sciences
13 # Development from 2014 by Centre for Geoscience Computing (GeoComp)
14 # Development from 2019 by School of Earth and Environmental Sciences
15 #
16 ##############################################################################
17
18 from __future__ import print_function, division
19
20 __copyright__="""Copyright (c) 2003-2020 by The University of Queensland
21 http://www.uq.edu.au
22 Primary Business: Queensland, Australia"""
23 __license__="""Licensed under the Apache License, version 2.0
24 http://www.apache.org/licenses/LICENSE-2.0"""
25 __url__="https://launchpad.net/escript-finley"
26
27 """
28 transformations
29
30 :var __author__: name of author
31 :var __copyright__: copyrights
32 :var __license__: licence agreement
33 :var __url__: url entry point on documentation
34 :var __version__: version
35 :var __date__: date of the version
36 :var DEG: unit of degree
37 :var RAD: unit of radiant
38 """
39
40 __author__="Lutz Gross, l.gross@uq.edu.au"
41
42 import numpy
43 import math
44
45 _TYPE=numpy.float64
46 DEG=math.pi/180.
47 RAD=1.
48 class Transformation(object):
49 """
50 General class to define an affine transformation *x->Ax+b*.
51 """
52 def __init__(self):
53 """
54 Creates a linear transformation.
55 """
56 pass
57
58 def __call__(self,x=numpy.zeros((3,))):
59 """
60 Applies transformation to ``x``.
61 """
62 raise NotImplementeError()
63
64 class Translation(Transformation):
65 """
66 Defines a translation *x->x+b*.
67 """
68 def __init__(self,b=numpy.zeros((3,),dtype=_TYPE)):
69 """
70 Creates the linear transformation *x->x+b*.
71 """
72 super(Translation, self).__init__()
73 self.__b=numpy.array(b,_TYPE)
74
75 def __call__(self,x=numpy.zeros((3,))):
76 """
77 Applies translation to ``x``.
78 """
79 return numpy.array(x,_TYPE)+self.__b
80
81 class Rotatation(Transformation):
82 """
83 Defines a rotation.
84 """
85 def __init__(self,axis=numpy.ones((3,),dtype=_TYPE),point=numpy.zeros((3,),dtype=_TYPE),angle=0.*RAD):
86 """
87 Creates a rotation using an axis and a point on the axis.
88 """
89 self.__axis=numpy.array(axis,dtype=_TYPE)
90 self.__point=numpy.array(point,dtype=_TYPE)
91 lax=numpy.dot(self.__axis,self.__axis)
92 if not lax>0:
93 raise ValueError("points must be distinct.")
94 self.__axis/=math.sqrt(lax)
95 self.__angle=float(angle)
96
97 def __call__(self,x=numpy.zeros((3,))):
98 """
99 Applies the rotation to ``x``.
100 """
101 x=numpy.array(x,_TYPE)
102 z=x-self.__point
103 z0=numpy.dot(z,self.__axis)
104 z_per=z-z0*self.__axis
105 lz_per=numpy.dot(z_per,z_per)
106 if lz_per>0:
107 axis1=z_per/math.sqrt(lz_per)
108 axis2=_cross(axis1,self.__axis)
109 lax2=numpy.dot(axis2,axis2)
110 if lax2>0:
111 axis2/=math.sqrt(lax2)
112 return z0*self.__axis+math.sqrt(lz_per)*(math.cos(self.__angle)*axis1-math.sin(self.__angle)*axis2)+self.__point
113 else:
114 return x
115 else:
116 return x
117
118 def _cross(x, y):
119 """
120 Returns the cross product of ``x`` and ``y``.
121 """
122 return numpy.array([x[1] * y[2] - x[2] * y[1], x[2] * y[0] - x[0] * y[2], x[0] * y[1] - x[1] * y[0]], _TYPE)
123
124 class Dilation(Transformation):
125 """
126 Defines a dilation.
127 """
128 def __init__(self,factor=1.,center=numpy.zeros((3,),dtype=_TYPE)):
129 """
130 Creates a dilation with a center and a given expansion/contraction
131 factor.
132 """
133 if not abs(factor)>0:
134 raise ValueError("factor must be non-zero.")
135 self.__factor=factor
136 self.__center=numpy.array(center,dtype=_TYPE)
137
138 def __call__(self,x=numpy.zeros((3,))):
139 """
140 Applies dilation to ``x``.
141 """
142 x=numpy.array(x,_TYPE)
143 return self.__factor*(x-self.__center)+self.__center
144
145 class Reflection(Transformation):
146 """
147 Defines a reflection on a plane.
148 """
149 def __init__(self,normal=numpy.ones((3,),dtype=_TYPE),offset=0.):
150 """
151 Defines a reflection on a plane defined in normal form.
152 """
153 self.__normal=numpy.array(normal,dtype=_TYPE)
154 ln=math.sqrt(numpy.dot(self.__normal,self.__normal))
155 if not ln>0.:
156 raise ValueError("normal must have positive length.")
157 self.__normal/=ln
158 if isinstance(offset,float) or isinstance(offset,int):
159 self.__offset=offset/ln
160 else:
161 self.__offset=numpy.dot(numpy.array(offset,dtype=_TYPE),self.__normal)
162
163 def __call__(self,x=numpy.zeros((3,))):
164 """
165 Applies reflection to ``x``.
166 """
167 x=numpy.array(x,_TYPE)
168 return x - 2*(numpy.dot(x,self.__normal)-self.__offset)*self.__normal
169

  ViewVC Help
Powered by ViewVC 1.1.26