Example #1
0
    def extent(self, identifiers=None):
        """Calculate extent using ogr GetExtent function
        """
        layer = mapnik.Layer(self.layer_name, detect_prj(self.prj))

        layer.datasource = mapnik.Shapefile(
            file=self.layer_filename)

        ds = osgeo.ogr.Open(self.layer_filename)
        lyr = ds.GetLayer()
        lyr.ResetReading()
        w, e, s, n = lyr.GetExtent()

        w, s = transform(
            Proj(detect_prj(self.prj)), google_projection, w, s)
        e, n = transform(
            Proj(detect_prj(self.prj)), google_projection, e, n)

        return {
            'north': n,
            'west': w,
            'south': s,
            'east': e}
Example #2
0
    def layer(self, layer_ids=None, request=None):
        """Return layer and styles for a shapefile.

        http://127.0.0.1:8000/map/workspace/1/wms/?LAYERS=basic&SERVICE=
        WMS&VERSION=1.1.1&REQUEST=GetMap&STYLES=&EXCEPTIONS=application%
        2Fvnd.ogc.se_inimage&FORMAT=image%2Fjpeg&SRS=EPSG%3A900913&BBOX=
        523838.00391791,6818214.5267836,575010.91942212,6869720.7532931&
        WIDTH=140&HEIGHT=140
        """
        layers = []
        styles = {}
        layer = mapnik.Layer(self.layer_name, detect_prj(self.prj))
        # TODO: ^^^ translation!
        logging.debug("Giving shapefile %s to a mapnik layer...",
                      self.layer_filename)
        layer.datasource = mapnik.Shapefile(
            file=self.layer_filename)

        if self.legend_id is not None:
            legend = self._legend_object
            style = legend.mapnik_style(
                value_field=str(self.value_field))
        else:
            # Show layer with default legend.
            style = self._default_mapnik_style()

        style_name = str('Area style %s::%s::%s' % (
                self.layer_filename,
                self.legend_id,
                self.value_field))
        styles[style_name] = style
        layer.styles.append(style_name)
        layers = [layer]
        logging.debug("Giving shapefile %s as layer to mapnik...",
                      self.layer_filename)
        return layers, styles
Example #3
0
    def search(self, x, y, radius=None):
        """
        Search area, line or point.

        Make sure that value_field, search_property_id,
        search_property_name are valid columns in your shapefile.

        x,y are google coordinates

        Note: due to mapnik #503 (http://trac.mapnik.org/ticket/503)
        the search does not work for lines and points. So the
        implementation was done with shapely.

        """
        logger.debug("Searching coordinates (%0.2f, %0.2f) radius %r..." %
                     (x, y, radius))

        if not self.search_property_name:
            # We don't have anything to return, so don't search.
            return []

        if radius is not None:
            # Manually make radius smaller

            # RG, way later: it used to say 0.2 on the line below, but
            # there were complaints saying that this was too
            # small. From some manual testing, 1 (the default) is too
            # large. I'll put 0.8. Obviously a very well argued value.
            logger.debug("Adjusting radius...")
            radius = radius * 0.8

        transformed_x, transformed_y = transform(
            google_projection, Proj(detect_prj(self.prj)), x, y)
        query_point = Point(transformed_x, transformed_y)

        ds = osgeo.ogr.Open(self.layer_filename)
        try:
            lyr = ds.GetLayer()
        except AttributeError:
            # #3033
            # This one occurs when the file does not exist.
            logger.error("The search function crashed. Probably due "
                         "to a missing shapefile.")
            return []

        if radius is not None:

            # The radius needs to be transformed as well, but how?
            # A transformed square will no longer be a square!
            # This needs further attention...

            transformed_x_radius, transformed_y_radius = transform(
                google_projection, Proj(detect_prj(self.prj)),
                x + radius, y + radius)

            radius = max(abs(transformed_x - transformed_x_radius),
                         abs(transformed_y - transformed_y_radius))

            lyr.SetSpatialFilterRect(
                transformed_x - radius,
                transformed_y - radius,
                transformed_x + radius,
                transformed_y + radius)

        lyr.ResetReading()
        feat = lyr.GetNextFeature()

        results = []

        while feat is not None:
            geom = feat.GetGeometryRef()
            if geom:
                item = loads(geom.ExportToWkt())
                distance = query_point.distance(item)
                feat_items = feat.items()

                if not radius or (radius is not None and distance < radius):
                    # Add stripped keys, because column names can contain
                    # spaces after the 'real' name.
                    for key in feat_items.keys():
                        feat_items[key.strip()] = feat_items[key]

                    # Found an item.
                    if self.search_property_name not in feat_items:
                        # This means that the search_property_name is not a
                        # valid field in the shapefile dbf.
                        logger.error(
                            ('Search: The field "%s" cannot be found in '
                             'shapefile "%s". Available fields: %r'
                             'Check your settings in '
                             'lizard_shape.models.Shape.') %
                            (self.search_property_name, self.layer_name,
                             feat_items.keys()))
                        break  # You don't have to search other rows.
                    name = str(feat_items[self.search_property_name])

                    if self.display_fields:
                        if self.display_fields[0]['field'] not in feat_items:
                            # This means that the value_field is not a
                            # valid field in the shapefile dbf.
                            logger.error(
                                ('Search: The field "%s" cannot be found in '
                                 'shapefile "%s". Check display_fields. '
                                 'Options are: %s') %
                                (self.display_fields[0]['field'],
                                 self.layer_name,
                                 feat_items.keys()))
                            break  # You don't have to search other rows.
                        name += ' - %s=%s' % (
                            self.display_fields[0]['name'],
                            str(float_to_string(feat_items[
                                        self.display_fields[0]['field']])))

                    result = {'distance': distance,
                              'name': name,
                              'workspace_item': self.workspace_item}
                    try:
                        result.update(
                            {'google_coords':
                                 transform(Proj(detect_prj(self.prj)),
                                           google_projection,
                                           *item.coords[0])})
                    except NotImplementedError:
                        logger.warning(
                            "Got a NotImplementedError while transforming "
                            "coordinates from %s to google with pyproj "
                            "for shapefile %s. Not returning google "
                            "coordinates.",
                            self.prj, self.shape)

                    if (self.search_property_id and
                        self.search_property_id in feat_items):
                        result.update(
                            {'identifier':
                                 {'id': feat_items[self.search_property_id]}})
                    else:
                        logger.error("Problem with search_property_id: %s. "
                                     "List of available properties: %r" %
                                     (self.search_property_id,
                                      feat_items.keys()))
                    results.append(result)
            feat = lyr.GetNextFeature()
        results = sorted(results, key=lambda a: a['distance'])
        if len(results) > MAX_SEARCH_RESULTS:
            logger.info('A lot of results found (%d), just taking top %s.',
                        len(results), MAX_SEARCH_RESULTS)
        return results[:MAX_SEARCH_RESULTS]