76 |
""" |
""" |
77 |
del _renderer_extensions[:] |
del _renderer_extensions[:] |
78 |
|
|
79 |
|
def proj_params_to_str(proj): |
80 |
|
"Build a string suitable for GDAL describing the given projection" |
81 |
|
str = "" |
82 |
|
if proj is not None: |
83 |
|
for p in proj.GetAllParameters(): |
84 |
|
str += "+" + p + " " |
85 |
|
return str |
86 |
|
|
87 |
# |
# |
88 |
# Base Renderer |
# Base Renderer |
184 |
that methods especially in derived classes have access to the |
that methods especially in derived classes have access to the |
185 |
map if necessary. |
map if necessary. |
186 |
""" |
""" |
|
# Whether the raster layer has already been drawn. See below for |
|
|
# the optimization this is used for |
|
|
seenRaster = True |
|
|
|
|
|
# |
|
|
# This is only a good optimization if there is only one |
|
|
# raster layer and the image covers the entire window (as |
|
|
# it currently does). We note if there is a raster layer |
|
|
# and only begin drawing layers once we have drawn it. |
|
|
# That way we avoid drawing layers that won't be seen. |
|
|
# |
|
|
if Thuban.Model.resource.has_gdal_support(): |
|
|
for layer in self.map.Layers(): |
|
|
if isinstance(layer, RasterLayer) and layer.Visible(): |
|
|
seenRaster = False |
|
|
break |
|
187 |
|
|
188 |
for layer in self.map.Layers(): |
for layer in self.map.Layers(): |
189 |
# if honor_visibility is true, only draw visible layers, |
# if honor_visibility is true, only draw visible layers, |
190 |
# otherwise draw all layers |
# otherwise draw all layers |
191 |
if not self.honor_visibility or layer.Visible(): |
if not self.honor_visibility or layer.Visible(): |
192 |
if isinstance(layer, Layer): |
if isinstance(layer, Layer): |
193 |
if seenRaster: |
for i in self.draw_shape_layer_incrementally(layer): |
194 |
for i in self.draw_shape_layer_incrementally(layer): |
yield True |
|
yield True |
|
195 |
elif isinstance(layer, RasterLayer) \ |
elif isinstance(layer, RasterLayer) \ |
196 |
and Thuban.Model.resource.has_gdal_support(): |
and Thuban.Model.resource.has_gdal_support(): |
197 |
self.draw_raster_layer(layer) |
self.draw_raster_layer(layer) |
|
seenRaster = True |
|
198 |
yield True |
yield True |
199 |
else: |
else: |
200 |
# look it up in the renderer extensions |
# look it up in the renderer extensions |
359 |
scale = self.scale |
scale = self.scale |
360 |
offx, offy = self.offset |
offx, offy = self.offset |
361 |
make_point = self.make_point |
make_point = self.make_point |
362 |
|
|
363 |
for part in points: |
for part in points: |
364 |
result.append([]) |
result.append([]) |
365 |
for x, y in part: |
for x, y in part: |
452 |
offx, offy = self.offset |
offx, offy = self.offset |
453 |
width, height = self.dc.GetSizeTuple() |
width, height = self.dc.GetSizeTuple() |
454 |
|
|
455 |
in_proj = "" |
in_proj = proj_params_to_str(layer.GetProjection()) |
456 |
proj = layer.GetProjection() |
out_proj = proj_params_to_str(self.map.GetProjection()) |
|
if proj is not None: |
|
|
for p in proj.GetAllParameters(): |
|
|
in_proj += "+" + p + " " |
|
457 |
|
|
458 |
out_proj = "" |
# True -- warp the image to the size of the whole screen |
459 |
proj = self.map.GetProjection() |
# False -- only use the bound box of the layer (currently inaccurate) |
460 |
if proj is not None: |
if True: |
461 |
for p in proj.GetAllParameters(): |
#if False: |
462 |
out_proj += "+" + p + " " |
pmin = [0,height] |
463 |
|
pmax = [width, 0] |
464 |
|
else: |
465 |
|
bb = layer.LatLongBoundingBox() |
466 |
|
bb = [[[bb[0], bb[1]], [bb[2], bb[3]],],] |
467 |
|
pmin, pmax = self.projected_points(layer, bb)[0] |
468 |
|
|
469 |
|
#print bb |
470 |
|
#print pmin, pmax |
471 |
|
|
472 |
|
fmin = [max(0, min(pmin[0], pmax[0])) - offx, |
473 |
|
offy - min(height, max(pmin[1], pmax[1]))] |
474 |
|
|
475 |
|
fmax = [min(width, max(pmin[0], pmax[0])) - offx, |
476 |
|
offy - max(0, min(pmin[1], pmax[1]))] |
477 |
|
|
478 |
|
xmin = fmin[0]/self.scale |
479 |
|
ymin = fmin[1]/self.scale |
480 |
|
xmax = fmax[0]/self.scale |
481 |
|
ymax = fmax[1]/self.scale |
482 |
|
|
483 |
xmin = (0 - offx) / self.scale |
width = int(min(width, round(fmax[0] - fmin[0] + 1))) |
484 |
ymin = (offy - height) / self.scale |
height = int(min(height, round(fmax[1] - fmin[1] + 1))) |
|
xmax = (width - offx) / self.scale |
|
|
ymax = (offy - 0) / self.scale |
|
485 |
|
|
486 |
try: |
try: |
487 |
data = ProjectRasterFile(layer.GetImageFilename(), |
options = 0 |
488 |
in_proj, out_proj, |
if layer.UseMask(): options = options | 1 |
489 |
(xmin, ymin, xmax, ymax), "", |
|
490 |
(width, height)) |
project_params = (layer.GetImageFilename(), in_proj, out_proj, |
491 |
except (IOError, AttributeError, ValueError): |
(xmin, ymin, xmax, ymax), "", (width, height), |
492 |
|
options) |
493 |
|
|
494 |
|
data = (width, height, apply(ProjectRasterFile, project_params)) |
495 |
|
|
496 |
|
except (MemoryError, IOError, AttributeError, ValueError): |
497 |
# Why does this catch AttributeError and ValueError? |
# Why does this catch AttributeError and ValueError? |
498 |
# FIXME: The exception should be communicated to the user |
# FIXME: The exception should be communicated to the user |
499 |
# better. |
# better. |
500 |
traceback.print_exc() |
traceback.print_exc() |
501 |
else: |
else: |
502 |
self.draw_raster_data(data, "BMP") |
self.draw_raster_data(fmin[0]+offx, offy-fmax[1], data, "RAW") |
503 |
|
data = None |
|
def draw_raster_data(self, data, format="BMP"): |
|
|
"""Draw the raster image in data onto the DC |
|
504 |
|
|
505 |
The raster image data is a string holding the data in the format |
def draw_raster_data(self, x, y, data, format="BMP"): |
506 |
indicated by the format parameter. The image is assumed to be |
"""Draw the raster image in data onto the DC with the top |
507 |
exactly the size of the dc and to cover it completely. |
left corner at (x,y) |
508 |
|
|
509 |
|
The raster image data is a tuple of the form |
510 |
|
(width, height, (image_data, mask_data)) |
511 |
|
|
512 |
|
holding the image width, height, image data, and mask data. |
513 |
|
mask_data may be None if a mask should not be used. If |
514 |
|
format is 'RAW' the data will be RGB values and the mask |
515 |
|
will be in XMB format. Otherwise, both kinds |
516 |
|
of data are assumed to be in the format specified in format. |
517 |
|
|
518 |
The format parameter is a string with the name of the format. |
The format parameter is a string with the name of the format. |
519 |
The following format names should be used: |
The following format names should be used: |
520 |
|
|
521 |
'BMP' -- Windows Bitmap |
'RAW' -- an array of RGB values (len=3*width*height) |
522 |
'JPEG' -- Jpeg |
'BMP' -- Windows Bitmap |
523 |
|
'JPEG' -- JPEG Image |
524 |
|
|
525 |
The default format is 'bmp'. |
The default format is 'BMP'. |
526 |
|
|
527 |
This method has to be implemented by derived classes. The |
This method has to be implemented by derived classes. The |
528 |
implementation in the derived class should try to support at |
implementation in the derived class should try to support at |