Example #1
0
def main():
    """ Our main program.
    """
    # Start by deleting our existing polygons.

    print "Deleting existing polygons..."

    Outline.objects.all().delete()

    # Load all the Location objects into memory, for speed of access.

    print "Loading locations into memory..."

    locations = {} # Maps location code to Location object.
    for location in Location.objects.all():
        locations[location.code] = location

    print
    print "Loaded %d locations" % len(locations)
    print

    # Now process each of our polygon files in turn.

    polygonDir = os.path.join("..", "Location Data", "polygons")
    for fName in os.listdir(polygonDir):
        print "Processing %s..." % fName
        f = open(os.path.join(polygonDir, fName), "r")
        for line in f.readlines():
            locationCode,wkt = line.rstrip().split("\t")

            if locationCode not in locations:
                print "Unknown location: " + locationCode
                continue

            outline = Outline()
            outline.location = locations[locationCode]
            outline.outline  = GEOSGeometry(wkt)
            outline.save()

    # That's all, folks!

    print "All done!"
Example #2
0
def confirm(request):
    """ Confirm with the user that he/she wants to build a new polygon.
    """
    if request.method == "GET":
        src_locs = request.GET['src_locs']
        dst_loc  = request.GET['dst_loc']
        loc      = Location.objects.get(code=dst_loc)

        msg = "Are you sure you want to rebuild the polygon for " \
            + str(loc.name) + "?  This will replace the existing polygon " \
            + "for this location."

        return render_to_response("editor/templates/confirm.html",
                                  {'title'        : "Geodatabase Editor",
                                   'heading'      : "Polygon Builder",
                                   'message'      : msg,
                                   'extra_params' : {'src_locs' : src_locs,
                                                     'dst_loc'  : dst_loc},
                                  },
                                  context_instance=RequestContext(request))

    if request.POST.get("confirm") != "1":
        return HttpResponseRedirect("/geo/editor/buildpolygon")

    # If we get here, the user has confirmed that he/she wants to proceed.  Get
    # the desired source and destination locations.

    src_loc_codes = request.POST['src_locs']
    dst_loc_code  = request.POST['dst_loc']

    src_locs = []
    for src_code in src_loc_codes.split(","):
        try:
            src_locs.append(Location.objects.get(code=src_code))
        except Location.DoesNotExist:
            pass

    try:
        dst_loc = Location.objects.get(code=dst_loc_code)
    except Location.DoesNotExist:
        return HttpResponse("Missing destination location.")

    # Build the outline out of the desired source outlines.

    polygons = []
    for loc in src_locs:
        for outline in Outline.objects.filter(location=loc):
            if outline.outline.geom_type == "MultiPolygon":
                for poly in outline.outline:
                    polygons.append(poly)
            elif outline.outline.geom_type == "Polygon":
                polygons.append(outline.outline)

    mpoly = MultiPolygon(polygons)
    union = mpoly.cascaded_union.buffer(0)

    if union.geom_type == "MultiPolygon":
        mpoly = union
    elif union.geom_type == "Polygon":
        # Wrap the polygon into a MultiPolygon so we can save it into the
        # database.
        mpoly = MultiPolygon([union])

    # Save the new outline into the database for this location.

    for outline in Outline.objects.filter(location=dst_loc):
        outline.delete()

    outline = Outline()
    outline.location = dst_loc
    outline.outline = mpoly
    outline.save()

    # Finally, redirect the user to the "done" page so we can tell the user
    # that we've finished.

    return HttpResponseRedirect("/geo/editor/buildpolygon/done/?dst_loc=" +
                                dst_loc_code)
Example #3
0
def main(request, loc_code):
    """ Respond to the "/geo/editor/outline/XYZ/" URL.

        We let the user edit the outline for the given location.
    """
    if not request.user.is_authenticated:
        return HttpResponseRedirect("/geo/editor/")

    try:
        location = Location.objects.get(code=loc_code)
    except Location.DoesNotExist:
        return HttpResponseRedirect("/geo/editor/location/")

    try:
        outline = Outline.objects.get(location=location)
    except Outline.DoesNotExist:
        outline = Outline()
        outline.location = location
        outline.save()

    formType = getMapForm()

    if request.method == "GET":

        # We're visiting the page for the first time -> just display it.

        wkt = outline.outline
        form = formType({'geometry' : wkt})

    elif request.method == "POST":

        # The user is submitting our form.  If the user clicked on the
        # "Finished" button, redirect the user back to the main location editor
        # page.

        if request.POST.get("finished") == "Finished":
            return HttpResponseRedirect("/geo/editor/location/")

        # Save the updated outline back into the database.

        form = formType(request.POST)
        try:
            if form.is_valid():
                wkt = form.cleaned_data['geometry']
                outline.outline = wkt
                outline.save()

                # Send a signal telling the rest of the system that the outline
                # has changed.

                outline_changed.send(sender=None, loc_code=loc_code)

                # Finally, tell the user's web browser to reload the page.

                return HttpResponseRedirect("/geo/editor/outline/" +
                                            loc_code + "/")
        except ValueError:
            pass

    # If we get here, display the form.

    imports = []
    imports.append('<script src="http://openlayers.org/api/OpenLayers.js">')
    imports.append('</script>')

    return render_to_response("editor/templates/location_wrapper.html",
                              {'tab'             : "outline",
                               'heading'         : "Editing " + str(location),
                               'location'        : location,
                               'template_name'   : "location_outline.html",
                               'extra_head_tags' : imports,
                               'errMsg'          : None,
                               'form'            : form,
                              },
                              context_instance=RequestContext(request))
Example #4
0
def import_data(f, log):
    """ Import the data in 'f', recording errors etc into 'log'.

        'f' is a temporary file holding the data to import, and 'log' is a list
        of strings.

        We import the data from 'f', updating the Location records, etc, as we
        go along.  If we encounter any errors, or want to notify the user of an
        action which has occurred, we append the error or notification to the
        'log' list.
    """
    locs_with_names = set() # Set of location codes which we had names for.
    cur_loc         = None  # Location object we are currently importing.

    for line in f:
        line = line.rstrip()
        if len(line) == 0: continue # Ignore blanks.
        parts = line.split("\t")
        if len(parts) < 2:
            log.append("File contains invalid data.  Are you sure it's " \
                       + "a tab-delimited text file?")
            break

        # Process this line.

        loc_code = parts[0]
        field    = parts[1].lower()

        if len(parts) >= 3:
            value = parts[2]
        else:
            value = ""

        if cur_loc == None or loc_code != cur_loc.code:
            # We're starting a new location.
            if cur_loc != None:
                # Save the previous location to disk.
                cur_loc.save()
                if is_new:
                    log.append("Added location " + cur_loc.code)
                else:
                    log.append("Updated location " + cur_loc.code)

            # Load the new location into memory.

            try:
                cur_loc = Location.objects.get(code=loc_code)
                is_new  = False
            except Location.DoesNotExist:
                cur_loc = Location() # Create a new location.
                cur_loc.code = loc_code
                is_new  = True

        # Import the field specified by this line in the import field.

        if field == "level":

            try:
                level = Level.objects.get(level=int(value))
            except:
                level = None

            if level != None:
                cur_loc.level = level

        elif field == "full_name":

            cur_loc.name = value

        elif field == "display_name":

            cur_loc.display_name = value

        elif field == "min_zoom_lat":

            try:
                cur_loc.min_zoom_lat = decimal.Decimal(value)
            except:
                log.append("Invalid min_zoom_lat value '" + value +
                           "' for location " + loc_code)

        elif field == "min_zoom_long":

            try:
                cur_loc.min_zoom_long = decimal.Decimal(value)
            except:
                log.append("Invalid min_zoom_long value '" + value +
                           "' for location " + loc_code)

        elif field == "max_zoom_lat":

            try:
                cur_loc.max_zoom_lat = decimal.Decimal(value)
            except:
                log.append("Invalid max_zoom_lat value '" + value +
                           "' for location " + loc_code)

        elif field == "max_zoom_long":

            try:
                cur_loc.max_zoom_long = decimal.Decimal(value)
            except:
                log.append("Invalid max_zoom_long value '" + value +
                           "' for location " + loc_code)

        elif field == "population":

            try:
                cur_loc.population = int(value)
            except:
                log.append("Invalid population value '" + value +
                           "' for location " + loc_code)

        elif field == "area":

            try:
                cur_loc.area = int(value)
            except:
                log.append("Invalid area value '" + value +
                           "' for location " + loc_code)

        elif field == "income":

            try:
                cur_loc.averageIncome = decimal.Decimal(value)
            except:
                log.append("Invalid income value '" + value +
                           "' for location " + loc_code)

        elif field == "parents":

            parents = []
            ok      = True # initially.
            for parent_code in parts[2:]:
                try:
                    parent = Location.objects.get(code=parent_code)
                except Location.DoesNotExist:
                    log.append("Invalid parent location code: " + parent_code)
                    ok = False
                    break
                parents.append(parent)

            if ok:
                cur_loc.parents.clear()
                cur_loc.parents.add(*parents)

        elif field == "children":

            children = []
            ok       = True # initially.
            for child_code in parts[2:]:
                try:
                    child = Location.objects.get(code=child_code)
                except Location.DoesNotExist:
                    log.append("Invalid child location code: " + child_code)
                    ok = False
                    break
                children.append(child)

            if ok:
                cur_loc.children.clear()
                cur_loc.children.add(*children)

        elif field == "neighbors":

            neighbours = []
            ok         = True # initially.
            for neighbour_code in parts[2:]:
                try:
                    neighbour = Location.objects.get(code=neighbour_code)
                except Location.DoesNotExist:
                    log.append("Invalid neighbour location code: " +
                               neighbour_code)
                    ok = False
                    break
                neighbours.append(neighbour)

            if ok:
                cur_loc.neighbors.clear()
                cur_loc.neighbors.add(*neighbours)

        elif field == "outline":

            wkt = "".join(parts[2:])

            try:
                outline = Outline.objects.get(location=cur_loc)
            except Outline.DoesNotExist:
                if is_new:
                    # We have to save the current location before our outline
                    # can refer to it.
                    cur_loc.save()
                outline = Outline()
                outline.location = cur_loc

            outline.outline = wkt
            outline.save()

        elif field == "name" or field == "addname":

            filter = {}
            ok     = True # initially.
            for filter_src in parts[3:]:
                if "=" not in filter_src:
                    log.append("Invalid name filter: '" + filter_src + "'")
                    ok = False
                    break

                key,value = filter_src.split("=", 1)
                key = key.strip().lower()
                value = value.strip()
                if key not in ["source", "country", "state",
                               "metro", "region", "county", "city"]:
                    log.append("Invalid name filter: '" + filter_src + "'")
                    ok = False
                    break

                try:
                    filter_loc = Location.objects.get(code=value)
                except Location.DoesNotExist:
                    log.append("The filter '" + filter_src + " refers to " + \
                               "a non-existent location.")
                    ok = False
                    break

                filter[key] = filter_loc

            if ok:
                # If this is the first time we've received a name for this
                # location, and we aren't adding to the list of names, erase
                # the existing names (if any).
                if field == "name":
                    if loc_code not in locs_with_names and not is_new:
                        for loc_name in LocationName.objects.filter(
                                                            location=cur_loc):
                            name = loc_name.name
                            loc_name.delete()

                            if name.locationname_set.count() == 0:
                                # We've removed the last occurrence of this
                                # name -> delete the name as well.
                                name.delete()

                    # Remember that we've got a name for this location.

                    locs_with_names.add(loc_code)

                # Create a new LocationName record for this name.

                if is_new:
                    # We have to save the current location before our
                    # LocationName object can refer to it.
                    cur_loc.save()

                try:
                    name = Name.objects.get(level=cur_loc.level,
                                            name=parts[2])
                except Name.DoesNotExist:
                    name = Name()
                    name.level = cur_loc.level
                    name.name  = parts[2]
                    name.save()

                loc_name = LocationName()
                loc_name.name     = name
                loc_name.location = cur_loc

                for field,filter_loc in filter.items():
                    if field == "source":
                        loc_name.sourceFilter = filter_loc
                    elif field == "country":
                        loc_name.countryFilter = filter_loc
                    elif field == "state":
                        loc_name.stateFilter = filter_loc
                    elif field == "metro":
                        loc_name.metroFilter = filter_loc
                    elif field == "region":
                        loc_name.regionFilter = filter_loc
                    elif field == "county":
                        loc_name.countyFilter = filter_loc
                    elif field == "city":
                        loc_name.cityFilter = filter_loc

                loc_name.save()

        elif field == "delete":

            log.append("Deleting locations is not supported yet.")

        else:

            log.append("Invalid field for location " + loc_code +
                       ": '" + field + "'")

    f.close()

    if cur_loc != None:
        # Save the last location to disk.
        cur_loc.save()
        if is_new:
            log.append("Added location " + cur_loc.code)
        else:
            log.append("Updated location " + cur_loc.code)