def write_vector_geometry(self, vector_map, geom, cat_num, map_layer): """Write geometry in the adequate layer """ cats = Cats(geom.c_cats) cats.reset() cats.set(cat_num, map_layer) # write geometry vector_map.write(geom)
def group_by(vinput, voutput, isolate=None, aggregate=None, function='sum', vtype='lines', where='', group_by=None, linput=1, loutput=1): vname, vmapset = vinput.split('@') if '@' in vinput else (vinput, '') with VectorTopo(vname, mapset=vmapset, mode='r') as vin: columns = ['cat', ] vincols = vin.table.columns types = ['PRIMARY KEY', ] siso = '' if isolate is not None: columns += list(isolate) types += [vincols[c] for c in isolate] siso = ', '.join(isolate) sagg = '' if aggregate is not None: ct = '{func}({col}) as {col}' sagg = ', '.join([ct.format(func=function, col=col) for col in aggregate]) columns += list(aggregate) types += [vincols[c] for c in aggregate] scols = "%s, %s" % (siso, sagg) if siso and sagg else siso + sagg base = "SELECT {cols} FROM {tin}" bwhere = " WHERE %s" % where if where else '' bgroup = " GROUP BY %s" % ', '.join(group_by) if group_by else '' grp = (base + bwhere + bgroup + ';').format(cols=scols, tin=vin.table.name, tout=voutput) bqry = "SELECT {cat} FROM {tin} WHERE {cond};" qry = bqry.format(cat=vin.table.key, tin=vin.table.name, cond=' AND '.join(['%s=?' % g for g in group_by])) selcols = columns[1:] gindexs = [selcols.index(col) for col in group_by] insrt = sql.INSERT.format(tname=voutput, values=','.join(['?', ] * len(columns))) with VectorTopo(voutput, mode='w', tab_name=voutput, layer=loutput, tab_cols=list(zip(columns, types)), link_key='cat', overwrite=True) as vout: cur = vout.table.conn.cursor() ncat = 1 #import ipdb; ipdb.set_trace() # TODO: why do I need to use list(cur) and I can not iterate directly for row in list(cur.execute(grp)): # add the new line to table print(row) cur.execute(insrt, tuple([ncat, ] + list(row))) for cat in cur.execute(qry, tuple([row[i] for i in gindexs])): for line in vin.cat(cat[0], vtype): # set the new category category = Cats(line.c_cats) category.reset() category.set(ncat, loutput) # write geometry vout.write(line, set_cats=False) ncat += 1 vout.table.conn.commit()
def write(self, geo_obj, cat=None, attrs=None): """Write geometry features and attributes. :param geo_obj: a geometry grass object define in grass.pygrass.vector.geometry :type geo_obj: geometry GRASS object :param attrs: a list with the values that will be insert in the attribute table. :type attrs: list :param cat: The category of the geometry feature, otherwise the c_cats attribute of the geometry object will be used. :type cat: integer Open a new vector map :: >>> new = VectorTopo('newvect') >>> new.exist() False define the new columns of the attribute table :: >>> cols = [(u'cat', 'INTEGER PRIMARY KEY'), ... (u'name', 'TEXT')] open the vector map in write mode >>> new.open('w', tab_name='newvect', tab_cols=cols) import a geometry feature :: >>> from grass.pygrass.vector.geometry import Point create two points :: >>> point0 = Point(0, 0) >>> point1 = Point(1, 1) then write the two points on the map, with :: >>> new.write(point0, cat=1, attrs=('pub',)) >>> new.write(point1, cat=2, attrs=('resturant',)) commit the db changes :: >>> new.table.conn.commit() >>> new.table.execute().fetchall() [(1, u'pub'), (2, u'resturant')] close the vector map :: >>> new.close() >>> new.exist() True then play with the map :: >>> new.open(mode='r') >>> new.read(1) Point(0.000000, 0.000000) >>> new.read(2) Point(1.000000, 1.000000) >>> new.read(1).attrs['name'] u'pub' >>> new.read(2).attrs['name'] u'resturant' >>> new.close() >>> new.remove() """ self.n_lines += 1 if not isinstance(cat, int) and not isinstance(cat, str): # likely the case of using 7.0 API import warnings warnings.warn("Vector.write(geo_obj, attrs=(...)) is" " depreciated, specify cat explicitly", DeprecationWarning) # try to accommodate attrs = cat cat = None if attrs and cat is None: # TODO: this does not work as expected when there are # already features in the map when we opened it cat = (self._cats[-1] if self._cats else 0) + 1 if cat is not None and cat not in self._cats: self._cats.append(cat) if self.table is not None and attrs is not None: attr = [cat, ] attr.extend(attrs) cur = self.table.conn.cursor() cur.execute(self.table.columns.insert_str, attr) cur.close() if cat is not None: cats = Cats(geo_obj.c_cats) cats.reset() cats.set(cat, self.layer) if geo_obj.gtype == _Area.gtype: result = self._write_area(geo_obj) result = libvect.Vect_write_line(self.c_mapinfo, geo_obj.gtype, geo_obj.c_points, geo_obj.c_cats) if result == -1: raise GrassError("Not able to write the vector feature.") if self._topo_level == 2: # return new feature id (on level 2) geo_obj.id = result else: # return offset into file where the feature starts (on level 1) geo_obj.offset = result
def write(self, geo_obj, attrs=None, set_cats=True): """Write geometry features and attributes. :param geo_obj: a geometry grass object define in grass.pygrass.vector.geometry :type geo_obj: geometry GRASS object :param attrs: a list with the values that will be insert in the attribute table. :type attrs: list :param set_cats: if True, the category of the geometry feature is set using the default layer of the vector map and a progressive category value (default), otherwise the c_cats attribute of the geometry object will be used. :type set_cats: bool Open a new vector map :: >>> new = VectorTopo('newvect') >>> new.exist() False define the new columns of the attribute table :: >>> cols = [(u'cat', 'INTEGER PRIMARY KEY'), ... (u'name', 'TEXT')] open the vector map in write mode >>> new.open('w', tab_name='newvect', tab_cols=cols) import a geometry feature :: >>> from grass.pygrass.vector.geometry import Point create two points :: >>> point0 = Point(636981.336043, 256517.602235) >>> point1 = Point(637209.083058, 257970.129540) then write the two points on the map, with :: >>> new.write(point0, ('pub', )) >>> new.write(point1, ('resturnat', )) commit the db changes :: >>> new.table.conn.commit() >>> new.table.execute().fetchall() [(1, u'pub'), (2, u'resturnat')] close the vector map :: >>> new.close() >>> new.exist() True then play with the map :: >>> new.open(mode='r') >>> new.read(1) Point(636981.336043, 256517.602235) >>> new.read(2) Point(637209.083058, 257970.129540) >>> new.read(1).attrs['name'] u'pub' >>> new.read(2).attrs['name'] u'resturnat' >>> new.close() >>> new.remove() """ self.n_lines += 1 if self.table is not None and attrs: attr = [self.n_lines, ] attr.extend(attrs) cur = self.table.conn.cursor() cur.execute(self.table.columns.insert_str, attr) cur.close() if set_cats: cats = Cats(geo_obj.c_cats) cats.reset() cats.set(self.n_lines, self.layer) if geo_obj.gtype == _Area.gtype: result = self._write_area(geo_obj) result = libvect.Vect_write_line(self.c_mapinfo, geo_obj.gtype, geo_obj.c_points, geo_obj.c_cats) if result == -1: raise GrassError("Not able to write the vector feature.") if self._topo_level == 2: # return new feature id (on level 2) geo_obj.id = result else: # return offset into file where the feature starts (on level 1) geo_obj.offset = result