source: anuga_core/source/anuga/pmesh/mesh_interface.py @ 4522

Last change on this file since 4522 was 4285, checked in by duncan, 18 years ago

comments and import fix

File size: 10.7 KB
Line 
1
2#!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
3# Assume that the directory anuga_core/source is included in your pythonpath
4#!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
5
6from anuga.coordinate_transforms.geo_reference import Geo_reference,DEFAULT_ZONE
7from anuga.utilities.polygon import  point_in_polygon ,populate_polygon
8from anuga.utilities.numerical_tools import ensure_numeric
9from Numeric import Float
10from anuga.utilities.polygon import inside_polygon
11
12# This is due to pmesh being a package and a module and
13# the current dir being unknown
14try:
15    from anuga.pmesh.mesh import Mesh
16except ImportError: 
17    from mesh import Mesh
18
19import exceptions
20class PolygonError(exceptions.Exception): pass
21
22def create_mesh_from_regions(bounding_polygon,
23                             boundary_tags,
24                             maximum_triangle_area=None,
25                             filename=None,
26                             interior_regions=None,
27                             interior_holes=None,
28                             poly_geo_reference=None,
29                             mesh_geo_reference=None,
30                             minimum_triangle_angle=28.0,
31                             use_cache=False,
32                             verbose=True):
33    """Create mesh from bounding polygons, and resolutions.
34
35    bounding_polygon is a list of points in Eastings and Northings,
36    relative to the poly_geo_reference.
37
38    Boundary tags is a dictionary of symbolic tags. For every tag there
39    is a list of indices referring to segments associated with that tag.
40    If a segment is omitted it will be assigned the default tag ''.
41
42    maximum_triangle_area is the maximal area per triangle
43    for the bounding polygon, excluding the  interior regions.
44
45    Interior_regions is a list of tuples consisting of (polygon, resolution)
46    for each region to be separately refined.
47   
48    NOTE: If a interior_region is outside the bounding_polygon it should
49    throw an error
50   
51    Interior_holes is a list of ploygons for each hole.
52
53    This function does not allow segments to share points - use underlying
54    pmesh functionality for that
55
56    poly_geo_reference is the geo_reference of the bounding polygon and
57    the interior polygons.
58    If none, assume absolute.  Please pass one though, since absolute
59    references have a zone.
60   
61    mesh_geo_reference is the geo_reference of the mesh to be created.
62    If none is given one will be automatically generated.  It was use
63    the lower left hand corner of  bounding_polygon (absolute)
64    as the x and y values for the geo_ref.
65   
66    Returns the mesh instance if no filename is given
67
68    Note, interior regions should be fully nested, as overlaps may cause
69    unintended resolutions.
70   
71    """
72   
73    # Build arguments and keyword arguments for use with caching or apply.
74    args = (bounding_polygon,
75            boundary_tags)
76   
77    kwargs = {'maximum_triangle_area': maximum_triangle_area,
78              'filename': filename,
79              'interior_regions': interior_regions,
80              'interior_holes': interior_holes,
81              'poly_geo_reference': poly_geo_reference,
82              'mesh_geo_reference': mesh_geo_reference,
83              'minimum_triangle_angle': minimum_triangle_angle,
84              'verbose': verbose}   # FIXME (Ole): Should be bypassed one day
85                                    # What should be bypassed? Verbose?
86   
87    #print 'kwargs', kwargs
88
89    # Call underlying engine with or without caching
90    if use_cache is True:
91        try:
92            from anuga.caching import cache
93        except:
94            msg = 'Caching was requested, but caching module'+\
95                  'could not be imported'
96            raise msg
97
98
99        m = cache(_create_mesh_from_regions,
100                  args, kwargs,
101                  verbose=verbose,
102                  compression=False)
103    else:
104        m = apply(_create_mesh_from_regions,
105                  args, kwargs)
106
107    return m   
108       
109
110
111def _create_mesh_from_regions(bounding_polygon,
112                              boundary_tags,
113                              maximum_triangle_area=None,
114                              filename=None,                             
115                              interior_regions=None,
116                              interior_holes=None,
117                              poly_geo_reference=None,
118                              mesh_geo_reference=None,
119                              minimum_triangle_angle=28.0,
120                              verbose=True):
121    """_create_mesh_from_regions - internal function.
122
123    See create_mesh_from_regions for documentation.
124    """
125    #FIXME (OLE-DSG)
126    # check the segment indexes - throw an error if they are out of bounds
127    #(DSG) Yes!
128
129   
130    #In addition I reckon the polygons could be of class Geospatial_data
131    #(DSG) If polygons were classes caching would break in places.
132
133    # First check that interior polygons are fully contained in bounding
134    # polygon
135    #Note, Both poly's have the same geo_ref, therefore don't take into account
136    # geo_ref
137
138    # Simple check
139    bounding_polygon = ensure_numeric(bounding_polygon, Float)
140    msg = 'Bounding polygon must be a list of points or an Nx2 array'
141    assert len(bounding_polygon.shape) == 2, msg
142    assert bounding_polygon.shape[1] == 2, msg   
143
144    #
145    if interior_regions is not None:       
146        # Test that all the interior polygons are inside the bounding_poly
147        for interior_polygon, res in interior_regions:
148            indices = inside_polygon(interior_polygon, bounding_polygon,
149                                     closed = True, verbose = False)
150   
151            if len(indices) <> len(interior_polygon): 
152                msg = 'Interior polygon %s is outside bounding polygon: %s'\
153                      %(str(interior_polygon), str(bounding_polygon))
154                raise PolygonError, msg
155   
156# the following segment of code could be used to Test that all the
157# interior polygons are inside the bounding_poly... however it might need
158# to be change a bit   
159#
160#count = 0
161#for i in range(len(interior_regions)):
162#    region = interior_regions[i]
163#    interior_polygon = region[0]
164#    if len(inside_polygon(interior_polygon, bounding_polygon,
165#                   closed = True, verbose = False)) <> len(interior_polygon):
166#        print 'WARNING: interior polygon %d is outside bounding polygon' %(i)
167#        count += 1
168
169#if count == 0:
170#    print 'interior regions OK'
171#else:
172#    print 'check out your interior polygons'
173#    print 'check %s in production directory' %figname
174#    import sys; sys.exit()
175   
176
177    if interior_holes is not None:       
178        # Test that all the interior polygons are inside the bounding_poly
179        for interior_polygon in interior_holes:
180            indices = inside_polygon(interior_polygon, bounding_polygon,
181                                     closed = True, verbose = False)
182   
183            if len(indices) <> len(interior_polygon): 
184                msg = 'Interior polygon %s is outside bounding polygon: %s'\
185                      %(str(interior_polygon), str(bounding_polygon))
186                raise PolygonError, msg
187
188    # Resolve geo referencing       
189    if mesh_geo_reference is None:
190        xllcorner = min(bounding_polygon[:,0])
191        yllcorner = min(bounding_polygon[:,1])   
192        #
193        if poly_geo_reference is None:
194            zone = DEFAULT_ZONE
195        else:
196            zone = poly_geo_reference.get_zone()
197            [(xllcorner,yllcorner)] = poly_geo_reference.get_absolute( \
198            [(xllcorner,yllcorner)])
199        # create a geo_ref, based on the llc of the bounding_polygon
200        mesh_geo_reference = Geo_reference(xllcorner = xllcorner,
201                                           yllcorner = yllcorner,
202                                           zone = zone)
203
204    m = Mesh(geo_reference=mesh_geo_reference)
205
206    # Do bounding polygon
207    m.add_region_from_polygon(bounding_polygon,
208                              tags=boundary_tags,
209                              geo_reference=poly_geo_reference)
210
211    # Find one point inside region automatically
212    if interior_regions is not None:
213        excluded_polygons = []       
214        for polygon, res in interior_regions:
215            excluded_polygons.append( polygon )
216    else:
217        excluded_polygons = None
218
219    # Convert bounding poly to absolute values
220    # this sort of thing can be fixed with the geo_points class
221    if poly_geo_reference is not None:
222        bounding_polygon_absolute = \
223            poly_geo_reference.get_absolute(bounding_polygon)
224    else:
225        bounding_polygon_absolute = bounding_polygon
226   
227    inner_point = point_in_polygon(bounding_polygon_absolute)
228    inner = m.add_region(inner_point[0], inner_point[1])
229    inner.setMaxArea(maximum_triangle_area)
230
231    # Do interior regions
232#    if interior_regions is not None:   
233#        for polygon, res in interior_regions:
234#            m.add_region_from_polygon(polygon,
235#                                      geo_reference=poly_geo_reference)
236#            # convert bounding poly to absolute values
237#            if poly_geo_reference is not None:
238#                polygon_absolute = \
239#                    poly_geo_reference.get_absolute(polygon)
240#            else:
241#                polygon_absolute = polygon
242#            inner_point = point_in_polygon(polygon_absolute)
243#            region = m.add_region(inner_point[0], inner_point[1])
244#            region.setMaxArea(res)
245           
246           
247    if interior_regions is not None:   
248        for polygon, res in interior_regions:
249            m.add_region_from_polygon(polygon,
250                                      max_triangle_area=res,
251                                      geo_reference=poly_geo_reference)
252   
253           
254    # Do interior holes
255    if interior_holes is not None:   
256        for polygon in interior_holes:
257            m.add_hole_from_polygon(polygon,
258                                    geo_reference=poly_geo_reference)
259       
260
261
262
263    # NOTE (Ole): This was moved here as it is annoying if mesh is always
264    # stored irrespective of whether the computation
265    # was cached or not. This caused Domain to
266    # recompute as it has meshfile as a dependency
267
268    # Decide whether to store this mesh or return it   
269    if filename is None:
270        return m
271    else:
272        if verbose: print 'Generating mesh to file "%s"' %filename
273        m.generate_mesh(minimum_triangle_angle=minimum_triangle_angle,
274                        verbose=verbose)
275        m.export_mesh_file(filename)
276
277
Note: See TracBrowser for help on using the repository browser.