Beispiel #1
0
    def testConvertToString(self):
        """ensure styles can be created and output to strings
        in a round trip"""
        input_string = """
            STYLE
                SIZE 7.25
                COLOR 255 0 0
                OFFSET 10.5 20.75
            END
        """

        new_style = mapscript.fromstring(input_string)
        assert new_style.size == 7.25
        assert new_style.color.red == 255
        assert new_style.color.green == 0
        assert new_style.color.blue == 0

        assert new_style.offsetx == 10.5
        assert new_style.offsety == 20.75

        output_string = new_style.convertToString()
        new_style2 = mapscript.fromstring(output_string)

        # ensure attributes are output as doubles
        assert new_style.size == 7.25
        assert new_style2.offsetx == 10.5
        assert new_style2.offsety == 20.75
Beispiel #2
0
 def __getMapObj(self):
     path = self.__pathToShapeFile
     shapePath, shapeName = os.path.split(path)
     shapeName = shapeName.split('.')[0]
     shpfile = ms.shapefileObj(path,-1) # "value of -1 to open an existing shapefile"-ms.docs
     #print self.projection
     src_prj = ms.projectionObj(self.projection)
     shpfile.bounds.project(src_prj,self.targetProj)
     if not self.idVar:
         mapobj = ms.fromstring(MAPFILE%{'shapePath':shapePath,'shapeName':shapeName,'color':DEFAULT_COLOR,'projString':self.projection,'size':self.size})
     else:
         mapobj = ms.fromstring(MAPFILE%{'shapePath':self.__workSpace,'shapeName':'dtm','color':'[dtmValue]','projString':self.projection,'size':self.size})
         
     mapobj.extent = shpfile.bounds
     return mapobj
Beispiel #3
0
def runTiler(shpfile,outdir,config,zoom=None):
    if not os.path.exists(shpfile):
        raise StandardError('Shape File: %s, does not exist!'%shpfile)
    if not os.path.exists(outdir):
        os.mkdir(outdir)

    shapePath, shapeName = os.path.split(shpfile)
    shapeName = shapeName.split('.')[0]

    #c = Classifier(shapePath,shapeName)
    #c.CheckUID(config['IdName'])
    #mapProj = ms.projectionObj(config['projString'])

    shpfile = ms.shapefileObj(shpfile,-1) # "value of -1 to open an existing shapefile"-ms.docs
    bounds = shpfile.bounds
    return bounds
    bounds.project(mapProj,GMERC)
    mapobj = ms.fromstring(MAPFILE%{'shapePath':shapePath,'shapeName':shapeName,'classes':c(),'projString':config['projString']})
    mapobj.extent = bounds
    mapobj.draw().save('f.png')
    t = Tiler(mapobj,outdir,zoom)

    print "extents: "
    bounds.project(GMERC,WGS)
    print (bounds.maxx + bounds.minx) / 2
    print (bounds.maxy + bounds.miny) / 2

    return c,t
Beispiel #4
0
    def testRuntimeSubstitutions(self):
        """
        For supported parameters see https://mapserver.org/cgi/runsub.html#parameters-supported
        """
        s = """
MAP
    WEB
        VALIDATION
            'key1' '.*'
            'default_key1' 'Test Title'
        END
        METADATA
            "wms_title" "%key1%"
        END
    END
    LAYER
        TYPE POINT
        FILTER ([size]<%my_filter%)
        VALIDATION
            'my_filter' '^[0-9]$'
        END
    END
END
        """
        map = mapscript.fromstring(s)

        d = {"key1": "New Title", "my_filter": "3"}
        map.applySubstitutions(d)

        assert map.web.metadata["wms_title"] == "New Title"
        assert map.getLayer(0).getFilterString() == "([size]<3)"
    def legend_img_from_style(self, style_name, subclass, w, h):
        with codecs.open(path.join(LAYERS_DEF_STYLES_PATH, style_name + '.xml'), encoding='utf-8') as style_file:
            map_xml = style_file.read()

        E = ElementMaker()
        buf = StringIO()
        emap = etree.fromstring(map_xml)
        esymbolset = E.symbolset(resource_filename('nextgisweb_mapserver', 'symbolset'))
        emap.insert(0, esymbolset)


        # PIXMAP и SVG маркеры
        for type_elem in emap.iterfind('./symbol/type'):
            if type_elem.text not in ('pixmap', 'svg'):
                continue
            symbol = type_elem.getparent()
            image = symbol.find('./image')
            marker = Marker.filter_by(keyname=image.text).one()
            image.text = self.env.file_storage.filename(marker.fileobj)

        # FONTS
        fonts_e = E.fontset(self.env.mapserver.settings['fontset'])
        emap.insert(0, fonts_e)

        mapf_map = Map().from_xml(emap)
        mapfile(mapf_map, buf)
        mapobj = mapscript.fromstring(buf.getvalue().encode('utf-8'))
        layerobj = mapobj.getLayer(0)
        classobj = layerobj.getClass(subclass)
        gdimg = classobj.createLegendIcon(mapobj, layerobj, w, h)

        mem_png = StringIO(gdimg.saveToString())
        img = Image.open(mem_png)

        return img
Beispiel #6
0
 def save_to_mapfile(self,out_path):
     path = self.__pathToShapeFile
     shapePath, shapeName = os.path.split(path)
     shapeName = shapeName.split('.')[0]
     shpfile = ms.shapefileObj(path,-1) # "value of -1 to open an existing shapefile"-ms.docs
     #print self.projection
     src_prj = ms.projectionObj(self.projection)
     shpfile.bounds.project(src_prj,self.targetProj)
     mapobj = ms.fromstring(MAPFILE%{'shapePath':shapePath,'shapeName':shapeName,'color':'[dtmValue]','projString':self.projection,'size':self.size})
     mapobj.extent = shpfile.bounds
     mapobj.save(out_path)
Beispiel #7
0
	def __init__(self, mapfile_string, label_col_index, mapserver_layers,
			min_zoom=0, max_zoom=100, label_spacing=1024, img_w=256, img_h=256, tile_buffer=256,
			info_cache_name=None):
		tiletree.Renderer.__init__(self, img_w, img_h, info_cache_name)
		self.mapfile = mapscript.fromstring(mapfile_string)
		self.label_col_index = label_col_index
		self.mapserver_layers = mapserver_layers
		self.label_spacing = label_spacing
		self.img_w = img_w
		self.img_h = img_h
		self.tile_buffer = tile_buffer
		self.min_zoom = min_zoom
		self.max_zoom = max_zoom
		self.label_classes = {}
		self.blank_img_bytes = None
		self.font_faces = {}
Beispiel #8
0
    def testDefaultSubstitutions(self):
        s = """
MAP
    WEB
        VALIDATION
            'key1' '.*'
            'default_key1' 'Test Title'
        END
        METADATA
            "wms_title" "%key1%"
        END
    END
END
        """
        map = mapscript.fromstring(s)
        map.applyDefaultSubstitutions()
        assert map.web.metadata["wms_title"] == "Test Title"
Beispiel #9
0
    def testPointDraw(self):
        """Can create a point, add to a layer, and draw it directly"""

        map_string = """
        MAP
            EXTENT 0 0 90 90
            SIZE 500 500

            SYMBOL
            NAME "circle"
            TYPE ELLIPSE
            POINTS 1 1 END
            FILLED true
            END

            LAYER
            NAME "punkt"
            STATUS ON
            TYPE POINT
            END

        END"""

        test_map = mapscript.fromstring(map_string)
        layer = test_map.getLayerByName('punkt')
        cls = mapscript.classObj()
        style = mapscript.styleObj()
        style.outlinecolor.setHex('#00aa00ff')
        style.size = 10
        style.setSymbolByName(test_map, 'circle')

        cls.insertStyle(style)
        class_idx = layer.insertClass(cls)
        point = mapscript.pointObj(45, 45)

        img = test_map.prepareImage()
        point.draw(test_map, layer, img, class_idx, "test")

        filename = 'testDrawPoint.png'
        with open(filename, 'wb') as fh:
            img.write(fh)

        if have_image:
            pyimg = Image.open(filename)
            assert pyimg.size == (500, 500)
Beispiel #10
0
	def __init__(self, mapfile_template, layers, img_w=256, img_h=256, img_buffer=0, min_zoom=0, max_zoom=19,
			cache_fulls=True, srs='EPSG:3857', trust_cutter=False, tile_buffer=0,
			info_cache_name=None, skip_info=False):
		Renderer.__init__(self, img_w, img_h, info_cache_name=info_cache_name)
		self.mapfile_template=mapfile_template
		self.layers=layers
		self.img_buffer=img_buffer
		self.min_zoom = min_zoom
		self.max_zoom = max_zoom
		self.cache_fulls=cache_fulls
		self.srs = srs
		self.trust_cutter = trust_cutter
		self.tile_buffer = tile_buffer
		self.skip_info = skip_info

		#creating a mapfile leaks memory, so only create it once
		template_args = {
			#'wkt': shapely.wkt.dumps(geometry),
			#'shapefile_path' : shapefile_path
		}
		self.mapfile = mapscript.fromstring(self.mapfile_template % template_args)
		self.mapfile.loadOWSParameters(self.build_request(0, 0, 10, 10))
Beispiel #11
0
 def __init__(self,
              mapfile_string,
              label_col_index,
              mapserver_layers,
              min_zoom=0,
              max_zoom=100,
              label_spacing=1024,
              img_w=256,
              img_h=256,
              tile_buffer=256,
              info_cache_name=None):
     tiletree.Renderer.__init__(self, img_w, img_h, info_cache_name)
     self.mapfile = mapscript.fromstring(mapfile_string)
     self.label_col_index = label_col_index
     self.mapserver_layers = mapserver_layers
     self.label_spacing = label_spacing
     self.img_w = img_w
     self.img_h = img_h
     self.tile_buffer = tile_buffer
     self.min_zoom = min_zoom
     self.max_zoom = max_zoom
     self.label_classes = {}
     self.blank_img_bytes = None
     self.font_faces = {}
Beispiel #12
0
def application(env, start_response):
    """WSGI application for WMS/WCS"""

    for key in MAPSERV_ENV:
        if key in env:
            os.environ[key] = env[key]
        else:
            os.unsetenv(key)

    layer = None
    mapfile_ = None

    request = mapscript.OWSRequest()
    request.loadParams()

    lang_ = request.getValueByName('LANG')
    service_ = request.getValueByName('SERVICE')
    request_ = request.getValueByName('REQUEST')
    layers_ = request.getValueByName('LAYERS')
    layer_ = request.getValueByName('LAYER')
    coverageid_ = request.getValueByName('COVERAGEID')

    if lang_ is not None and lang_ in ['f', 'fr', 'fra']:
        lang = 'fr'
    else:
        lang = 'en'
    if layers_ is not None:
        layer = layers_
    elif layer_ is not None:
        layer = layer_
    elif coverageid_ is not None:
        layer = coverageid_
    else:
        layer = None
    if service_ is None:
        service_ = 'WMS'

    if layer is not None and len(layer) == 0:
        layer = None

    time_error = None

    LOGGER.debug('service: {}'.format(service_))
    LOGGER.debug('language: {}'.format(lang))

    if layer == 'GODS':
        banner = os.path.join(BASEDIR, 'geomet_mapfile/resources',
                              'other/banner.txt')
        with open(banner) as fh:
            start_response('200 OK', [('Content-Type', 'text/plain')])
            msg = fh.read()
            return ['{}'.format(msg).encode()]

    # fetch mapfile from store or from disk
    if MAPFILE_STORAGE == 'file':
        # if a single layer is specified in LAYER param fetch mapfile from disk
        if layer is not None and ',' not in layer:
            mapfile_ = '{}/mapfile/geomet-weather-{}.map'.format(
                BASEDIR, layer)
        # if mapfile_ is None or its path does not exist
        if mapfile_ is None or not os.path.exists(mapfile_):
            mapfile_ = '{}/mapfile/geomet-weather.map'.format(BASEDIR)
        # if mapfile_ path does not exist set mapfile_ to None
        if not os.path.exists(mapfile_):
            mapfile_ = None
    elif MAPFILE_STORAGE == 'store':
        st = load_plugin('store', {'type': STORE_TYPE, 'url': STORE_URL})
        if layer is not None and ',' not in layer:
            mapfile_ = st.get_key('{}_mapfile'.format(layer))
        if mapfile_ is None:
            mapfile_ = st.get_key('geomet-weather_mapfile')

    # if no mapfile at all is found return a Unsupported service exception
    if not mapfile_:
        start_response('400 Bad Request',
                       [('Content-Type', 'application/xml')])
        msg = 'Unsupported service'
        return [SERVICE_EXCEPTION.format(msg).encode()]

    # if requesting GetCapabilities for entire service, return cache
    if request_ == 'GetCapabilities' and layer is None:
        LOGGER.debug('Requesting global mapfile')
        if service_ == 'WMS':
            filename = 'geomet-weather-ogc-wms-1.3.0-capabilities-{}.xml'.format(
                lang)  # noqa
            cached_caps = os.path.join(BASEDIR, 'mapfile', filename)

        if os.path.isfile(cached_caps):
            start_response('200 OK', [('Content-Type', 'application/xml')])
            with io.open(cached_caps, 'rb') as fh:
                return [fh.read()]
    else:
        LOGGER.debug('Requesting layer mapfile')
        if os.path.exists(mapfile_):
            # read mapfile from filepath
            LOGGER.debug('Loading mapfile {} from disk'.format(mapfile_))
            mapfile = mapscript.mapObj(mapfile_)
        else:
            # read mapfile from string returned from store
            LOGGER.debug('Loading {}_mapfile from store'.format(
                layer if layer else 'geomet-mapfile'))
            mapfile = mapscript.fromstring(mapfile_)

        layerobj = mapfile.getLayerByName(layer)
        time = request.getValueByName('TIME')
        ref_time = request.getValueByName('DIM_REFERENCE_TIME')

        if any(time_param == '' for time_param in [time, ref_time]):
            time_error = "Valeur manquante pour la date ou l'heure / Missing value for date or time"  # noqa
            start_response('200 OK', [('Content-type', 'text/xml')])
            return [SERVICE_EXCEPTION.format(time_error).encode()]

        if time is None:
            time = layerobj.getMetaData('wms_timedefault')
        if ref_time is None:
            ref_time = layerobj.getMetaData('wms_reference_time_default')

        try:
            filepath, url = get_data_path(layer, time, ref_time)
        except TileNotFoundError as err:
            LOGGER.error(err)
            time_error = (
                'NoMatch: Date et heure invalides / Invalid date and time')
            start_response('200 OK', [('Content-type', 'text/xml')])
            return [SERVICE_EXCEPTION.format(time_error).encode()]

        try:
            if request_ in ['GetMap', 'GetFeatureInfo']:
                if all([
                        filepath.startswith(os.sep),
                        not os.path.isfile(filepath)
                ]):
                    LOGGER.debug('File is not on disk: {}'.format(filepath))
                    if not ALLOW_LAYER_DATA_DOWNLOAD:
                        LOGGER.error('layer data downloading not allowed')
                        _error = 'data not found'
                        start_response('500 Internal Server Error',
                                       [('Content-type', 'text/xml')])
                        return [SERVICE_EXCEPTION.format(_error).encode()]

                    if not os.path.exists(os.path.dirname(filepath)):
                        LOGGER.debug('Creating the filepath')
                        os.makedirs(os.path.dirname(filepath))
                    LOGGER.debug('Downloading url: {}'.format(url))
                    with urlopen(url) as r:
                        with open(filepath, 'wb') as fh:
                            fh.write(r.read())

            layerobj.data = filepath

        except ValueError as err:
            LOGGER.error(err)
            _error = (
                'NoApplicableCode: Donnée non disponible / Data not available')
            start_response('500 Internal Server Error',
                           [('Content-type', 'text/xml')])
            return [SERVICE_EXCEPTION.format(_error).encode()]

        if request_ == 'GetCapabilities' and lang == 'fr':
            metadata_lang(mapfile, layer.split(','), lang)

    mapscript.msIO_installStdoutToBuffer()

    # giving we don't use properly use tileindex due to performance issues
    # we need to remove the time parameter from the request for uvraster layer
    if 'time' in env['QUERY_STRING'].lower():
        query_string = env['QUERY_STRING'].split('&')
        query_string = [x for x in query_string if 'time' not in x.lower()]
        request.loadParamsFromURL('&'.join(query_string))
    else:
        request.loadParamsFromURL(env['QUERY_STRING'])

    try:
        LOGGER.debug('Dispatching OWS request')
        mapfile.OWSDispatch(request)
    except (mapscript.MapServerError, IOError) as err:
        # let error propagate to service exception
        LOGGER.error(err)
        pass

    headers = mapscript.msIO_getAndStripStdoutBufferMimeHeaders()

    headers_ = [
        ('Content-Type', headers['Content-Type']),
    ]

    content = mapscript.msIO_getStdoutBufferBytes()

    start_response('200 OK', headers_)

    return [content]
Beispiel #13
0
    def _mapobj(self, features):
        # tmpf = NamedTemporaryFile(suffix='.map')
        # buf = codecs.open(tmpf.name, 'w', 'utf-8')
        buf = StringIO()

        fieldnames = [f.keyname for f in self.parent.fields]

        E = ElementMaker()

        # Настраиваем map
        emap = etree.fromstring(self.xml)

        map_setup = [
            E.size(width='800', height='600'),
            E.maxsize('4096'),
            E.imagecolor(red='255', green='255', blue='255'),
            E.imagetype('PNG'),
            E.outputformat(E.name('png'), E.extension('png'),
                           E.mimetype('image/png'), E.driver('AGG/PNG'),
                           E.imagemode('RGBA'),
                           E.formatoption('INTERLACE=OFF')),
            E.web(
                E.metadata(
                    E.item(key='wms_onlineresource',
                           value='http://localhost/'),
                    E.item(key='wfs_onlineresource',
                           value='http://localhost/'),
                    E.item(key='ows_title', value='nextgisweb'),
                    E.item(key='wms_enable_request', value='*'),
                    E.item(key='wms_srs', value='EPSG:3857'))),
            E.extent(minx='-180', miny='-90', maxx='180', maxy='90'),
            E.projection("+init=epsg:4326"),
            E.fontset(env.mapserver.options['fontset']),
            E.symbolset(resource_filename('nextgisweb_mapserver', 'symbolset'))
        ]

        for i in reversed(map_setup):
            emap.insert(0, i)

        # Настраиваем layer
        elayer = emap.find('./layer')

        layer_setup = [
            E.name('main'),
            E.type({
                GEOM_TYPE.POINT: 'point',
                GEOM_TYPE.LINESTRING: 'line',
                GEOM_TYPE.POLYGON: 'polygon',
                GEOM_TYPE.MULTIPOINT: 'point',
                GEOM_TYPE.MULTILINESTRING: 'line',
                GEOM_TYPE.MULTIPOLYGON: 'polygon',
                GEOM_TYPE.POINTZ: 'point',
                GEOM_TYPE.LINESTRINGZ: 'line',
                GEOM_TYPE.POLYGONZ: 'polygon',
                GEOM_TYPE.MULTIPOINTZ: 'point',
                GEOM_TYPE.MULTILINESTRINGZ: 'line',
                GEOM_TYPE.MULTIPOLYGONZ: 'polygon'
            }[self.parent.geometry_type]),
            E.template('dummy.html'),
            E.projection("+init=epsg:3857"),
            E.extent(minx='-20037508.34',
                     miny='-20037508.34',
                     maxx='20037508.34',
                     maxy='20037508.34'),
            E.status('DEFAULT'),
        ]

        for e in reversed(layer_setup):
            elayer.insert(0, e)

        # PIXMAP & SVG markers: replace to rectangle
        for type_elem in emap.iterfind('./symbol/type'):
            if type_elem.text not in ('pixmap', 'svg'):
                continue

            symbol = type_elem.getparent()
            image = symbol.find('./image')

            # TODO: Set path to SVG marker library
            # image.text = ...

            type_elem.text = 'vector'
            image.tag = 'points'
            image.text = '0 0 0 1 1 1 1 0 0 0'
            symbol.append(E.filled('true'))

        obj = Map().from_xml(emap)
        mapfile(obj, buf)

        val = buf.getvalue()
        mapobj = mapscript.fromstring(val)

        layer = mapobj.getLayer(0)

        items = ','.join(fieldnames)
        layer.setProcessingKey('ITEMS', items)

        layer.setProcessingKey('APPROXIMATION_SCALE', 'full')
        layer.setProcessingKey('LABEL_NO_CLIP', 'true')

        for f in features:
            # MapServer has problems while rendering 3D geometries and
            # geometries with duplicate points.
            ogr_geom = f.geom.ogr
            ogr_geom.Set3D(False)
            ogr_geom.Simplify(0)
            shape = mapscript.shapeObj.fromWKT(ogr_geom.ExportToIsoWkt())

            shape.initValues(len(fieldnames))
            for i, fld in enumerate(fieldnames, start=0):
                v = f.fields[fld]

                if v is None:
                    # TODO: Возможно есть более удачный способ
                    # передавать mapserver пустые значения, но
                    # пока он мне не известен
                    v = ""
                elif isinstance(v, str):
                    pass
                elif isinstance(v, bytes):
                    v = v.decode('utf-8')
                elif isinstance(v, datetime.date):
                    v = v.strftime(r'%Y-%m-%dT%H:%M:%S')
                else:
                    v = repr(v)

                shape.setValue(i, v)

            layer.addFeature(shape)

        return mapobj
Beispiel #14
0
    def _mapobj(self, features):
        # tmpf = NamedTemporaryFile(suffix='.map')
        # buf = codecs.open(tmpf.name, 'w', 'utf-8')
        buf = StringIO()

        fieldnames = map(lambda f: f.keyname, self.layer.fields)

        E = ElementMaker()

        # Настраиваем map
        emap = etree.fromstring(self.xml)

        map_setup = [
            E.size(width='800', height='600'),
            E.maxsize('4096'),
            E.imagecolor(red='255', green='255', blue='255'),
            E.imagetype('PNG'),
            E.outputformat(
                E.name('png'),
                E.extension('png'),
                E.mimetype('image/png'),
                E.driver('AGG/PNG'),
                E.imagemode('RGBA'),
                E.formatoption('INTERLACE=OFF')
            ),
            E.web(
                E.metadata(
                    E.item(
                        key='wms_onlineresource',
                        value='http://localhost/'
                    ),
                    E.item(
                        key='wfs_onlineresource',
                        value='http://localhost/'
                    ),
                    E.item(
                        key='ows_title',
                        value='nextgisweb'
                    ),
                    E.item(
                        key='wms_enable_request',
                        value='*'
                    ),
                    E.item(
                        key='wms_srs',
                        value='EPSG:3857'
                    )
                )
            ),
            E.extent(minx='-180', miny='-90', maxx='180', maxy='90'),
            E.projection("+init=epsg:4326"),
            E.fontset(env.mapserver_style.settings['fontset']),
            E.symbolset(resource_filename(
                'nextgisweb_mapserver', 'symbolset'
            ))
        ]

        for i in reversed(map_setup):
            emap.insert(0, i)

        # Настраиваем layer
        elayer = emap.find('./layer')

        layer_setup = [
            E.name('main'),
            E.type({
                "POINT": 'point',
                'LINESTRING': 'line',
                'POLYGON': 'polygon'
            }[self.layer.geometry_type]),
            E.template('dummy.html'),
            E.projection("+init=epsg:3857"),
            E.extent(
                minx='-20037508.34',
                miny='-20037508.34',
                maxx='20037508.34',
                maxy='20037508.34'
            ),
        ]

        for e in reversed(layer_setup):
            elayer.insert(0, e)

        # PIXMAP и SVG маркеры: подставляем путь к файлу в SYMBOL cо значением TYPE 'PIXMAP' или 'SVG'
        for type_elem in emap.iterfind('./symbol/type'):
            if type_elem.text not in ('pixmap', 'svg'):
                continue

            symbol = type_elem.getparent()
            image = symbol.find('./image')

            try:
                marker = Marker.filter_by(
                    keyname=image.text
                ).one()

                image.text = env.file_storage.filename(marker.fileobj)

            except orm_exc.NoResultFound:
                # Если маркера не нашлось, то заменяем symbol на квадрат
                type_elem.text = 'vector'

                image.tag = 'points'
                image.text = '0 0 0 1 1 1 1 0 0 0'

                symbol.append(E.filled('true'))

        obj = Map().from_xml(emap)
        mapfile(obj, buf)

        mapobj = mapscript.fromstring(buf.getvalue().encode('utf-8'))

        layer = mapobj.getLayer(0)

        items = ','.join(fieldnames).encode('utf-8')
        layer.setProcessingKey('ITEMS', items)

        layer.setProcessingKey('APPROXIMATION_SCALE', 'full')
        layer.setProcessingKey('LABEL_NO_CLIP', 'true')

        for f in features:
            # У MapServer серьёзные проблемы с отрисовкой объектов,
            # содержащих дублирующиеся узлы, поэтому выкидываем их
            shape = mapscript.shapeObj.fromWKT(f.geom.simplify(0).wkt)

            shape.initValues(len(fieldnames))
            i = 0
            for fld in fieldnames:
                v = f.fields[fld]

                if v is None:
                    # TODO: Возможно есть более удачный способ
                    # передавать mapserver пустые значения, но
                    # пока он мне не известен
                    v = ""
                elif isinstance(v, unicode):
                    v = v.encode('utf-8')
                else:
                    v = str(v)

                shape.setValue(i, v)
                i += 1

            layer.addFeature(shape)

        return mapobj
Beispiel #15
0
"""
C:\VirtualEnvs\mappyfile\Scripts\activate
SET PATH=C:\MapServer\bin;%PATH%
SET PROJ_LIB=C:\MapServer\bin\proj\SHARE
"""
import mapscript

s = u"""
MAP
    LAYER
        TYPE POINT
        CLUSTER
            MAXDISTANCE 50
            REGION ELLIPSE
        END
    END
END
"""

map = mapscript.fromstring(s)

print(map.convertToString())
    def _mapobj(self, features):
        # tmpf = NamedTemporaryFile(suffix='.map')
        # buf = codecs.open(tmpf.name, 'w', 'utf-8')
        buf = StringIO()

        fieldnames = map(lambda f: f.keyname, self.layer.fields)

        E = ElementMaker()

        # Настраиваем map
        emap = etree.fromstring(self.xml)

        map_setup = [
            E.size(width='800', height='600'),
            E.maxsize('4096'),
            E.imagecolor(red='255', green='255', blue='255'),
            E.imagetype('PNG'),
            E.outputformat(E.name('png'), E.extension('png'),
                           E.mimetype('image/png'), E.driver('AGG/PNG'),
                           E.imagemode('RGBA'),
                           E.formatoption('INTERLACE=OFF')),
            E.web(
                E.metadata(
                    E.item(key='wms_onlineresource',
                           value='http://localhost/'),
                    E.item(key='wfs_onlineresource',
                           value='http://localhost/'),
                    E.item(key='ows_title', value='nextgisweb'),
                    E.item(key='wms_enable_request', value='*'),
                    E.item(key='wms_srs', value='EPSG:3857'))),
            E.extent(minx='-180', miny='-90', maxx='180', maxy='90'),
            E.projection("+init=epsg:4326"),
            E.fontset(env.mapserver_style.settings['fontset']),
            E.symbolset(resource_filename('nextgisweb_mapserver', 'symbolset'))
        ]

        for i in reversed(map_setup):
            emap.insert(0, i)

        # Настраиваем layer
        elayer = emap.find('./layer')

        layer_setup = [
            E.name('main'),
            E.type({
                "POINT": 'point',
                'LINESTRING': 'line',
                'POLYGON': 'polygon'
            }[self.layer.geometry_type]),
            E.template('dummy.html'),
            E.projection("+init=epsg:3857"),
            E.extent(minx='-20037508.34',
                     miny='-20037508.34',
                     maxx='20037508.34',
                     maxy='20037508.34'),
        ]

        for e in reversed(layer_setup):
            elayer.insert(0, e)

        # PIXMAP и SVG маркеры: подставляем путь к файлу в SYMBOL cо значением TYPE 'PIXMAP' или 'SVG'
        for type_elem in emap.iterfind('./symbol/type'):
            if type_elem.text not in ('pixmap', 'svg'):
                continue

            symbol = type_elem.getparent()
            image = symbol.find('./image')

            try:
                marker = Marker.filter_by(keyname=image.text).one()

                image.text = env.file_storage.filename(marker.fileobj)

            except orm_exc.NoResultFound:
                # Если маркера не нашлось, то заменяем symbol на квадрат
                type_elem.text = 'vector'

                image.tag = 'points'
                image.text = '0 0 0 1 1 1 1 0 0 0'

                symbol.append(E.filled('true'))

        obj = Map().from_xml(emap)
        mapfile(obj, buf)

        mapobj = mapscript.fromstring(buf.getvalue().encode('utf-8'))

        layer = mapobj.getLayer(0)

        items = ','.join(fieldnames).encode('utf-8')
        layer.setProcessingKey('ITEMS', items)

        layer.setProcessingKey('APPROXIMATION_SCALE', 'full')
        layer.setProcessingKey('LABEL_NO_CLIP', 'true')

        for f in features:
            # У MapServer серьёзные проблемы с отрисовкой объектов,
            # содержащих дублирующиеся узлы, поэтому выкидываем их
            shape = mapscript.shapeObj.fromWKT(f.geom.simplify(0).wkt)

            shape.initValues(len(fieldnames))
            i = 0
            for fld in fieldnames:
                v = f.fields[fld]

                if v is None:
                    # TODO: Возможно есть более удачный способ
                    # передавать mapserver пустые значения, но
                    # пока он мне не известен
                    v = ""
                elif isinstance(v, unicode):
                    v = v.encode('utf-8')
                else:
                    v = str(v)

                shape.setValue(i, v)
                i += 1

            layer.addFeature(shape)

        return mapobj