1 |
gross |
898 |
# $Id:$ |
2 |
|
|
|
3 |
|
|
""" |
4 |
|
|
Geometrical Elementries |
5 |
|
|
|
6 |
|
|
the concept is inspired by gmsh and very much focused on the fact that |
7 |
|
|
the classes are used to wrk with gmsh. |
8 |
|
|
|
9 |
|
|
@var __author__: name of author |
10 |
|
|
@var __copyright__: copyrights |
11 |
|
|
@var __license__: licence agreement |
12 |
|
|
@var __url__: url entry point on documentation |
13 |
|
|
@var __version__: version |
14 |
|
|
@var __date__: date of the version |
15 |
|
|
""" |
16 |
|
|
|
17 |
|
|
|
18 |
|
|
__author__="Lutz Gross, l.gross@uq.edu.au" |
19 |
|
|
__copyright__=""" Copyright (c) 2006 by ACcESS MNRF |
20 |
|
|
http://www.access.edu.au |
21 |
|
|
Primary Business: Queensland, Australia""" |
22 |
|
|
__license__="""Licensed under the Open Software License version 3.0 |
23 |
|
|
http://www.opensource.org/licenses/osl-3.0.php""" |
24 |
|
|
__url__="http://www.iservo.edu.au/esys/escript" |
25 |
|
|
__version__="$Revision:$" |
26 |
|
|
__date__="$Date:$" |
27 |
|
|
|
28 |
|
|
class Elementary(object): |
29 |
|
|
""" |
30 |
|
|
template for elementary geometrical object |
31 |
|
|
""" |
32 |
|
|
def __init__(self): |
33 |
|
|
""" |
34 |
|
|
""" |
35 |
|
|
pass |
36 |
|
|
|
37 |
|
|
class Point(Elementary): |
38 |
|
|
""" |
39 |
|
|
a three dimensional point |
40 |
|
|
""" |
41 |
|
|
def __init__(self,x=0.,y=0.,z=0.,local_scale=1.): |
42 |
|
|
""" |
43 |
|
|
creates a point with coorinates x,y,z with a relative refinement factor |
44 |
|
|
""" |
45 |
|
|
super(Point, self).__init__() |
46 |
|
|
if not local_scale > 0.: |
47 |
|
|
raise ValueError("local_scale needs to be positive.") |
48 |
|
|
self._x=numarray.array([x,y,z],numarray.Float64) |
49 |
|
|
self.setLocalScale(0.,local_scale) |
50 |
|
|
def __str__(self): |
51 |
|
|
return str(self._x) |
52 |
|
|
def setLocalScale(self,factor=1.): |
53 |
|
|
self.__local_scale=factor |
54 |
|
|
|
55 |
|
|
|
56 |
|
|
class Curve(Elementary): |
57 |
|
|
""" |
58 |
|
|
a curve |
59 |
|
|
""" |
60 |
|
|
def __init__(self,*args): |
61 |
|
|
""" |
62 |
|
|
defines a curve form a set of control points |
63 |
|
|
""" |
64 |
|
|
super(Curve, self).__init__() |
65 |
|
|
l=len(args) |
66 |
|
|
for i in range(l): |
67 |
|
|
if not isinstance(args[i],Point): |
68 |
|
|
raise TypeError("%s-th argument is not a Point object.") |
69 |
|
|
super(Curve, self).__init__(args[0],args[l-1]) |
70 |
|
|
self.__nodes=list(args) |
71 |
|
|
def __len__(self): |
72 |
|
|
return len(self.__nodes) |
73 |
|
|
|
74 |
|
|
def getStart(self): |
75 |
|
|
""" |
76 |
|
|
returns start point |
77 |
|
|
""" |
78 |
|
|
return self.__nodes[0] |
79 |
|
|
|
80 |
|
|
def getEnd(self): |
81 |
|
|
""" |
82 |
|
|
returns end point |
83 |
|
|
""" |
84 |
|
|
return self.__nodes[-1] |
85 |
|
|
|
86 |
|
|
def getNodes(self): |
87 |
|
|
""" |
88 |
|
|
returns a list of the nodes |
89 |
|
|
""" |
90 |
|
|
return self.__nodes |
91 |
|
|
|
92 |
|
|
def __neg__(self): |
93 |
|
|
""" |
94 |
|
|
returns the line segment with swapped start and end points |
95 |
|
|
""" |
96 |
|
|
return Curve(self.__nodes[::-1]) |
97 |
|
|
|
98 |
|
|
class BezierCurve(Curve): |
99 |
|
|
""" |
100 |
|
|
a Bezier curve |
101 |
|
|
""" |
102 |
|
|
def __neg__(self): |
103 |
|
|
""" |
104 |
|
|
returns the line segment with swapped start and end points |
105 |
|
|
""" |
106 |
|
|
return BezierCurve(self.getNodesInReversedOrder()) |
107 |
|
|
|
108 |
|
|
class BSplineCurve(Curve): |
109 |
|
|
""" |
110 |
|
|
a BSpline curve. Control points may be repeated. |
111 |
|
|
""" |
112 |
|
|
def __neg__(self): |
113 |
|
|
""" |
114 |
|
|
returns the line segment with swapped start and end points |
115 |
|
|
""" |
116 |
|
|
return BSplineCurve(self.getNodesInReversedOrder()) |
117 |
|
|
|
118 |
|
|
|
119 |
|
|
class Line(Curve): |
120 |
|
|
""" |
121 |
|
|
a line is defined by two L{Point}s |
122 |
|
|
""" |
123 |
|
|
def __neg__(self): |
124 |
|
|
""" |
125 |
|
|
returns the line segment with swapped start and end points |
126 |
|
|
""" |
127 |
|
|
return Line(self.getEnd(),self.getStart()) |
128 |
|
|
|
129 |
|
|
class Arc(Curve): |
130 |
|
|
""" |
131 |
|
|
defines an arc |
132 |
|
|
""" |
133 |
|
|
def __init__(self,center,start,end): |
134 |
|
|
""" |
135 |
|
|
creates an arc by the start point, end point and center |
136 |
|
|
""" |
137 |
|
|
if not isinstance(center,Point): |
138 |
|
|
raise TypeError("center needs to be a Point object.") |
139 |
|
|
super(Arc, self).__init__(start,end) |
140 |
|
|
self.__center=center |
141 |
|
|
|
142 |
|
|
def getCenter(self): |
143 |
|
|
""" |
144 |
|
|
returns center |
145 |
|
|
""" |
146 |
|
|
return self.__center |
147 |
|
|
def __neg__(self): |
148 |
|
|
""" |
149 |
|
|
returns the line segment with swapped start and end points |
150 |
|
|
""" |
151 |
|
|
return Arc(self.getCenter(),self.getEnd(),self.getStart()) |
152 |
|
|
|
153 |
|
|
class CurveLoop(Elementary): |
154 |
|
|
""" |
155 |
|
|
An oriented loop of curves. |
156 |
|
|
|
157 |
|
|
The loop must be closed and the L{Curves}s should be oriented consistently. |
158 |
|
|
""" |
159 |
|
|
def __init__(self,*curves): |
160 |
|
|
""" |
161 |
|
|
creates a polygon from a list of line curves. The curves must form a closed loop. |
162 |
|
|
""" |
163 |
|
|
super(CurveLoop, self).__init__() |
164 |
|
|
for i in curves: |
165 |
|
|
if not isinstance(curves[i],Curve): |
166 |
|
|
raise TypeError("%s-th argument is not a Curve object.") |
167 |
|
|
if length(curves)>0: |
168 |
|
|
for i in range(len(curves)-1): |
169 |
|
|
if not curves[i].getEnd() == curves[i+1].getStart(): |
170 |
|
|
raise ValueError("start point of %s-th curve does not match end point of %s-th curve."%(i,i+1)) |
171 |
|
|
if curves[0].getStart() == curves[len(curves)-1].getEnd(): |
172 |
|
|
raise ValueError("loop is not closed.") |
173 |
|
|
self.__curves=curves |
174 |
|
|
|
175 |
|
|
def getCurves(self): |
176 |
|
|
return self.__curves |
177 |
|
|
|
178 |
|
|
def __neg__(self): |
179 |
|
|
return CurveLoop([-c for c in self.__curves[::-1]]) |
180 |
|
|
|
181 |
|
|
def __len__(self): |
182 |
|
|
return len(self.__curves) |
183 |
|
|
|
184 |
|
|
class Surface(Elementary): |
185 |
|
|
""" |
186 |
|
|
a surface |
187 |
|
|
""" |
188 |
|
|
def __init__(self,loop): |
189 |
|
|
""" |
190 |
|
|
creates a surface with boundary loop |
191 |
|
|
|
192 |
|
|
@param loop: L{CurveLoop} defining the boundary of the surface |
193 |
|
|
""" |
194 |
|
|
super(Surface, self).__init__() |
195 |
|
|
if not isinstance(loop,CurveLoop): |
196 |
|
|
raise TypeError("argument loop needs to be a CurveLoop object.") |
197 |
|
|
self.__loop=loop |
198 |
|
|
def getBoundaryLoop(self): |
199 |
|
|
return self.__loop |
200 |
|
|
def __neg__(self): |
201 |
|
|
return Surface(-self.getBoundaryLoop()) |
202 |
|
|
|
203 |
|
|
class PlaneSurface(Surface): |
204 |
|
|
""" |
205 |
|
|
a plane surface with holes |
206 |
|
|
""" |
207 |
|
|
def __init__(self,loop,holes=[]): |
208 |
|
|
""" |
209 |
|
|
creates a plane surface. |
210 |
|
|
|
211 |
|
|
@param loop: L{CurveLoop} defining the boundary of the surface |
212 |
|
|
@param holes: list of L{CurveLoop} defining holes in the surface. |
213 |
|
|
@note: A CurveLoop defining a hole should not have any lines in common with the exterior CurveLoop. |
214 |
|
|
A CurveLoop defining a hole should not have any lines in common with another CurveLoop defining a hole in the same surface. |
215 |
|
|
""" |
216 |
|
|
super(PlaneSurface, self).__init__(loop) |
217 |
|
|
for i in range(len(holes)): |
218 |
|
|
if not isinstance(holes[i],CurveLoop): |
219 |
|
|
raise TypeError("%i th hole needs to be a CurveLoop object.") |
220 |
|
|
self.__holes=holes |
221 |
|
|
def getHoles(self): |
222 |
|
|
return self.__holes |
223 |
|
|
def __neg__(self): |
224 |
|
|
return PlaneSurface(-self.getBoundaryLoop(),holes=[-h for h in self.getHoles()] ) |
225 |
|
|
|
226 |
|
|
class RuledSurface(Surface): |
227 |
|
|
""" |
228 |
|
|
A ruled surface, i.e., a surface that can be interpolated using transfinite interpolation |
229 |
|
|
""" |
230 |
|
|
def __init__(self,loop): |
231 |
|
|
""" |
232 |
|
|
creates a ruled surface from a |
233 |
|
|
|
234 |
|
|
@param loop: L{CurveLoop} defining the boundary of the surface. There is a restriction of composed of either three or four L{Curve} objects. |
235 |
|
|
""" |
236 |
|
|
if not isinstance(loop,CurveLoop): |
237 |
|
|
raise TypeError("argument loop needs to be a CurveLoop object.") |
238 |
|
|
if len(loop)<3: |
239 |
|
|
raise TypeError("the loop must contain at least three Curves.") |
240 |
|
|
super(RuledSurface, self).__init__(loop) |
241 |
|
|
def __neg__(self): |
242 |
|
|
return RuledSurface(-self.getBoundaryLoop()) |
243 |
|
|
|
244 |
|
|
class SurfaceLoop(Elementary): |
245 |
|
|
""" |
246 |
|
|
a surface loop. It defines the shell of a volume. |
247 |
|
|
|
248 |
|
|
The loop must represent a closed shell, and the L{Surface}s should be oriented consistently. |
249 |
|
|
""" |
250 |
|
|
def __init__(self,*surfaces): |
251 |
|
|
""" |
252 |
|
|
creates a surface loop |
253 |
|
|
""" |
254 |
|
|
super(SurfaceLoop, self).__init__() |
255 |
|
|
for i in surfaces: |
256 |
|
|
if not isinstance(surfaces[i],Curve): |
257 |
|
|
raise TypeError("%s-th argument is not a Curve object.") |
258 |
|
|
self.__surfaces=surfaces |
259 |
|
|
|
260 |
|
|
def getSurfaces(self): |
261 |
|
|
return self.__surfaces |
262 |
|
|
|
263 |
|
|
def __neg__(self): |
264 |
|
|
return SurfaceLoop(-c for c in self.__surfaces[::-1]) |
265 |
|
|
|
266 |
|
|
def __len__(self): |
267 |
|
|
return len(self.__surfaces) |
268 |
|
|
|
269 |
|
|
class Volume(Elementary): |
270 |
|
|
""" |
271 |
|
|
a volume with holes. |
272 |
|
|
""" |
273 |
|
|
def __init__(self,loop,holes=[]): |
274 |
|
|
""" |
275 |
|
|
creates a volume |
276 |
|
|
|
277 |
|
|
@param loop: L{SurfaceLoop} defining the boundary of the surface |
278 |
|
|
@param holes: list of L{SurfaceLoop} defining holes in the surface. |
279 |
|
|
@note: A SurfaceLoop defining a hole should not have any surfaces in common with the exterior SurfaceLoop. |
280 |
|
|
A SurfaceLoop defining a hole should not have any surfaces in common with another SurfaceLoop defining a hole in the same volume. |
281 |
|
|
""" |
282 |
|
|
super(Volume, self).__init__() |
283 |
|
|
if not isinstance(loop,SurfaceLoop): |
284 |
|
|
raise TypeError("argument loop needs to be a SurfaceLoop object.") |
285 |
|
|
for i in range(len(holes)): |
286 |
|
|
if not isinstance(holes[i],SurfaceLoop): |
287 |
|
|
raise TypeError("%i th hole needs to be a SurfaceLoop object.") |
288 |
|
|
self.__loop=loop |
289 |
|
|
self.__holes=holes |
290 |
|
|
def getHoles(self): |
291 |
|
|
return self.__holes |
292 |
|
|
def getSurfaceLoop(self): |
293 |
|
|
return self.__loop |
294 |
|
|
def __neg__(self): |
295 |
|
|
return PlaneSurface(-self.getSurfaceLoop(),holes=[-h for h in self.getHoles()] ) |
296 |
|
|
|
297 |
|
|
class PropertySet(Elementary): |
298 |
|
|
""" |
299 |
|
|
defines a group L{Elementary} objects. |
300 |
|
|
""" |
301 |
|
|
def __init__(self,tag=None,*items): |
302 |
|
|
super(PropertySet, self).__init__() |
303 |
|
|
self.__items=items |
304 |
|
|
self.__tag=tag |