[GRASS-SVN] r58634 - grass/trunk/lib/python/pygrass/vector

svn_grass at osgeo.org svn_grass at osgeo.org
Tue Jan 7 07:38:49 PST 2014


Author: zarch
Date: 2014-01-07 07:38:49 -0800 (Tue, 07 Jan 2014)
New Revision: 58634

Modified:
   grass/trunk/lib/python/pygrass/vector/geometry.py
Log:
Transform gtype attribute to a class attribute and rewrite some functions and methods

Modified: grass/trunk/lib/python/pygrass/vector/geometry.py
===================================================================
--- grass/trunk/lib/python/pygrass/vector/geometry.py	2014-01-07 01:34:26 UTC (rev 58633)
+++ grass/trunk/lib/python/pygrass/vector/geometry.py	2014-01-07 15:38:49 UTC (rev 58634)
@@ -163,7 +163,8 @@
                                                          tname=self.table.name,
                                                          condition=self.cond))
         results = cur.fetchone()
-        return results[0] if len(results) == 1 else results
+        if results is not None:
+            return results[0] if len(results) == 1 else results
 
     def __setitem__(self, key, value):
         """Set value of a given column of a table attribute. ::
@@ -245,22 +246,26 @@
     >>> cats = ctypes.pointer(libvect.line_cats())
     >>> geo1 = Geo(c_points=points, c_cats=cats)
     """
+    gtype = None
+
     def __init__(self, v_id=None, c_mapinfo=None, c_points=None, c_cats=None,
                  table=None, writable=False, is2D=True):
         self.id = v_id  # vector id
         self.c_mapinfo = c_mapinfo
         self.is2D = is2D
-        self.gtype = None
 
+        read = False
         # set c_points
         if c_points is None:
             self.c_points = ctypes.pointer(libvect.line_pnts())
+            read = True
         else:
             self.c_points = c_points
 
         # set c_cats
         if c_cats is None:
             self.c_cats = ctypes.pointer(libvect.line_cats())
+            read = True
         else:
             self.c_cats = c_cats
 
@@ -269,6 +274,9 @@
         if table is not None:
             self.attrs = Attrs(self.cat, table, writable)
 
+        if self.id is not None and self.c_mapinfo is not None and read:
+            self.read()
+
     @property
     def cat(self):
         if self.c_cats.contents.cat:
@@ -283,8 +291,8 @@
     def read(self):
         """Read and set the coordinates of the centroid from the vector map,
         using the centroid_id and calling the Vect_read_line C function"""
-        libvect.Vect_read_line(self.c_mapinfo, self.c_points,
-                               self.c_cats, self.id)
+        ftype, c_points, c_cats = c_read_line(self.id, self.c_mapinfo,
+                                              self.c_points, self.c_cats)
 
 
 class Point(Geo):
@@ -313,6 +321,9 @@
 
     ..
     """
+    # geometry type
+    gtype = libvect.GV_POINT
+
     def __init__(self, x=0, y=0, z=None, **kargs):
         super(Point, self).__init__(**kargs)
         if self.id is not None:
@@ -322,9 +333,6 @@
             z = z if z is not None else 0
             libvect.Vect_append_point(self.c_points, x, y, z)
 
-        # geometry type
-        self.gtype = libvect.GV_POINT
-
     def _get_x(self):
         return self.c_points.contents.x[0]
 
@@ -506,15 +514,15 @@
 
     ..
     """
+    # geometry type
+    gtype = libvect.GV_LINE
+
     def __init__(self, points=None, **kargs):
         super(Line, self).__init__(**kargs)
         if points is not None:
             for pnt in points:
                 self.append(pnt)
 
-        # geometry type
-        self.gtype = libvect.GV_LINE
-
     def __getitem__(self, key):
         """Get line point of given index,  slice allowed. ::
 
@@ -627,7 +635,7 @@
         x, y, z = get_xyz(pnt)
         libvect.Vect_append_point(self.c_points, x, y, z)
 
-    def bbox(self):
+    def bbox(self, bbox=None):
         """Return the bounding box of the line, using ``Vect_line_box``
         C function. ::
 
@@ -638,7 +646,7 @@
 
         ..
         """
-        bbox = Bbox()
+        bbox = bbox if bbox else Bbox()
         libvect.Vect_line_box(self.c_points, bbox.c_bbox)
         return bbox
 
@@ -1035,38 +1043,51 @@
 class Boundary(Line):
     """
     """
-    def __init__(self, area_id=None, lines=None, left=None, right=None,
+    # geometry type
+    gtype = libvect.GV_BOUNDARY
+
+    def __init__(self, lines=None, left=None, right=None,
                  **kargs):
+        v_id = kargs.get('v_id', 0)
+        self.dir = libvect.GV_FORWARD if v_id > 0 else libvect.GV_BACKWARD
         super(Boundary, self).__init__(**kargs)
-        self.area_id = area_id
-        self.ilist = Ilist()
-        self.lines = lines
-        if lines:
-            if len(lines) != len(left) or len(lines) != len(right):
-                str_err = "Left and right must have the same length of lines"
-                raise ValueError(str_err)
-        self.left = Ilist()
-        self.right = Ilist()
-        # geometry type
-        self.gtype = libvect.GV_BOUNDARY
+        self.c_left = ctypes.pointer(ctypes.c_int())
+        self.c_right = ctypes.pointer(ctypes.c_int())
+        self.get_left_right()
 
+    @property
+    def left_id(self):
+        return self.c_left.contents.value
+
+    @property
+    def right_id(self):
+        return self.c_right.contents.value
+
     def __repr__(self):
         return "Boundary(v_id=%r)" % self.id
 
-    def boundaries(self):
-        """Returna Ilist object with the line id"""
-        bounds = Ilist()
-        libvect.Vect_get_area_boundaries(self.c_mapinfo, self.area_id,
-                                         bounds.c_ilist)
-        return bounds
+    def _get_centroid(self, side, idonly=False):
+        if side > 0:
+            v_id = libvect.Vect_get_area_centroid(self.c_mapinfo, side)
+            v_id = v_id if v_id else None
+            if idonly:
+                return v_id
+            else:
+                cntr = Centroid(v_id=v_id, c_mapinfo=self.c_mapinfo)
+                return cntr
 
+    def get_left_centroid(self, idonly=False):
+        return self._get_centroid(self.left_id, idonly)
+
+    def get_right_centroid(self, idonly=False):
+        return self._get_centroid(self.left_id, idonly)
+
     def get_left_right(self):
         """Return left and right value"""
-        left = ctypes.pointer(ctypes.c_int())
-        right = ctypes.pointer(ctypes.c_int())
+
         libvect.Vect_get_line_areas(self.c_mapinfo, self.id,
-                                    left, right)
-        return left.contents.value, right.contents.value
+                                    self.c_left, self.c_right)
+        return self.c_left.contents.value, self.c_right.contents.value
 
     def area(self):
         """Return the area of the polygon.
@@ -1098,8 +1119,11 @@
         >>> centroid
         Centoid(893202.874416, 297339.312795)
 
-        ..
-        """
+    ..
+    """
+    # geometry type
+    gtype = libvect.GV_CENTROID
+
     def __init__(self, area_id=None, **kargs):
         super(Centroid, self).__init__(**kargs)
         self.area_id = area_id
@@ -1110,8 +1134,6 @@
         if self.area_id is not None:
             self.read()
 
-        # geometry type
-        self.gtype = libvect.GV_CENTROID
         #self.c_pline = ctypes.pointer(libvect.P_line()) if topology else None
 
     def __repr__(self):
@@ -1150,8 +1172,8 @@
                                          ilist.c_ilist)
         return ilist
 
-    def bbox(self):
-        bbox = Bbox()
+    def bbox(self, bbox=None):
+        bbox = bbox if bbox else Bbox()
         libvect.Vect_get_isle_box(self.c_mapinfo, self.id, bbox.c_bbox)
         return bbox
 
@@ -1199,19 +1221,24 @@
 
 
 class Isles(object):
-    def __init__(self, c_mapinfo, area_id):
+    def __init__(self, c_mapinfo, area_id=None):
         self.c_mapinfo = c_mapinfo
         self.area_id = area_id
-        self._isles_id = self.get_isles_id()
-        self._isles = self.get_isles()
+        self._isles_id = None
+        self._isles = None
+        if area_id:
+            self._isles_id = self.get_isles_id()
+            self._isles = self.get_isles()
 
     def __len__(self):
         return libvect.Vect_get_area_num_isles(self.c_mapinfo, self.area_id)
 
     def __repr__(self):
-        return "Isles(%r)" % self._isles
+        return "Isles(%r)" % self.area_id
 
     def __getitem__(self, key):
+        if self._isles is None:
+            self.get_isles()
         return self._isles[key]
 
     def get_isles_id(self):
@@ -1248,30 +1275,23 @@
      'Vect_select_areas_by_box',
      'Vect_select_areas_by_polygon']
     """
+    # geometry type
+    gtype = libvect.GV_AREA
 
     def __init__(self, boundary=None, centroid=None, isles=None, **kargs):
         super(Area, self).__init__(**kargs)
-        if self.id is not None and self.c_mapinfo:
-            self.boundary = self.get_points()
-            self.centroid = self.get_centroid()
-            self.isles = self.get_isles()
-            libvect.Vect_read_line(self.c_mapinfo, None, self.c_cats,
-                                   self.centroid.id)
-        elif boundary and centroid:
+        self.boundary = None
+        self.centroid = None
+        self.isles = None
+        if boundary and centroid:
             self.boundary = boundary
             self.centroid = centroid
             self.isles = isles if isles else []
-        else:
-            str_err = "To instantiate an Area you need at least: Boundary and Centroid"
-            raise GrassError(str_err)
 
         # set the attributes
         if self.attrs and self.cat:
             self.attrs.cat = self.cat
 
-        # geometry type
-        self.gtype = libvect.GV_AREA
-
     def __repr__(self):
         return "Area(%d)" % self.id if self.id else "Area( )"
 
@@ -1285,23 +1305,29 @@
         # get isles
         self.get_isles()
 
-    def get_points(self):
+    def get_points(self, line=None):
         """Return a Line object with the outer ring"""
-        line = Line()
+        line = Line() if line is None else line
         libvect.Vect_get_area_points(self.c_mapinfo, self.id, line.c_points)
         return line
 
-    def get_centroid(self):
+    def get_centroid(self, centroid=None):
         centroid_id = libvect.Vect_get_area_centroid(self.c_mapinfo, self.id)
-        #import pdb; pdb.set_trace()
+        if centroid:
+            centroid.id = centroid_id
+            centroid.read()
+            return centroid
         return Centroid(v_id=centroid_id, c_mapinfo=self.c_mapinfo,
                         area_id=self.id)
 
     def num_isles(self):
         return libvect.Vect_get_area_num_isles(self.c_mapinfo, self.id)
 
-    def get_isles(self):
+    def get_isles(self, isles=None):
         """Instantiate the boundary attribute reading area_id"""
+        if isles is not None:
+            isles.area_id = self.id
+            return isles
         return Isles(self.c_mapinfo, self.id)
 
     def area(self):
@@ -1316,11 +1342,11 @@
         """
         return bool(libvect.Vect_area_alive(self.c_mapinfo, self.id))
 
-    def bbox(self):
+    def bbox(self, bbox=None):
         """
         Vect_get_area_box
         """
-        bbox = Bbox()
+        bbox = bbox if bbox else Bbox()
         libvect.Vect_get_area_box(self.c_mapinfo, self.id, bbox.c_bbox)
         return bbox
 
@@ -1371,23 +1397,25 @@
                     isles=[Line(c_points=pp_isle[i].contents)
                            for i in xrange(n_isles.contents.value)])
 
-    def boundaries(self):
+    def boundaries(self, ilist=False):
         """Creates list of boundaries for given area.
 
         int Vect_get_area_boundaries(const struct Map_info *Map,
                                      int area, struct ilist *List)
         """
-        ilist = Ilist()
+        ilst = Ilist()
         libvect.Vect_get_area_boundaries(self.c_mapinfo, self.id,
-                                         ilist.c_ilist)
-        return ilist
+                                         ilst.c_ilist)
+        if ilist:
+            return ilist
+        return [Boundary(v_id, c_mapinfo=self.c_mapinfo) for v_id in ilst]
 
-    def cats(self):
+    def cats(self, cats=None):
         """Get area categories.
         int Vect_get_area_cats (const struct Map_info *Map,
                                 int area, struct line_cats *Cats)
         """
-        cats = Cats()
+        cats = cats if cats else Cats()
         libvect.Vect_get_area_cats(self.c_mapinfo, self.id, cats.c_cats)
         return cats
 
@@ -1398,16 +1426,16 @@
         """
         pass
 
-    def contain_pnt(self, pnt):
+    def contain_pnt(self, pnt, bbox=None):
         """Check if point is in area.
         int Vect_point_in_area(double x, double y,
                                const struct Map_info *Map,
                                int area, struct bound_box box)
         """
-        bbox = self.bbox()
-        libvect.Vect_point_in_area(pnt.x, pnt.y, self.c_mapinfo, self.id,
-                                   bbox.c_bbox)
-        return bbox
+        bbox = bbox if bbox else self.bbox()
+        return bool(libvect.Vect_point_in_area(pnt.x, pnt.y,
+                                               self.c_mapinfo, self.id,
+                                               bbox.c_bbox))
 
     def perimeter(self):
         """Calculate area perimeter.
@@ -1418,7 +1446,14 @@
         border = self.get_points()
         return libvect.Vect_area_perimeter(border.c_points)
 
+    def read(self, line=None, centroid=None, isles=None):
+        self.boundary = self.get_points(line)
+        self.centroid = self.get_centroid(centroid)
+        #self.isles = self.get_isles(isles)
+        libvect.Vect_read_line(self.c_mapinfo, None, self.c_cats,
+                               self.centroid.id)
 
+
 #
 # Define a dictionary to convert the feature type to name and or object
 #
@@ -1445,40 +1480,54 @@
           "volumes": None}
 
 
-def read_next_line(c_mapinfo, table=None, writable=False):
-    """Return the next geometry feature of a vector map."""
+def c_read_next_line(c_mapinfo, c_points, c_cats):
     v_id = c_mapinfo.contents.next_line
     v_id = v_id if v_id != 0 else None
-    c_points = ctypes.pointer(libvect.line_pnts())
-    c_cats = ctypes.pointer(libvect.line_cats())
     ftype = libvect.Vect_read_next_line(c_mapinfo, c_points, c_cats)
     if ftype == -2:
         raise StopIteration()
     if ftype == -1:
         raise
-    #if  GV_TYPE[ftype]['obj'] is not None:
+    return ftype, v_id, c_points, c_cats
+
+
+def read_next_line(c_mapinfo, table=None, writable=False,
+                   c_points=None, c_cats=None):
+    """Return the next geometry feature of a vector map."""
+    c_points = c_points if c_points else ctypes.pointer(libvect.line_pnts())
+    c_cats = c_cats if c_cats else ctypes.pointer(libvect.line_cats())
+    ftype, v_id, c_points, c_cats = c_read_next_line(c_mapinfo, c_points,
+                                                     c_cats)
     return GV_TYPE[ftype]['obj'](v_id=v_id, c_mapinfo=c_mapinfo,
                                  c_points=c_points, c_cats=c_cats,
                                  table=table, writable=writable)
 
 
-def read_line(feature_id, c_mapinfo, table=None, writable=False):
-    """Return a geometry object given the feature id and the c_mapinfo.
-    """
+def c_read_line(feature_id, c_mapinfo, c_points, c_cats):
     nmax = libvect.Vect_get_num_lines(c_mapinfo)
     if feature_id < 0:  # Handle negative indices
         feature_id += nmax + 1
     if feature_id > nmax:
         raise IndexError('Index out of range')
     if feature_id > 0:
-        c_points = ctypes.pointer(libvect.line_pnts())
-        c_cats = ctypes.pointer(libvect.line_cats())
         ftype = libvect.Vect_read_line(c_mapinfo, c_points, c_cats, feature_id)
-        if  GV_TYPE[ftype]['obj'] is not None:
-            return GV_TYPE[ftype]['obj'](v_id=feature_id, c_mapinfo=c_mapinfo,
-                                         c_points=c_points, c_cats=c_cats,
-                                         table=table, writable=writable)
+        return ftype, c_points, c_cats
     else:
         raise ValueError('The index must be >0, %r given.' % feature_id)
 
 
+def read_line(feature_id, c_mapinfo, table=None, writable=False,
+              c_points=None, c_cats=None):
+    """Return a geometry object given the feature id and the c_mapinfo.
+    """
+    c_points = c_points if c_points else ctypes.pointer(libvect.line_pnts())
+    c_cats = c_cats if c_cats else ctypes.pointer(libvect.line_cats())
+    ftype, c_points, c_cats = c_read_line(feature_id, c_mapinfo,
+                                          c_points, c_cats)
+    if GV_TYPE[ftype]['obj'] is not None:
+        return GV_TYPE[ftype]['obj'](v_id=feature_id, c_mapinfo=c_mapinfo,
+                                     c_points=c_points, c_cats=c_cats,
+                                     table=table, writable=writable)
+
+
+



More information about the grass-commit mailing list