web/lib/django/contrib/gis/gdal/field.py
changeset 0 0d40e90630ef
equal deleted inserted replaced
-1:000000000000 0:0d40e90630ef
       
     1 from ctypes import byref, c_int
       
     2 from datetime import date, datetime, time
       
     3 from django.contrib.gis.gdal.base import GDALBase
       
     4 from django.contrib.gis.gdal.error import OGRException
       
     5 from django.contrib.gis.gdal.prototypes import ds as capi
       
     6 
       
     7 # For more information, see the OGR C API source code:
       
     8 #  http://www.gdal.org/ogr/ogr__api_8h.html
       
     9 #
       
    10 # The OGR_Fld_* routines are relevant here.
       
    11 class Field(GDALBase):
       
    12     "A class that wraps an OGR Field, needs to be instantiated from a Feature object."
       
    13 
       
    14     #### Python 'magic' routines ####
       
    15     def __init__(self, feat, index):
       
    16         """
       
    17         Initializes on the feature pointer and the integer index of
       
    18         the field within the feature.
       
    19         """
       
    20         # Setting the feature pointer and index.
       
    21         self._feat = feat
       
    22         self._index = index
       
    23         
       
    24         # Getting the pointer for this field.
       
    25         fld_ptr = capi.get_feat_field_defn(feat, index)
       
    26         if not fld_ptr:
       
    27             raise OGRException('Cannot create OGR Field, invalid pointer given.')
       
    28         self.ptr = fld_ptr
       
    29 
       
    30         # Setting the class depending upon the OGR Field Type (OFT)
       
    31         self.__class__ = OGRFieldTypes[self.type]
       
    32 
       
    33         # OFTReal with no precision should be an OFTInteger.
       
    34         if isinstance(self, OFTReal) and self.precision == 0:
       
    35             self.__class__ = OFTInteger
       
    36 
       
    37     def __str__(self):
       
    38         "Returns the string representation of the Field."
       
    39         return str(self.value).strip()
       
    40 
       
    41     #### Field Methods ####
       
    42     def as_double(self):
       
    43         "Retrieves the Field's value as a double (float)."
       
    44         return capi.get_field_as_double(self._feat, self._index)
       
    45 
       
    46     def as_int(self):
       
    47         "Retrieves the Field's value as an integer."
       
    48         return capi.get_field_as_integer(self._feat, self._index)
       
    49 
       
    50     def as_string(self):
       
    51         "Retrieves the Field's value as a string."
       
    52         return capi.get_field_as_string(self._feat, self._index)
       
    53 
       
    54     def as_datetime(self):
       
    55         "Retrieves the Field's value as a tuple of date & time components."
       
    56         yy, mm, dd, hh, mn, ss, tz = [c_int() for i in range(7)]
       
    57         status = capi.get_field_as_datetime(self._feat, self._index, byref(yy), byref(mm), byref(dd),
       
    58                                             byref(hh), byref(mn), byref(ss), byref(tz))
       
    59         if status:
       
    60             return (yy, mm, dd, hh, mn, ss, tz)
       
    61         else:
       
    62             raise OGRException('Unable to retrieve date & time information from the field.')
       
    63 
       
    64     #### Field Properties ####
       
    65     @property
       
    66     def name(self):
       
    67         "Returns the name of this Field."
       
    68         return capi.get_field_name(self.ptr)
       
    69 
       
    70     @property
       
    71     def precision(self):
       
    72         "Returns the precision of this Field."
       
    73         return capi.get_field_precision(self.ptr)
       
    74 
       
    75     @property
       
    76     def type(self):
       
    77         "Returns the OGR type of this Field."
       
    78         return capi.get_field_type(self.ptr)
       
    79 
       
    80     @property
       
    81     def type_name(self):
       
    82         "Return the OGR field type name for this Field."
       
    83         return capi.get_field_type_name(self.type)
       
    84 
       
    85     @property
       
    86     def value(self):
       
    87         "Returns the value of this Field."
       
    88         # Default is to get the field as a string.
       
    89         return self.as_string()
       
    90 
       
    91     @property
       
    92     def width(self):
       
    93         "Returns the width of this Field."
       
    94         return capi.get_field_width(self.ptr)
       
    95 
       
    96 ### The Field sub-classes for each OGR Field type. ###
       
    97 class OFTInteger(Field):
       
    98     @property
       
    99     def value(self):
       
   100         "Returns an integer contained in this field."
       
   101         return self.as_int()
       
   102 
       
   103     @property
       
   104     def type(self):
       
   105         """
       
   106         GDAL uses OFTReals to represent OFTIntegers in created
       
   107         shapefiles -- forcing the type here since the underlying field
       
   108         type may actually be OFTReal.
       
   109         """
       
   110         return 0
       
   111 
       
   112 class OFTReal(Field):
       
   113     @property
       
   114     def value(self):
       
   115         "Returns a float contained in this field."
       
   116         return self.as_double()
       
   117 
       
   118 # String & Binary fields, just subclasses
       
   119 class OFTString(Field): pass
       
   120 class OFTWideString(Field): pass
       
   121 class OFTBinary(Field): pass
       
   122 
       
   123 # OFTDate, OFTTime, OFTDateTime fields.
       
   124 class OFTDate(Field):
       
   125     @property
       
   126     def value(self):
       
   127         "Returns a Python `date` object for the OFTDate field."
       
   128         try:
       
   129             yy, mm, dd, hh, mn, ss, tz = self.as_datetime()
       
   130             return date(yy.value, mm.value, dd.value)
       
   131         except (ValueError, OGRException):
       
   132             return None
       
   133 
       
   134 class OFTDateTime(Field):
       
   135     @property
       
   136     def value(self):
       
   137         "Returns a Python `datetime` object for this OFTDateTime field."
       
   138         # TODO: Adapt timezone information.
       
   139         #  See http://lists.maptools.org/pipermail/gdal-dev/2006-February/007990.html
       
   140         #  The `tz` variable has values of: 0=unknown, 1=localtime (ambiguous), 
       
   141         #  100=GMT, 104=GMT+1, 80=GMT-5, etc.
       
   142         try:
       
   143             yy, mm, dd, hh, mn, ss, tz = self.as_datetime()
       
   144             return datetime(yy.value, mm.value, dd.value, hh.value, mn.value, ss.value)
       
   145         except (ValueError, OGRException):
       
   146             return None
       
   147 
       
   148 class OFTTime(Field):
       
   149     @property
       
   150     def value(self):
       
   151         "Returns a Python `time` object for this OFTTime field."
       
   152         try:
       
   153             yy, mm, dd, hh, mn, ss, tz = self.as_datetime()
       
   154             return time(hh.value, mn.value, ss.value)
       
   155         except (ValueError, OGRException):
       
   156             return None
       
   157 
       
   158 # List fields are also just subclasses
       
   159 class OFTIntegerList(Field): pass
       
   160 class OFTRealList(Field): pass
       
   161 class OFTStringList(Field): pass
       
   162 class OFTWideStringList(Field): pass
       
   163 
       
   164 # Class mapping dictionary for OFT Types and reverse mapping.
       
   165 OGRFieldTypes = { 0 : OFTInteger,
       
   166                   1 : OFTIntegerList,
       
   167                   2 : OFTReal,
       
   168                   3 : OFTRealList,
       
   169                   4 : OFTString,
       
   170                   5 : OFTStringList,
       
   171                   6 : OFTWideString,
       
   172                   7 : OFTWideStringList,
       
   173                   8 : OFTBinary,
       
   174                   9 : OFTDate,
       
   175                  10 : OFTTime,
       
   176                  11 : OFTDateTime,
       
   177                   }
       
   178 ROGRFieldTypes = dict([(cls, num) for num, cls in OGRFieldTypes.items()])