Example #1
0
        def validate_geom(geom, coordinate_count=0):
            try:
                coordinate_count += geom.num_coords
                bbox = Polygon(settings.DATA_VALIDATION_BBOX)
                if coordinate_count > coord_limit:
                    message = 'Geometry has too many coordinates for Elasticsearch ({0}), Please limit to less then {1} coordinates of 5 digits of precision or less.'.format(
                        coordinate_count, coord_limit)
                    errors.append({
                        'type':
                        'ERROR',
                        'message':
                        'datatype: {0} value: {1} {2} - {3}'.format(
                            self.datatype_model.datatype, value, source,
                            message)
                    })

                if bbox.contains(geom) == False:
                    message = 'Geometry does not fall within the bounding box of the selected coordinate system. Adjust your coordinates or your settings.DATA_EXTENT_VALIDATION property.'
            except:
                message = 'Not a properly formatted geometry'
                errors.append({
                    'type':
                    'ERROR',
                    'message':
                    'datatype: {0} value: {1} {2} - {3}'.format(
                        self.datatype_model.datatype, value, source, message)
                })
Example #2
0
def assign_geofence(lat, long):
    coordinates = Point(float(lat), float(long))
    for area in GEOFENCE_BOUNDS:
        points_list = [(point['lat'], point['long']) for point in GEOFENCE_BOUNDS[area]]
        points_list.append(points_list[0])
        polygon = Polygon(points_list)
        if polygon.contains(coordinates):
            return area
    return UNKNOWN_GEOFENCE
Example #3
0
    def test_RD_to_WGS84_conversion(self):
        # Crude test, we check that Amsterdam Cityhall lies within a larger
        # Amsterdam bounding box we took from the factories file. All this in
        # WGS84 coordinates.
        polygon = self.gl.load_polygon(self.polygon_1)
        bbox_020 = Polygon(LinearRing(WGS84_BBOX_AMSTERDAM, srid=4326), srid=4326)
        self.assertEqual(bbox_020.srid, 4326)

        polygon.transform(ct=4326)
        self.assertTrue(bbox_020.contains(polygon))
Example #4
0
        def validate_geom(geom, coordinate_count=0):
            try:
                coordinate_count += geom.num_coords
                bbox = Polygon(settings.DATA_VALIDATION_BBOX)
                if coordinate_count > coord_limit:
                    message = 'Geometry has too many coordinates for Elasticsearch ({0}), Please limit to less then {1} coordinates of 5 digits of precision or less.'.format(coordinate_count, coord_limit)
                    errors.append({'type': 'ERROR', 'message': 'datatype: {0} value: {1} {2} - {3}'.format(self.datatype_model.datatype, value, source, message)})

                if bbox.contains(geom) == False:
                    message = 'Geometry does not fall within the bounding box of the selected coordinate system. Adjust your coordinates or your settings.DATA_EXTENT_VALIDATION property.'
            except:
                message = 'Not a properly formatted geometry'
                errors.append({'type': 'ERROR', 'message': 'datatype: {0} value: {1} {2} - {3}'.format(self.datatype_model.datatype, value, source, message)})
def import_dhm(dhm_filename: str, bounding_box: Polygon, srid=DEFAULT_DHM_SRID):

    # delete all old data within the bounding box
    if bounding_box:
        logger.debug("delete all data from database within geometry {}".format(bounding_box))
        DigitalHeightModel.objects.filter(point__within=bounding_box).delete()

    # getting the type of dhm and check if we import a vector (*.shp) or raster file (anything else)
    if dhm_filename.lower().endswith(".shp"):

        # vector implementation
        logger.debug("staring vector import")
        mapping = {'height': 'float',
                   'point': 'POINT', }
        lm = LayerMapping(DigitalHeightModel, dhm_filename, mapping)
        lm.save(verbose=True)  # save the data to the database

    # raster implementation
    else:
        with rasterio.open(dhm_filename) as dhm_datasource:
            crs = dhm_datasource.crs
            np_heightmap = dhm_datasource.read(1)  # we assume there is a single height band
            rows, cols = np_heightmap.shape
            logger.debug("starting raster import with {} points".format(rows * cols))

            # add all valid points to a list
            dhm_list = []
            for x in range(0, rows):
                for y in range(0, cols):
                    x_m, y_m = dhm_datasource.affine * (x, y)
                    point = Point(x_m, y_m, srid=crs)  # convert x,y to meters in crs

                    # only import points within the bounding polygon
                    if bounding_box:
                        if not bounding_box.contains(point):
                            continue
                    dhm_point = DigitalHeightModel()
                    dhm_point.point = point
                    dhm_point.height = np_heightmap[x, y]
                    dhm_list.append(dhm_point)

            # bulk insert the batch into the database
            count = 0
            while True:
                batch = list(islice(dhm_list, BATCH_SIZE))
                if not batch:
                    break
                DigitalHeightModel.objects.bulk_create(batch, BATCH_SIZE)
                count += BATCH_SIZE
                logger.debug("inserted {} from {} entries ({} %)".format(count, len(dhm_list),
                                                                         count * 100 / len(dhm_list)))
Example #6
0
def InPoly(request, x, y):
    path = os.path.abspath(os.path.join(
        os.path.dirname(__file__))) + '/data/polygon.xlsx'
    bk = xlrd.open_workbook(path)
    table = bk.sheets()[0]
    nrows = table.nrows
    ncols = table.ncols
    plist = []
    for i in range(1, nrows):
        plist.append(
            GEOSGeometry('POINT(%s %s)' %
                         (table.cell(i, 1).value, table.cell(i, 2).value)))
    p = Polygon(plist)
    print p
    # pnt = Point(113.885, 22.517)
    lon = float(x)
    lat = float(y)
    pnt = Point(lon, lat)
    InOrNot = p.contains(pnt)
    # InOrNot=p.filter(poly__contains=pnt)
    Bldict = {"InOrNot": InOrNot}
    print json.dumps(Bldict)
    return HttpResponse(json.dumps(Bldict), content_type="application/json")
Example #7
0
class PaymentAreasTest(TestCase):
    def setUp(self):
        self.centralstation = Polygon([ 
                [ 13.136215, 55.702742 ], [ 13.163681, 55.737162 ], 
                [ 13.224792, 55.736389 ], [ 13.259125, 55.698099 ], 
                [ 13.209000, 55.682424 ], [ 13.175354, 55.683391 ], 
                [ 13.136215, 55.702742 ] ])
        self.customer = Customer.objects.create(name='SJ')
        self.area = PaymentArea.objects.create(identifier='SJ Lund',
                                               area=self.centralstation,
                                               owner=self.customer)
        self.client = Client()

    def test_areas_by_point(self):
        """
        Tests that the areas are retuned when querying for a location
        """
        p = Point(13.18686, 55.70605)
        self.failUnless(self.centralstation.contains(p))
        self.failUnless(PaymentArea.objects.all()[0].area.contains(p))
        self.failUnless(self.area in list(PaymentArea.objects.filter(area__contains=p)))

    def test_local_options_view(self):
        """
        Get the local options based on the position
        """
        response = self.client.get(
            reverse('discovery_areas')+'?position=13.18686,55.70605')
        self.failUnlessEqual(response.status_code, 200)
        self.failUnlessEqual(json.loads(response.content)['payload'], 
                             [{u'owner': u'SJ', u'identifier': u'SJ Lund', u'id':2}])

        response = self.client.get(
            reverse('discovery_areas')+'?position=34.18686,25.70605')
        self.failUnlessEqual(response.status_code, 200)
        self.failUnlessEqual(json.loads(response.content)['payload'], [])
Example #8
0
def map_tile(request, layer_slug, boundary_slug, tile_zoom, tile_x, tile_y, format):
    if not has_imaging_library: raise Http404("Cairo is not available.")
    
    layer = get_object_or_404(MapLayer, slug=layer_slug)
    
    # Load basic parameters.
    try:
        size = int(request.GET.get('size', '256' if format not in ('json', 'jsonp') else '64'))
        if size not in (64, 128, 256, 512, 1024): raise ValueError()
        
        srs = int(request.GET.get('srs', '3857'))
    except ValueError:
        raise Http404("Invalid parameter.")
        
    db_srs, out_srs = get_srs(srs)
    
    # Get the bounding box for the tile, in the SRS of the output.
    
    try:
        tile_x = int(tile_x)
        tile_y = int(tile_y)
        tile_zoom = int(tile_zoom)
    except ValueError:
        raise Http404("Invalid parameter.")
    
    # Guess the world size. We need to know the size of the world in
    # order to locate the bounding box of any viewport at zoom levels
    # greater than zero.
    if "radius" not in request.GET:
        p = Point( (-90.0, 0.0), srid=db_srs.srid )
        p.transform(out_srs)
        world_left = p[0]*2
        world_top = -world_left
        world_size = -p[0] * 4.0
    else:
        p = Point((0,0), srid=out_srs.srid )
        p.transform(db_srs)
        p1 = Point([p[0] + 1.0, p[1] + 1.0], srid=db_srs.srid)
        p.transform(out_srs)
        p1.transform(out_srs)
        world_size = math.sqrt(abs(p1[0]-p[0])*abs(p1[1]-p[1])) * float(request.GET.get('radius', '50'))
        world_left = p[0] - world_size/2.0
        world_top = p[1] + world_size/2.0
    tile_world_size = world_size / math.pow(2.0, tile_zoom)

    p1 = Point( (world_left + tile_world_size*tile_x, world_top - tile_world_size*tile_y) )
    p2 = Point( (world_left + tile_world_size*(tile_x+1), world_top - tile_world_size*(tile_y+1)) )
    bbox = Polygon( ((p1[0], p1[1]),(p2[0], p1[1]),(p2[0], p2[1]),(p1[0], p2[1]),(p1[0], p1[1])), srid=out_srs.srid )
    
    # A function to convert world coordinates in the output SRS into
    # pixel coordinates.
       
    blon1, blat1, blon2, blat2 = bbox.extent
    bx = float(size)/(blon2-blon1)
    by = float(size)/(blat2-blat1)
    def viewport(coord):
        # Convert the world coordinates to image coordinates according to the bounding box
        # (in output SRS).
        return float(coord[0] - blon1)*bx, (size-1) - float(coord[1] - blat1)*by

    # Convert the bounding box to the database SRS.

    db_bbox = bbox.transform(db_srs, clone=True)
    
    # What is the width of a pixel in the database SRS? If it is smaller than
    # SIMPLE_SHAPE_TOLERANCE, load the simplified geometry from the database.
    
    shape_field = 'shape'
    pixel_width = (db_bbox.extent[2]-db_bbox.extent[0]) / size / 2
    if pixel_width > boundaries_settings.SIMPLE_SHAPE_TOLERANCE:
        shape_field = 'simple_shape'

    # Query for any boundaries that intersect the bounding box.
    
    boundaries = Boundary.objects.filter(set=layer.boundaryset, shape__intersects=db_bbox)\
        .values("id", "slug", "name", "label_point", shape_field)
    if boundary_slug: boundaries = boundaries.filter(slug=boundary_slug)
    boundary_id_map = dict( (b["id"], b) for b in boundaries )
    
    if len(boundaries) == 0:
        if format == "svg":
            raise Http404("No boundaries here.")
        elif format in ("png", "gif"):
            # Send a 1x1 transparent image. Google is OK getting 404s for map tile images
            # but OpenLayers isn't. Maybe cache the image?
            im = cairo.ImageSurface(cairo.FORMAT_ARGB32, 1, 1)
            ctx = cairo.Context(im)
            buf = StringIO()
            im.write_to_png(buf)
            v = buf.getvalue()
            if format == "gif": v = convert_png_to_gif(v)
            r = HttpResponse(v, content_type='image/' + format)
            r["Content-Length"] = len(v)
            return r
        elif format == "json":
            # Send an empty "UTF-8 Grid"-like response.
            return HttpResponse('{"error":"nothing-here"}', content_type="application/json")
        elif format == "jsonp":
            # Send an empty "UTF-8 Grid"-like response.
            return HttpResponse(request.GET.get("callback", "callback") +  '({"error":"nothing-here"})', content_type="text/javascript")
    
    # Query for layer style information and then set it on the boundary objects.
    
    styles = layer.boundaries.filter(boundary__in=boundary_id_map.keys())
    for style in styles:
        boundary_id_map[style.boundary_id]["style"] = style
    
    # Create the image buffer.
    if format in ('png', 'gif'):
        im = cairo.ImageSurface(cairo.FORMAT_ARGB32, size, size)
    elif format == 'svg':
        buf = StringIO()
        im = cairo.SVGSurface(buf, size, size)
    elif format in ('json', 'jsonp'):
        # This is going to be a "UTF-8 Grid"-like response, but we generate that
        # info by first creating an actual image, with colors coded by index to
        # represent which boundary covers which pixels.
        im = cairo.ImageSurface(cairo.FORMAT_RGB24, size, size)

	# Color helpers.
    def get_rgba_component(c):
        return c if isinstance(c, float) else c/255.0
    def get_rgba_tuple(clr, alpha=.25):
        # Colors are specified as tuples/lists with 3 (RGB) or 4 (RGBA)
        # components. Components that are float values must be in the
        # range 0-1, while all other values are in the range 0-255.
        # Because .gif does not support partial transparency, alpha values
        # are forced to 1.
        return (get_rgba_component(clr[0]), get_rgba_component(clr[1]), get_rgba_component(clr[2]),
            get_rgba_component(clr[3]) if len(clr) == 4 and format != 'gif' else (alpha if format != 'gif' else 1.0))

    # Create the drawing surface.
    ctx = cairo.Context(im)
    ctx.select_font_face(maps_settings.MAP_LABEL_FONT, cairo.FONT_SLANT_NORMAL, cairo.FONT_WEIGHT_NORMAL)
    
    if format in ('json', 'jsonp'):
        # For the UTF-8 Grid response, turn off anti-aliasing since the color we draw to each pixel
        # is a code for what is there.
        ctx.set_antialias(cairo.ANTIALIAS_NONE)
    
    def max_extent(shape):
        a, b, c, d = shape.extent
        return max(c-a, d-b)
    
    # Transform the boundaries to output coordinates.
    draw_shapes = []
    for bdry in boundaries:
        if not "style" in bdry: continue # Boundary had no corresponding MapLayerBoundary
        
        shape = bdry[shape_field]
        
        # Simplify to the detail that could be visible in the output. Although
        # simplification may be a little expensive, drawing a more complex
        # polygon is even worse.
        try:
            shape = shape.simplify(pixel_width, preserve_topology=True)
        except: # GEOSException
            pass # try drawing original
        
        # Make sure the results are all MultiPolygons for consistency.
        if shape.__class__.__name__ == 'Polygon':
            shape = MultiPolygon((shape,), srid=db_srs.srid)
        else:
            # Be sure to override SRS (for Google, see above). This code may
            # never execute?
            shape = MultiPolygon(list(shape), srid=db_srs.srid)

        # Is this shape too small to be visible?
        ext_dim = max_extent(shape)
        if ext_dim < pixel_width:
            continue

        # Convert the shape to the output SRS.
        shape.transform(out_srs)
        
        draw_shapes.append( (len(draw_shapes), bdry, shape, ext_dim) )
        
    # Draw shading, for each linear ring of each polygon in the multipolygon.
    for i, bdry, shape, ext_dim in draw_shapes:
        if not bdry["style"].color and format not in ('json', 'jsonp'): continue
        for polygon in shape:
            for ring in polygon: # should just be one since no shape should have holes?
                color = bdry["style"].color
                
                if format in ('json', 'jsonp'):
                    # We're returning a "UTF-8 Grid" indicating which feature is at
                    # each pixel location on the grid. In order to compute the grid,
                    # we draw to an image surface with a distinct color for each feature.
                    # Then we convert the pixel data into the UTF-8 Grid format.
                    ctx.set_source_rgb(*[ (((i+1)/(256**exp)) % 256)/255.0 for exp in xrange(3) ])
                
                elif isinstance(color, (tuple, list)):
                    # Specify a 3/4-tuple (or list) for a solid color.
                    ctx.set_source_rgba(*get_rgba_tuple(color))
                        
                elif isinstance(color, dict):
                    # Specify a dict of the form { "color1": (R,G,B), "color2": (R,G,B) } to
                    # create a solid fill of color1 plus smaller stripes of color2.
                    if color.get("color", None) != None:
                        ctx.set_source_rgba(*get_rgba_tuple(color["color"]))
                    elif color.get("color1", None) != None and color.get("color2", None) != None:
                        pat = cairo.LinearGradient(0.0, 0.0, size, size)
                        for x in xrange(0,size, 32): # divisor of the size so gradient ends at the end
                            pat.add_color_stop_rgba(*([float(x)/size] + list(get_rgba_tuple(color["color1"], alpha=.3))))
                            pat.add_color_stop_rgba(*([float(x+28)/size] + list(get_rgba_tuple(color["color1"], alpha=.3))))
                            pat.add_color_stop_rgba(*([float(x+28)/size] + list(get_rgba_tuple(color["color2"], alpha=.4))))
                            pat.add_color_stop_rgba(*([float(x+32)/size] + list(get_rgba_tuple(color["color2"], alpha=.4))))
                        ctx.set_source(pat)
                    else:
                        continue # skip fill
                else:
                    continue # Unknown color data structure.
                ctx.new_path()
                for pt in ring.coords:
                    ctx.line_to(*viewport(pt))
                ctx.fill()
                
    # Draw outlines, for each linear ring of each polygon in the multipolygon.
    for i, bdry, shape, ext_dim in draw_shapes:
        if format in ('json', 'jsonp'): continue
        if ext_dim < pixel_width * 3: continue # skip outlines if too small
        color = bdry["style"].color
        for polygon in shape:
            for ring in polygon: # should just be one since no shape should have holes?
                ctx.new_path()
                for pt in ring.coords:
                    ctx.line_to(*viewport(pt))
                    
                if not isinstance(color, dict) or not "border" in color or not "width" in color["border"]:
                    if ext_dim < pixel_width * 60:
                        ctx.set_line_width(1)
                    else:
                        ctx.set_line_width(2.5)
                else:
                    ctx.set_line_width(color["border"]["width"])
                    
                if not isinstance(color, dict) or not "border" in color or not "color" in color["border"]:
                    ctx.set_source_rgba(.3,.3,.3, .75)  # grey, semi-transparent
                else:
                    ctx.set_source_rgba(*get_rgba_tuple(color["border"]["color"], alpha=.75))
                ctx.stroke_preserve()
                
    # Draw labels.
    for i, bdry, shape, ext_dim in draw_shapes:
        if format in ('json', 'jsonp'): continue
        if ext_dim < pixel_width * 20: continue
        
        color = bdry["style"].color
        if isinstance(color, dict) and "label" in color and color["label"] == None: continue
        
        # Get the location of the label stored in the database, or fall back to
        # GDAL routine point_on_surface to get a point quickly.
        if bdry["style"].label_point:
            # Override the SRS on the point (for Google, see above). Then transform
            # it to world coordinates.
            pt = Point(tuple(bdry["style"].label_point), srid=db_srs.srid)
            pt.transform(out_srs)
        elif bdry["label_point"]:
            # Same transformation as above.
            pt = Point(tuple(bdry["label_point"]), srid=db_srs.srid)
            pt.transform(out_srs)
        else:
            # No label_point is specified so try to find one by using the
            # point_on_surface to find a point that is in the shape and
            # in the viewport's bounding box.
            try:
                pt = bbox.intersection(shape).point_on_surface
            except:
                # Don't know why this would fail. Bad geometry of some sort.
                # But we really don't want to leave anything unlabeled so
                # try the center of the bounding box.
                pt = bbox.centroid
                if not shape.contains(pt):
                    continue
        
        # Transform to world coordinates and ensure it is within the bounding box.
        if not bbox.contains(pt):
            # If it's not in the bounding box and the shape occupies most of this
            # bounding box, try moving the point to somewhere in the current tile.
            try:
                inters = bbox.intersection(shape)
                if inters.area < bbox.area/3: continue
                pt = inters.point_on_surface
            except:
                continue
        pt = viewport(pt)
        
        txt = bdry["name"]
        if isinstance(bdry["style"].metadata, dict): txt = bdry["style"].metadata.get("label", txt)
        if ext_dim > size * pixel_width:
            ctx.set_font_size(18)
        else:
            ctx.set_font_size(12)
        x_off, y_off, tw, th = ctx.text_extents(txt)[:4]
        
        # Is it within the rough bounds of the shape and definitely the bounds of this tile?
        if tw < ext_dim/pixel_width/5 and th < ext_dim/pixel_width/5 \
            and pt[0]-x_off-tw/2-4 > 0 and pt[1]-th-4 > 0 and pt[0]-x_off+tw/2+7 < size and pt[1]+6 < size:
            # Draw the background rectangle behind the text.
            ctx.set_source_rgba(0,0,0,.55)  # black, some transparency
            ctx.new_path()
            ctx.line_to(pt[0]-x_off-tw/2-4,pt[1]-th-4)
            ctx.rel_line_to(tw+9, 0)
            ctx.rel_line_to(0, +th+8)
            ctx.rel_line_to(-tw-9, 0)
            ctx.fill()
            
            # Now a drop shadow (also is partially behind the first rectangle).
            ctx.set_source_rgba(0,0,0,.3)  # black, some transparency
            ctx.new_path()
            ctx.line_to(pt[0]-x_off-tw/2-4,pt[1]-th-4)
            ctx.rel_line_to(tw+11, 0)
            ctx.rel_line_to(0, +th+10)
            ctx.rel_line_to(-tw-11, 0)
            ctx.fill()
            
            # Draw the text.
            ctx.set_source_rgba(1,1,1,1)  # white
            ctx.move_to(pt[0]-x_off-tw/2,pt[1])
            ctx.show_text(txt)
                
    if format in ("png", "gif"):
        # Convert the image buffer to raw bytes.
        buf = StringIO()
        im.write_to_png(buf)
        v = buf.getvalue()
        if format == "gif": v = convert_png_to_gif(v)
        
        # Form the response.
        r = HttpResponse(v, content_type='image/' + format)
        r["Content-Length"] = len(v)
    
    elif format == "svg":
        im.finish()
        v = buf.getvalue()
        r = HttpResponse(v, content_type='image/svg+xml')
        r["Content-Length"] = len(v)
    
    elif format in ('json', 'jsonp'):
        # Get the bytes, which are RGBA sequences.
        buf1 = list(im.get_data())
        
        # Convert the 4-byte sequences back into integers that refer back to
        # the boundary list. Count the number of pixels for each shape.
        shapeidx = []
        shapecount = { }
        for i in xrange(0, size*size):
            b = ord(buf1[i*4+2])*(256**0) + ord(buf1[i*4+1])*(256**1) + ord(buf1[i*4+0])*(256**2)
            shapeidx.append(b)
            if b > 0: shapecount[b] = shapecount.get(b, 0) + 1
            
        # Assign low unicode code points to the most frequently occuring pixel values,
        # except always map zero to character 32.
        shapecode1 = { }
        shapecode2 = { }
        for k, count in sorted(shapecount.items(), key = lambda kv : kv[1]):
            b = len(shapecode1) + 32 + 1
            if b >= 34: b += 1
            if b >= 92: b += 1
            shapecode1[k] = b
            shapecode2[b] = draw_shapes[k-1]
            
        buf = ''
        if format == 'jsonp': buf += request.GET.get("callback", "callback") + "(\n"
        buf += '{"grid":['
        for row in xrange(size):
            if row > 0: buf += ",\n         "
            buf += json.dumps(u"".join(unichr(shapecode1[k] if k != 0 else 32) for k in shapeidx[row*size:(row+1)*size]))
        buf += "],\n"
        buf += ' "keys":' + json.dumps([""] + [shapecode2[k][1]["slug"] for k in sorted(shapecode2)], separators=(',', ':')) + ",\n"
        buf += ' "data":' + json.dumps(dict( 
                    (shapecode2[k][1]["slug"], {
                            "name": shapecode2[k][1]["name"],
                    })
                    for k in sorted(shapecode2)), separators=(',', ':'))
        buf += "}"
        if format == 'jsonp': buf += ")"
        
        if format == "json":
            r = HttpResponse(buf, content_type='application/json')
        else:
            r = HttpResponse(buf, content_type='text/javascript')
    
    return r
from django.contrib.gis.geos import Point, Polygon
pnt = Point(1, 1)
poly = Polygon( ((0, 0), (0, 2), (2, 2), (2, 0), (0, 0)) )
<trkpt lat="36.936607018" lon="-122.091610313"></trkpt>
    <trkpt lat="36.958683905" lon="-122.162639595"></trkpt>
    <trkpt lat="36.987815521" lon="-122.21506135"></trkpt>
    <trkpt lat="36.985890676" lon="-122.407740579"></trkpt>
    <trkpt lat="36.938457841" lon="-122.407684788"></trkpt>
    <trkpt lat="36.547896033" lon="-122.403661688"></trkpt>
    <trkpt lat="36.54776547" lon="-121.992926099"></trkpt>
    <trkpt lat="36.593976161" lon="-121.989732818"></trkpt>
    <trkpt lat="36.651878564" lon="-121.95285214"></trkpt>
    <trkpt lat="36.661324564" lon="-121.909793526"></trkpt>
    <trkpt lat="36.626844509" lon="-121.880774172"></trkpt>
    <trkpt lat="36.700304474" lon="-121.835279292"></trkpt>
    <trkpt lat="36.761488333" lon="-121.823453925"></trkpt>
    <trkpt lat="36.803637867" lon="-121.812197052"></trkpt>
    <trkpt lat="36.876714034" lon="-121.853754579"></trkpt>
    <trkpt lat="36.940579814" lon="-121.895316436"></trkpt>
    <trkpt lat="36.961193612" lon="-121.929400728"></trkpt>
    <trkpt lat="36.940762557" lon="-121.971105151"></trkpt>
    <trkpt lat="36.948092066" lon="-122.002927721"></trkpt>
    <trkpt lat="36.936402112" lon="-122.028084038"></trkpt>
    <trkpt lat="36.936607018" lon="-122.091610313"></trkpt>



poly.contains(pnt)
	def testIfPointInSafeRegion(self, lat,lon):
                pnt=Point(lat, lon)
                
                poly=Polygon(((36.936607018, -122.091610313), (36.958683905,-122.162639595) ,(36.987815521,-122.21506135) ,(37.15981,-122.56020),(36.69,-122.56020) ,(36.54776547,-121.992926099) ,(36.593976161,-121.989732818) ,(36.651878564,-121.95285214) ,(36.661324564,-121.909793526),(36.626844509,-121.880774172) ,(36.700304474,-121.835279292) ,(36.761488333,-121.823453925) ,(36.803637867,-121.812197052) ,(36.876714034,-121.853754579) ,(36.940579814,-121.895316436) ,(36.961193612,-121.929400728),(36.940762557,-121.971105151) ,(36.948092066,-122.002927721) ,(36.936402112,-122.028084038) ,(36.936607018,-122.091610313)))
                
                return poly.contains(pnt)