コード例 #1
0
class MILayer(object):
    '''
    Map layer
    
    :param layer: (*MapLayer*) MapLayer object.
    :param shapetype: (*ShapeTypes*) Shape type ['point' | 'line' | 'polygon']
    '''
    def __init__(self, layer=None, shapetype=None):
        if layer is None:
            if shapetype is None:
                print 'shapetype must be specified!'
            else:                
                type = ShapeTypes.Point
                if shapetype == 'line':
                    type = ShapeTypes.Polyline
                elif shapetype == 'polygon':
                    type = ShapeTypes.Polygon
                self.layer = VectorLayer(type)
                self.shapetype = type
                self.proj = KnownCoordinateSystems.geographic.world.WGS1984
        else:
            self.layer = layer
            self.shapetype = layer.getShapeType()
            self.proj = layer.getProjInfo()
        self._coord_array = None
    
    def __repr__(self):
        return self.layer.getLayerInfo()

    @property
    def x_coord(self):
        '''
        Get X coordinate array.
        :return: X coordinate array
        '''
        if self.isvectorlayer():
            if self._coord_array is None:
                self._coord_array = GeometryUtil.getCoordinates(self.layer)
            return np.array(self._coord_array[0])
        else:
            return None

    @property
    def y_coord(self):
        '''
        Get Y coordinate array.
        :return: Y coordinate array
        '''
        if self.isvectorlayer():
            if self._coord_array is None:
                self._coord_array = GeometryUtil.getCoordinates(self.layer)
            return np.array(self._coord_array[1])
        else:
            return None

    @property
    def z_coord(self):
        '''
        Get Z coordinate array.
        :return: Z coordinate array
        '''
        if self.isvectorlayer():
            if self._coord_array is None:
                self._coord_array = GeometryUtil.getCoordinates(self.layer)
            return np.array(self._coord_array[2])
        else:
            return None
    
    def isvectorlayer(self):
        '''
        Check this layer is VectorLayer or not.
        
        :returns: (*boolean*) Is VectorLayer or not.
        '''
        return self.layer.getLayerType() == LayerTypes.VectorLayer
        
    def get_encoding(self):
        '''
        Get encoding.
        
        :returns: (*string*) Encoding
        '''
        return self.layer.getAttributeTable().getEncoding()
        
    def gettable(self):
        '''
        Get attribute table.
        
        :returns: (*PyTableData') Attribute table.
        '''
        r = self.layer.getAttributeTable().getTable()
        return np.datatable(r)
    
    def cellvalue(self, fieldname, shapeindex):
        '''
        Get attribute table cell value.
        
        :param fieldname: (*string*) Field name.
        :param shapeindex: (*int*) Shape index.
        
        :returns: The value in attribute table identified by field name and shape index.
        '''
        v = self.layer.getCellValue(fieldname, shapeindex)
        if isinstance(v, LocalDateTime):
            dt = miutil.pydate(v)
            return dt
        else:
            return v
            
    def setcellvalue(self, fieldname, shapeindex, value):
        '''
        Set cell value in attribute table.
        
        :param fieldname: (*string*) Field name.
        :param shapeindex: (*int*) Shape index.
        :param value: (*object*) Cell value to be asigned.
        '''
        self.layer.editCellValue(fieldname, shapeindex, value)
            
    def shapes(self):
        '''
        Get shapes.
        '''
        return self.layer.getShapes()
        
    def shapenum(self):
        '''
        Get shape number
        '''
        return self.layer.getShapeNum()
        
    def legend(self):
        '''
        Get legend scheme.
        '''
        return self.layer.getLegendScheme()
        
    def setlegend(self, legend):
        '''
        Set legend scheme.
        
        :param legend: (*LegendScheme*) Legend scheme.
        '''
        self.layer.setLegendScheme(legend)
        
    def update_legend(self, ltype, fieldname):
        '''
        Update legend scheme.
        
        :param ltype: (*string*) Legend type [single | unique | graduate].
        :param fieldname: (*string*) Field name.
        '''
        if ltype == 'single':
            ltype = LegendType.SingleSymbol
        elif ltype == 'unique':
            ltype = LegendType.UniqueValue
        elif ltyp == 'graduate':
            ltype = LegendType.GraduatedColor
        else:
            raise ValueError(ltype)
        self.layer.updateLegendScheme(ltype, fieldname)
        return self.layer.getLegendScheme()
    
    def addfield(self, fieldname, dtype, values=None):
        '''
        Add a field into the attribute table.
        
        :param fieldname: (*string*) Field name.
        :param dtype: (*string*) Field data type [string | int | float | double].
        :param values: (*array_like*) Field values.
        '''
        dt = TableUtil.toDataTypes(dtype)
        self.layer.editAddField(fieldname, dt)
        if not values is None:
            n = self.shapenum()
            for i in range(n):
                if i < len(values):
                    self.layer.editCellValue(fieldname, i, values[i])
                    
    def delfield(self, fieldname):
        '''
        Delete a field from the attribute table.
        
        :param fieldname: (*string*) Filed name.
        '''
        self.layer.editRemoveField(fieldname)
        
    def renamefield(self, fieldname, newfieldname):
        '''
        Rename the field.
        
        :param fieldname: (*string*) The old field name.
        :param newfieldname: (*string*) The new field name.
        '''
        self.layer.editRenameField(fieldname, newfieldname)
        
    def addshape(self, x, y, fields=None, z=None, m=None):
        '''
        Add a shape.
        
        :param x: (*array_like*) X coordinates of the shape points.
        :param y: (*array_like*) Y coordinates of the shape points.
        :param fields: (*array_like*) Field values of the shape.
        :param z: (*array_like*) Optional, Z coordinates of the shape points.
        :param m: (*array_like*) Optional, M coordinates of the shape points.
        '''
        type = 'point'
        if self.shapetype == ShapeTypes.Polyline:
            type = 'line'
        elif self.shapetype == ShapeTypes.Polygon:
            type = 'polygon'
        shapes = geoutil.makeshapes(x, y, type, z, m)
        if len(shapes) == 1:
            self.layer.editAddShape(shapes[0], fields)
        else:
            for shape, field in zip(shapes, fields):
                self.layer.editAddShape(shape, field)
                    
    def addlabels(self, fieldname, **kwargs):
        '''
        Add labels
        
        :param fieldname: (*string*) Field name
        :param fontname: (*string*) Font name. Default is ``Arial``.
        :param fontsize: (*string*) Font size. Default is ``14``.
        :param bold: (*boolean*) Font bold or not. Default is ``False``.
        :param color: (*color*) Label color. Default is ``None`` with black color.
        :param xoffset: (*int*) X coordinate offset. Default is ``0``.
        :param yoffset: (*int*) Y coordinate offset. Default is ``0``.
        :param avoidcoll: (*boolean*) Avoid labels collision or not. Default is ``True``.
        :param decimals: (*int*) Number of decimals of labels.
        '''
        labelset = self.layer.getLabelSet()
        labelset.setFieldName(fieldname)
        fontname = kwargs.pop('fontname', 'Arial')
        fontsize = kwargs.pop('fontsize', 14)
        bold = kwargs.pop('bold', False)
        if bold:
            font = Font(fontname, Font.BOLD, fontsize)
        else:
            font = Font(fontname, Font.PLAIN, fontsize)
        labelset.setLabelFont(font)
        color = kwargs.pop('color', None)
        if not color is None:
            color = miutil.getcolor(color)
            labelset.setLabelColor(color)
        xoffset = kwargs.pop('xoffset', 0)
        labelset.setXOffset(xoffset)
        yoffset = kwargs.pop('yoffset', 0)
        labelset.setYOffset(yoffset)
        avoidcoll = kwargs.pop('avoidcoll', True)
        labelset.setAvoidCollision(avoidcoll)
        decimals = kwargs.pop('decimals', None)
        if not decimals is None:
            labelset.setAutoDecimal(False)
            labelset.setDecimalDigits(decimals)
        self.layer.addLabels()
        
    def getlabel(self, text):
        '''
        Get a label.
        
        :param text: (*string*) The label text.
        '''
        return self.layer.getLabel(text)
        
    def movelabel(self, label, x=0, y=0):
        '''
        Move a label.
        
        :param label: (*string*) The label text.
        :param x: (*float*) X shift for moving in pixel unit.
        :param y: (*float*) Y shift for moving in pixel unit.
        '''
        self.layer.moveLabel(label, x, y)
        
    def add_charts(self, fieldnames, legend=None, **kwargs):
        '''
        Add charts
        
        :param fieldnames: (*list of string*) Field name list.
        :param legend: (*LegendScheme*) Chart legend.
        :param charttype: (*string*) Chart type [bar | pie]. Default is ``bar``.
        :param minsize: (*int*) Minimum chart size. Default is ``0``.
        :param maxsize: (*int*) Maximum chart size. Default is ``50``.
        :param barwidth: (*int*) Bar width. Only valid for bar chart. Default is ``8``.
        :param xoffset: (*int*) X coordinate offset. Default is ``0``.
        :param yoffset: (*int*) Y coordinate offset. Default is ``0``.
        :param avoidcoll: (*boolean*) Avoid labels collision or not. Default is ``True``.
        :param align: (*string*) Chart align type [center | left | right | none], Default is ``center``.
        :param view3d: (*boolean*) Draw chart as 3D or not. Default is ``False``.
        :param thickness: (*int*) 3D chart thickness. Default is ``5``.
        :param drawlabel: (*boolean*) Draw label or not. Default is ``False``.
        :param fontname: (*string*) Label font name.
        :param fontsize: (*int*) Label font size.
        :param bold: (*boolean*) Font bold or not. Default is ``False``.
        :param labelcolor: (*color*) Label color.
        :param decimals: (*int*) Number of decimals of labels.
        '''
        charttype = kwargs.pop('charttype', None)
        minsize = kwargs.pop('minsize', None)
        maxsize = kwargs.pop('maxsize', None)
        barwidth = kwargs.pop('barwidth', None)
        xoffset = kwargs.pop('xoffset', None)
        yoffset = kwargs.pop('yoffset', None)
        avoidcoll = kwargs.pop('avoidcoll', None)
        align = kwargs.pop('align', None)
        view3d = kwargs.pop('view3d', None)
        thickness = kwargs.pop('thickness', None)
        drawlabel = kwargs.pop('drawlabel', None)
        fontname = kwargs.pop('fontname', 'Arial')
        fontsize = kwargs.pop('fontsize', 12)
        bold = kwargs.pop('bold', False)
        if bold:
            font = Font(fontname, Font.BOLD, fontsize)
        else:
            font = Font(fontname, Font.PLAIN, fontsize)
        labelcolor = kwargs.pop('labelcolor', None)
        decimals = kwargs.pop('decimals', None)
        
        chartset = self.layer.getChartSet()
        chartset.setFieldNames(fieldnames)
        chartset.setLegendScheme(legend)
        if not charttype is None:
            chartset.setChartType(charttype)
        if not minsize is None:
            chartset.setMinSize(minsize)
        if not maxsize is None:
            chartset.setMaxSize(maxsize)
        if not barwidth is None:
            chartset.setBarWidth(barwidth)
        if not xoffset is None:
            chartset.setXShift(xoffset)
        if not yoffset is None:
            chartset.setYShift(yoffset)
        if not avoidcoll is None:
            chartset.setAvoidCollision(avoidcoll)
        if not align is None:
            chartset.setAlignType(align)
        if not view3d is None:
            chartset.setView3D(view3d)
        if not thickness is None:
            chartset.setThickness(thickness)
        if not drawlabel is None:
            chartset.setDrawLabel(drawlabel)
        chartset.setLabelFont(font)
        if not labelcolor is None:
            chartset.setLabelColor(miutil.getcolor(labelcolor))
        if not decimals is None:
            chartset.setDecimalDigits(decimals)
        self.layer.updateChartSet()
        self.layer.addCharts()
        return chartset
        
    def get_chartlegend(self):
        '''
        Get legend of the chart graphics.
        '''
        return self.layer.getChartSet().getLegendScheme()
        
    def get_chart(self, index):
        '''
        Get a chart graphic.
        
        :param index: (*int*) Chart index.
        
        :returns: Chart graphic
        '''
        return self.layer.getChartPoints()[index]
        
    def move_chart(self, index, x=0, y=0):
        '''
        Move a chart graphic.
        
        :param index: (*int*) Chart index.
        :param x: (*float*) X shift for moving.
        :param y: (*float*) Y shift for moving.
        '''
        s = self.layer.getChartPoints()[index].getShape()
        p = s.getPoint()
        p.X = p.X + x
        p.Y = p.Y + y
        s.setPoint(p)
        
    def set_avoidcoll(self, avoidcoll):
        '''
        Set if avoid collision or not. Only valid for VectorLayer with Point shapes.
        
        :param avoidcoll: (*boolean*) Avoid collision or not.
        '''
        self.layer.setAvoidCollision(avoidcoll)
        
    def project(self, toproj):
        '''
        Project to another projection.
        
        :param toproj: (*ProjectionInfo*) The projection to be projected.
        '''
        ProjectionUtil.projectLayer(self.layer, toproj)
        
    def buffer(self, dist=0, merge=False):
        '''
        Get the buffer layer.
        
        :param dist: (*float*) Buffer value.
        :param merge: (*boolean*) Merge the buffered shapes or not.
        
        :returns: (*MILayer*) Buffered layer.
        '''
        r = self.layer.buffer(dist, False, merge)
        return MILayer(r)
        
    def clip(self, clipobj):
        '''
        Clip this layer by polygon or another polygon layer.
        
        :param clipobj: (*PolygonShape or MILayer*) Clip object.
        
        :returns: (*MILayer*) Clipped layer.
        '''
        if isinstance(clipobj, PolygonShape):
            clipobj = [clipobj]
        elif isinstance(clipobj, MILayer):
            clipobj = clipobj.layer
        r = self.layer.clip(clipobj)
        return MILayer(r)
        
    def select(self, expression, seltype='new'):
        '''
        Select shapes by SQL expression.
        
        :param expression: (*string*) SQL expression.
        :param seltype: (*string*) Selection type ['new' | 'add_to_current' |
            'remove_from_current' | 'select_from_current']
            
        :returns: (*list of Shape*) Selected shape list.
        '''
        self.layer.sqlSelect(expression, seltype)
        return self.layer.getSelectedShapes()
        
    def clear_selection(self):
        '''
        Clear shape selection.
        '''
        self.layer.clearSelectedShapes()
        
    def clone(self):
        '''
        Clone self.
        '''
        return MILayer(self.layer.clone())
    
    def save(self, fn=None, encoding=None):
        """
        Save layer as shape file.
        
        :param fn: (*string*) Shape file name (.shp).
        :param encoding: (*string*) Encoding.
        """
        if fn is None:
            fn = self.layer.getFileName()
            
        if fn.strip() == '':
            print 'File name is needed to save the layer!'
            raise IOError
        else:
            if encoding is None:
                self.layer.saveFile(fn)
            else:
                self.layer.saveFile(fn, encoding)
    
    def savekml(self, fn):
        """
        Save layer as KML file.
        
        :param fn: (*string*) KML file name.
        """
        self.layer.saveAsKMLFile(fn)
コード例 #2
0
ファイル: milayer.py プロジェクト: lileipku00/MeteoInfoLab
class MILayer():
    '''
    Map layer
    
    :param layer: (*MapLayer*) MapLayer object.
    :param shapetype: (*ShapeTypes*) Shape type ['point' | 'line' | 'polygon']
    '''
    def __init__(self, layer=None, shapetype=None):
        if layer is None:
            if shapetype is None:
                print 'shapetype must be specified!'
            else:                
                type = ShapeTypes.Point
                if shapetype == 'line':
                    type = ShapeTypes.Polyline
                elif shapetype == 'polygon':
                    type = ShapeTypes.Polygon
                self.layer = VectorLayer(type)
                self.shapetype = type
                self.proj = KnownCoordinateSystems.geographic.world.WGS1984
        else:
            self.layer = layer
            self.shapetype = layer.getShapeType()
            self.proj = layer.getProjInfo()
    
    def __repr__(self):
        return self.layer.getLayerInfo()            
    
    def isvectorlayer(self):
        '''
        Check this layer is VectorLayer or not.
        
        :returns: (*boolean*) Is VectorLayer or not.
        '''
        return self.layer.getLayerType() == LayerTypes.VectorLayer
        
    def gettable(self):
        '''
        Get attribute table.
        
        :returns: (*PyTableData') Attribute table.
        '''
        r = self.layer.getAttributeTable().getTable()
        return minum.datatable(r)
    
    def cellvalue(self, fieldname, shapeindex):
        '''
        Get attribute table cell value.
        
        :param fieldname: (*string*) Field name.
        :param shapeindex: (*int*) Shape index.
        
        :returns: The value in attribute table identified by field name and shape index.
        '''
        v = self.layer.getCellValue(fieldname, shapeindex)
        if isinstance(v, Date):
            cal = Calendar.getInstance()
            cal.setTime(v)
            year = cal.get(Calendar.YEAR)
            month = cal.get(Calendar.MONTH) + 1
            day = cal.get(Calendar.DAY_OF_MONTH)
            hour = cal.get(Calendar.HOUR_OF_DAY)
            minute = cal.get(Calendar.MINUTE)
            second = cal.get(Calendar.SECOND)
            dt = datetime(year, month, day, hour, minute, second)
            return dt
        else:
            return v
            
    def setcellvalue(self, fieldname, shapeindex, value):
        '''
        Set cell value in attribute table.
        
        :param fieldname: (*string*) Field name.
        :param shapeindex: (*int*) Shape index.
        :param value: (*object*) Cell value to be asigned.
        '''
        self.layer.editCellValue(fieldname, shapeindex, value)
            
    def shapes(self):
        return self.layer.getShapes()
        
    def shapenum(self):
        return self.layer.getShapeNum()
        
    def legend(self):
        return self.layer.getLegendScheme()
        
    def setlegend(self, legend):
        self.layer.setLegendScheme(legend)
    
    def addfield(self, fieldname, dtype, values=None):
        dt = TableUtil.toDataTypes(dtype)
        self.layer.editAddField(fieldname, dt)
        if not values is None:
            n = self.shapenum()
            for i in range(n):
                if i < len(values):
                    self.layer.editCellValue(fieldname, i, values[i])
                    
    def delfield(self, fieldname):
        self.layer.editRemoveField(fieldname)
        
    def renamefield(self, fieldname, newfieldname):
        self.layer.editRenameField(fieldname, newfieldname)
        
    def addshape(self, x, y, fields=None, z=None, m=None):
        type = 'point'
        if self.shapetype == ShapeTypes.Polyline:
            type = 'line'
        elif self.shapetype == ShapeTypes.Polygon:
            type = 'polygon'
        shapes = makeshapes(x, y, type, z, m)
        if len(shapes) == 1:
            self.layer.editAddShape(shapes[0], fields)
        else:
            for shape, field in zip(shapes, fields):
                self.layer.editAddShape(shape, field)
                    
    def addlabels(self, fieldname, **kwargs):
        '''
        Add labels
        
        :param fieldname: (*string*) Field name
        :param fontname: (*string*) Font name. Default is ``Arial``.
        :param fontsize: (*string*) Font size. Default is ``14``.
        :param bold: (*boolean*) Font bold or not. Default is ``False``.
        :param color: (*color*) Label color. Default is ``None`` with black color.
        :param xoffset: (*int*) X coordinate offset. Default is ``0``.
        :param yoffset: (*int*) Y coordinate offset. Default is ``1``.
        :param avoidcoll: (*boolean*) Avoid labels collision or not. Default is ``True``.
        :param decimals: (*int*) Number of decimals of labels.
        '''
        labelset = self.layer.getLabelSet()
        labelset.setFieldName(fieldname)
        fontname = kwargs.pop('fontname', 'Arial')
        fontsize = kwargs.pop('fontsize', 14)
        bold = kwargs.pop('bold', False)
        if bold:
            font = Font(fontname, Font.BOLD, fontsize)
        else:
            font = Font(fontname, Font.PLAIN, fontsize)
        labelset.setLabelFont(font)
        color = kwargs.pop('color', None)
        if not color is None:
            color = miutil.getcolor(color)
            labelset.setLabelColor(color)
        xoffset = kwargs.pop('xoffset', 0)
        labelset.setXOffset(xoffset)
        yoffset = kwargs.pop('yoffset', 0)
        labelset.setYOffset(yoffset)
        avoidcoll = kwargs.pop('avoidcoll', True)
        labelset.setAvoidCollision(avoidcoll)
        decimals = kwargs.pop('decimals', None)
        if not decimals is None:
            labelset.setAutoDecimal(False)
            labelset.setDecimalDigits(decimals)
        self.layer.addLabels()
        
    def getlabel(self, text):
        return self.layer.getLabel(text)
        
    def movelabel(self, label, x=0, y=0):
        self.layer.moveLabel(label, x, y)
        
    def project(self, toproj):
        r = ProjectionManage.projectLayer(self.layer, toproj)
        return MILayer(r)
        
    def buffer(self, dist=0, merge=False):
        r = self.layer.buffer(dist, False, merge)
        return MILayer(r)
        
    def clip(self, clipobj):
        if isinstance(clipobj, PolygonShape):
            clipobj = [clipobj]
        elif isinstance(clipobj, MILayer):
            clipobj = clipobj.layer
        r = self.layer.clip(clipobj)
        return MILayer(r)
        
    def select(self, expression, seltype='new'):
        '''
        Select shapes by SQL expression.
        
        :param expression: (*string*) SQL expression.
        :param seltype: (*string*) Selection type ['new' | 'add_to_current' |
            'remove_from_current' | 'select_from_current']
            
        :returns: (*list of Shape*) Selected shape list.
        '''
        self.layer.sqlSelect(expression, seltype)
        return self.layer.getSelectedShapes()
        
    def clear_selection(self):
        '''
        Clear shape selection.
        '''
        self.layer.clearSelectedShapes()
        
    def clone(self):
        '''
        Clone self.
        '''
        return MILayer(self.layer.clone())
    
    def save(self, fn=None):
        """
        Save layer as shape file.
        
        :param fn: (*string*) Shape file name (.shp).
        """
        if fn is None:
            if self.layer.getFileName().strip() == '':
                print 'File name is needed to save the layer!'
            else:
                self.layer.saveFile()    
        else:
            self.layer.saveFile(fn)
    
    def savekml(self, fn):
        """
        Save layer as KML file.
        
        :param fn: (*string*) KML file name.
        """
        self.layer.saveAsKMLFile(fn)
コード例 #3
0
ファイル: milayer.py プロジェクト: meteoinfo/MeteoInfoLab
class MILayer(object):
    '''
    Map layer
    
    :param layer: (*MapLayer*) MapLayer object.
    :param shapetype: (*ShapeTypes*) Shape type ['point' | 'line' | 'polygon']
    '''
    def __init__(self, layer=None, shapetype=None):
        if layer is None:
            if shapetype is None:
                print 'shapetype must be specified!'
            else:                
                type = ShapeTypes.Point
                if shapetype == 'line':
                    type = ShapeTypes.Polyline
                elif shapetype == 'polygon':
                    type = ShapeTypes.Polygon
                self.layer = VectorLayer(type)
                self.shapetype = type
                self.proj = KnownCoordinateSystems.geographic.world.WGS1984
        else:
            self.layer = layer
            self.shapetype = layer.getShapeType()
            self.proj = layer.getProjInfo()
    
    def __repr__(self):
        return self.layer.getLayerInfo()            
    
    def isvectorlayer(self):
        '''
        Check this layer is VectorLayer or not.
        
        :returns: (*boolean*) Is VectorLayer or not.
        '''
        return self.layer.getLayerType() == LayerTypes.VectorLayer
        
    def get_encoding(self):
        '''
        Get encoding.
        
        :returns: (*string*) Encoding
        '''
        return self.layer.getAttributeTable().getEncoding()
        
    def gettable(self):
        '''
        Get attribute table.
        
        :returns: (*PyTableData') Attribute table.
        '''
        r = self.layer.getAttributeTable().getTable()
        return minum.datatable(r)
    
    def cellvalue(self, fieldname, shapeindex):
        '''
        Get attribute table cell value.
        
        :param fieldname: (*string*) Field name.
        :param shapeindex: (*int*) Shape index.
        
        :returns: The value in attribute table identified by field name and shape index.
        '''
        v = self.layer.getCellValue(fieldname, shapeindex)
        if isinstance(v, Date):
            cal = Calendar.getInstance()
            cal.setTime(v)
            year = cal.get(Calendar.YEAR)
            month = cal.get(Calendar.MONTH) + 1
            day = cal.get(Calendar.DAY_OF_MONTH)
            hour = cal.get(Calendar.HOUR_OF_DAY)
            minute = cal.get(Calendar.MINUTE)
            second = cal.get(Calendar.SECOND)
            dt = datetime(year, month, day, hour, minute, second)
            return dt
        else:
            return v
            
    def setcellvalue(self, fieldname, shapeindex, value):
        '''
        Set cell value in attribute table.
        
        :param fieldname: (*string*) Field name.
        :param shapeindex: (*int*) Shape index.
        :param value: (*object*) Cell value to be asigned.
        '''
        self.layer.editCellValue(fieldname, shapeindex, value)
            
    def shapes(self):
        '''
        Get shapes.
        '''
        return self.layer.getShapes()
        
    def shapenum(self):
        '''
        Get shape number
        '''
        return self.layer.getShapeNum()
        
    def legend(self):
        '''
        Get legend scheme.
        '''
        return self.layer.getLegendScheme()
        
    def setlegend(self, legend):
        '''
        Set legend scheme.
        
        :param legend: (*LegendScheme*) Legend scheme.
        '''
        self.layer.setLegendScheme(legend)
        
    def update_legend(self, ltype, fieldname):
        '''
        Update legend scheme.
        
        :param ltype: (*string*) Legend type [single | unique | graduate].
        :param fieldname: (*string*) Field name.
        '''
        if ltype == 'single':
            ltype = LegendType.SingleSymbol
        elif ltype == 'unique':
            ltype = LegendType.UniqueValue
        elif ltyp == 'graduate':
            ltype = LegendType.GraduatedColor
        else:
            raise ValueError(ltype)
        self.layer.updateLegendScheme(ltype, fieldname)
        return self.layer.getLegendScheme()
    
    def addfield(self, fieldname, dtype, values=None):
        '''
        Add a field into the attribute table.
        
        :param fieldname: (*string*) Field name.
        :param dtype: (*string*) Field data type [string | int | float | double].
        :param values: (*array_like*) Field values.
        '''
        dt = TableUtil.toDataTypes(dtype)
        self.layer.editAddField(fieldname, dt)
        if not values is None:
            n = self.shapenum()
            for i in range(n):
                if i < len(values):
                    self.layer.editCellValue(fieldname, i, values[i])
                    
    def delfield(self, fieldname):
        '''
        Delete a field from the attribute table.
        
        :param fieldname: (*string*) Filed name.
        '''
        self.layer.editRemoveField(fieldname)
        
    def renamefield(self, fieldname, newfieldname):
        '''
        Rename the field.
        
        :param fieldname: (*string*) The old field name.
        :param newfieldname: (*string*) The new field name.
        '''
        self.layer.editRenameField(fieldname, newfieldname)
        
    def addshape(self, x, y, fields=None, z=None, m=None):
        '''
        Add a shape.
        
        :param x: (*array_like*) X coordinates of the shape points.
        :param y: (*array_like*) Y coordinates of the shape points.
        :param fields: (*array_like*) Field values of the shape.
        :param z: (*array_like*) Optional, Z coordinates of the shape points.
        :param m: (*array_like*) Optional, M coordinates of the shape points.
        '''
        type = 'point'
        if self.shapetype == ShapeTypes.Polyline:
            type = 'line'
        elif self.shapetype == ShapeTypes.Polygon:
            type = 'polygon'
        shapes = geoutil.makeshapes(x, y, type, z, m)
        if len(shapes) == 1:
            self.layer.editAddShape(shapes[0], fields)
        else:
            for shape, field in zip(shapes, fields):
                self.layer.editAddShape(shape, field)
                    
    def addlabels(self, fieldname, **kwargs):
        '''
        Add labels
        
        :param fieldname: (*string*) Field name
        :param fontname: (*string*) Font name. Default is ``Arial``.
        :param fontsize: (*string*) Font size. Default is ``14``.
        :param bold: (*boolean*) Font bold or not. Default is ``False``.
        :param color: (*color*) Label color. Default is ``None`` with black color.
        :param xoffset: (*int*) X coordinate offset. Default is ``0``.
        :param yoffset: (*int*) Y coordinate offset. Default is ``0``.
        :param avoidcoll: (*boolean*) Avoid labels collision or not. Default is ``True``.
        :param decimals: (*int*) Number of decimals of labels.
        '''
        labelset = self.layer.getLabelSet()
        labelset.setFieldName(fieldname)
        fontname = kwargs.pop('fontname', 'Arial')
        fontsize = kwargs.pop('fontsize', 14)
        bold = kwargs.pop('bold', False)
        if bold:
            font = Font(fontname, Font.BOLD, fontsize)
        else:
            font = Font(fontname, Font.PLAIN, fontsize)
        labelset.setLabelFont(font)
        color = kwargs.pop('color', None)
        if not color is None:
            color = miutil.getcolor(color)
            labelset.setLabelColor(color)
        xoffset = kwargs.pop('xoffset', 0)
        labelset.setXOffset(xoffset)
        yoffset = kwargs.pop('yoffset', 0)
        labelset.setYOffset(yoffset)
        avoidcoll = kwargs.pop('avoidcoll', True)
        labelset.setAvoidCollision(avoidcoll)
        decimals = kwargs.pop('decimals', None)
        if not decimals is None:
            labelset.setAutoDecimal(False)
            labelset.setDecimalDigits(decimals)
        self.layer.addLabels()
        
    def getlabel(self, text):
        '''
        Get a label.
        
        :param text: (*string*) The label text.
        '''
        return self.layer.getLabel(text)
        
    def movelabel(self, label, x=0, y=0):
        '''
        Move a label.
        
        :param label: (*string*) The label text.
        :param x: (*float*) X shift for moving in pixel unit.
        :param y: (*float*) Y shift for moving in pixel unit.
        '''
        self.layer.moveLabel(label, x, y)
        
    def add_charts(self, fieldnames, legend=None, **kwargs):
        '''
        Add charts
        
        :param fieldnames: (*list of string*) Field name list.
        :param legend: (*LegendScheme*) Chart legend.
        :param charttype: (*string*) Chart type [bar | pie]. Default is ``bar``.
        :param minsize: (*int*) Minimum chart size. Default is ``0``.
        :param maxsize: (*int*) Maximum chart size. Default is ``50``.
        :param barwidth: (*int*) Bar width. Only valid for bar chart. Default is ``8``.
        :param xoffset: (*int*) X coordinate offset. Default is ``0``.
        :param yoffset: (*int*) Y coordinate offset. Default is ``0``.
        :param avoidcoll: (*boolean*) Avoid labels collision or not. Default is ``True``.
        :param align: (*string*) Chart align type [center | left | right | none], Default is ``center``.
        :param view3d: (*boolean*) Draw chart as 3D or not. Default is ``False``.
        :param thickness: (*int*) 3D chart thickness. Default is ``5``.
        :param drawlabel: (*boolean*) Draw label or not. Default is ``False``.
        :param fontname: (*string*) Label font name.
        :param fontsize: (*int*) Label font size.
        :param bold: (*boolean*) Font bold or not. Default is ``False``.
        :param labelcolor: (*color*) Label color.
        :param decimals: (*int*) Number of decimals of labels.
        '''
        charttype = kwargs.pop('charttype', None)
        minsize = kwargs.pop('minsize', None)
        maxsize = kwargs.pop('maxsize', None)
        barwidth = kwargs.pop('barwidth', None)
        xoffset = kwargs.pop('xoffset', None)
        yoffset = kwargs.pop('yoffset', None)
        avoidcoll = kwargs.pop('avoidcoll', None)
        align = kwargs.pop('align', None)
        view3d = kwargs.pop('view3d', None)
        thickness = kwargs.pop('thickness', None)
        drawlabel = kwargs.pop('drawlabel', None)
        fontname = kwargs.pop('fontname', 'Arial')
        fontsize = kwargs.pop('fontsize', 12)
        bold = kwargs.pop('bold', False)
        if bold:
            font = Font(fontname, Font.BOLD, fontsize)
        else:
            font = Font(fontname, Font.PLAIN, fontsize)
        labelcolor = kwargs.pop('labelcolor', None)
        decimals = kwargs.pop('decimals', None)
        
        chartset = self.layer.getChartSet()
        chartset.setFieldNames(fieldnames)
        chartset.setLegendScheme(legend)
        if not charttype is None:
            chartset.setChartType(charttype)
        if not minsize is None:
            chartset.setMinSize(minsize)
        if not maxsize is None:
            chartset.setMaxSize(maxsize)
        if not barwidth is None:
            chartset.setBarWidth(barwidth)
        if not xoffset is None:
            chartset.setXShift(xoffset)
        if not yoffset is None:
            chartset.setYShift(yoffset)
        if not avoidcoll is None:
            chartset.setAvoidCollision(avoidcoll)
        if not align is None:
            chartset.setAlignType(align)
        if not view3d is None:
            chartset.setView3D(view3d)
        if not thickness is None:
            chartset.setThickness(thickness)
        if not drawlabel is None:
            chartset.setDrawLabel(drawlabel)
        chartset.setLabelFont(font)
        if not labelcolor is None:
            chartset.setLabelColor(miutil.getcolor(labelcolor))
        if not decimals is None:
            chartset.setDecimalDigits(decimals)
        self.layer.updateChartSet()
        self.layer.addCharts()
        return chartset
        
    def get_chartlegend(self):
        '''
        Get legend of the chart graphics.
        '''
        return self.layer.getChartSet().getLegendScheme()
        
    def get_chart(self, index):
        '''
        Get a chart graphic.
        
        :param index: (*int*) Chart index.
        
        :returns: Chart graphic
        '''
        return self.layer.getChartPoints()[index]
        
    def move_chart(self, index, x=0, y=0):
        '''
        Move a chart graphic.
        
        :param index: (*int*) Chart index.
        :param x: (*float*) X shift for moving.
        :param y: (*float*) Y shift for moving.
        '''
        s = self.layer.getChartPoints()[index].getShape()
        p = s.getPoint()
        p.X = p.X + x
        p.Y = p.Y + y
        s.setPoint(p)
        
    def set_avoidcoll(self, avoidcoll):
        '''
        Set if avoid collision or not. Only valid for VectorLayer with Point shapes.
        
        :param avoidcoll: (*boolean*) Avoid collision or not.
        '''
        self.layer.setAvoidCollision(avoidcoll)
        
    def project(self, toproj):
        '''
        Project to another projection.
        
        :param toproj: (*ProjectionInfo*) The projection to be projected.
        '''
        ProjectionUtil.projectLayer(self.layer, toproj)
        
    def buffer(self, dist=0, merge=False):
        '''
        Get the buffer layer.
        
        :param dist: (*float*) Buffer value.
        :param merge: (*boolean*) Merge the buffered shapes or not.
        
        :returns: (*MILayer*) Buffered layer.
        '''
        r = self.layer.buffer(dist, False, merge)
        return MILayer(r)
        
    def clip(self, clipobj):
        '''
        Clip this layer by polygon or another polygon layer.
        
        :param clipobj: (*PolygonShape or MILayer*) Clip object.
        
        :returns: (*MILayer*) Clipped layer.
        '''
        if isinstance(clipobj, PolygonShape):
            clipobj = [clipobj]
        elif isinstance(clipobj, MILayer):
            clipobj = clipobj.layer
        r = self.layer.clip(clipobj)
        return MILayer(r)
        
    def select(self, expression, seltype='new'):
        '''
        Select shapes by SQL expression.
        
        :param expression: (*string*) SQL expression.
        :param seltype: (*string*) Selection type ['new' | 'add_to_current' |
            'remove_from_current' | 'select_from_current']
            
        :returns: (*list of Shape*) Selected shape list.
        '''
        self.layer.sqlSelect(expression, seltype)
        return self.layer.getSelectedShapes()
        
    def clear_selection(self):
        '''
        Clear shape selection.
        '''
        self.layer.clearSelectedShapes()
        
    def clone(self):
        '''
        Clone self.
        '''
        return MILayer(self.layer.clone())
    
    def save(self, fn=None, encoding=None):
        """
        Save layer as shape file.
        
        :param fn: (*string*) Shape file name (.shp).
        :param encoding: (*string*) Encoding.
        """
        if fn is None:
            fn = self.layer.getFileName()
            
        if fn.strip() == '':
            print 'File name is needed to save the layer!'
            raise IOError
        else:
            if encoding is None:
                self.layer.saveFile(fn)
            else:
                self.layer.saveFile(fn, encoding)
    
    def savekml(self, fn):
        """
        Save layer as KML file.
        
        :param fn: (*string*) KML file name.
        """
        self.layer.saveAsKMLFile(fn)