def test_raises_InvalidGeoJson_when_geometry_is_linestring(self):

        # arrange
        grid_json = get_canned_json("CHAI-Escuintla-West2.json")
        grid_dto = GridDTO(grid_json)
        grid_dto.clip_to_aoi = True

        # Act / Assert
        with self.assertRaises(InvalidGeoJson):
            GridService.merge_to_multi_polygon(grid_dto.area_of_interest, dissolve=True)
    def test_cant_create_aoi_with_invalid_multipolygon(self):
        bad_multipolygon = geojson.MultiPolygon([[(2.38, 57.322),
                                                  (23.194, -20.28),
                                                  (-120.43, 19.15), (2.38)]])
        bad_feature = geojson.Feature(geometry=bad_multipolygon)
        bad_feature_collection = geojson.FeatureCollection([bad_feature])

        # Act / Assert
        with self.assertRaises(InvalidGeoJson):
            # Only geometries of type MultiPolygon are valid
            GridService.merge_to_multi_polygon(
                geojson.dumps(bad_feature_collection), dissolve=True)
Пример #3
0
    def set_project_aoi(self, draft_project_dto: DraftProjectDTO):
        """ Sets the AOI for the supplied project """
        aoi_geojson = geojson.loads(json.dumps(draft_project_dto.area_of_interest))

        aoi_geometry = GridService.merge_to_multi_polygon(aoi_geojson, dissolve=True)

        valid_geojson = geojson.dumps(aoi_geometry)
        self.geometry = ST_SetSRID(ST_GeomFromGeoJSON(valid_geojson), 4326)
        self.centroid = ST_Centroid(self.geometry)
    def test_tasks_from_aoi_features(self):
        # arrange
        grid_json = get_canned_json("test_arbitrary.json")
        grid_dto = GridDTO(grid_json)
        expected = geojson.loads(
            json.dumps(get_canned_json("tasks_from_aoi_features.json")))

        # act
        result = GridService.tasks_from_aoi_features(grid_dto.area_of_interest)
        # assert
        self.assertEqual(str(expected), str(result))
    def test_feature_collection_multi_polygon_with_zcoord_nodissolve(self):
        # arrange
        project_json = get_canned_json("canned_kml_project.json")
        project_dto = DraftProjectDTO(project_json)
        expected = geojson.loads(json.dumps(get_canned_json("2d_multi_polygon.json")))
        aoi_geojson = geojson.loads(json.dumps(project_dto.area_of_interest))

        # act
        result = GridService.merge_to_multi_polygon(aoi_geojson, dissolve=False)

        # assert
        self.assertEqual(str(expected), str(result))
    def test_feature_collection_to_multi_polygon_nodissolve(self):
        # arrange
        grid_json = get_canned_json("test_grid.json")
        grid_dto = GridDTO(grid_json)
        expected = geojson.loads(json.dumps(get_canned_json("multi_polygon.json")))
        aoi_geojson = geojson.loads(json.dumps(grid_dto.area_of_interest))

        # act
        result = GridService.merge_to_multi_polygon(aoi_geojson, False)

        # assert
        self.assertEqual(str(expected), str(result))
    def create_draft_project(draft_project_dto: DraftProjectDTO) -> int:
        """
        Validates and then persists draft projects in the DB
        :param draft_project_dto: Draft Project DTO with data from API
        :raises InvalidGeoJson
        :returns ID of new draft project
        """
        user_id = draft_project_dto.user_id
        is_admin = UserService.is_user_an_admin(user_id)
        user_orgs = OrganisationService.get_organisations_managed_by_user_as_dto(
            user_id)
        is_org_manager = len(user_orgs.organisations) > 0

        # First things first, we need to validate that the author_id is a PM. issue #1715
        if not (is_admin or is_org_manager):
            user = UserService.get_user_by_id(user_id)
            raise (ProjectAdminServiceError(
                f"User {user.username} is not permitted to create project"))

        # If we're cloning we'll copy all the project details from the clone, otherwise create brand new project
        if draft_project_dto.cloneFromProjectId:
            draft_project = Project.clone(draft_project_dto.cloneFromProjectId,
                                          user_id)
        else:
            draft_project = Project()
            org = OrganisationService.get_organisation_by_id(
                draft_project_dto.organisation)
            if org is None:
                raise NotFound("Organisation does not exist")
            draft_project_dto.organisation = org
            draft_project.create_draft_project(draft_project_dto)

        draft_project.set_project_aoi(draft_project_dto)

        # if arbitrary_tasks requested, create tasks from aoi otherwise use tasks in DTO
        if draft_project_dto.has_arbitrary_tasks:
            tasks = GridService.tasks_from_aoi_features(
                draft_project_dto.area_of_interest)
            draft_project.task_creation_mode = TaskCreationMode.ARBITRARY.value
        else:
            tasks = draft_project_dto.tasks
        ProjectAdminService._attach_tasks_to_project(draft_project, tasks)

        if draft_project_dto.cloneFromProjectId:
            draft_project.save()  # Update the clone
        else:
            draft_project.create()  # Create the new project

        draft_project.set_default_changeset_comment()
        draft_project.set_country_info()
        return draft_project.id
    def test_trim_grid_to_aoi_noclip(self):
        # arrange

        grid_json = get_canned_json("test_grid.json")
        grid_dto = GridDTO(grid_json)
        grid_dto.clip_to_aoi = False

        expected = geojson.loads(json.dumps(get_canned_json("feature_collection.json")))

        # act
        result = GridService.trim_grid_to_aoi(grid_dto)

        # assert
        self.assertEqual(str(expected), str(result))
Пример #9
0
    def post(self):
        """
        Gets the tiles intersecting the aoi
        ---
        tags:
            - grid
        produces:
            - application/json
        parameters:
            - in: header
              name: Authorization
              description: Base64 encoded session token
              required: true
              type: string
              default: Token sessionTokenHere==
            - in: body
              name: body
              required: true
              description: JSON object containing aoi and tasks and bool flag for controlling clip grid to aoi
              schema:
                  properties:
                      clipToAoi:
                        type: boolean
                        default: true
                      areaOfInterest:
                          schema:
                              properties:
                                  type:
                                      type: string
                                      default: FeatureCollection
                                  features:
                                      type: array
                                      items:
                                          schema:
                                              $ref: "#/definitions/GeoJsonFeature"
                      grid:
                          schema:
                              properties:
                                  type:
                                      type: string
                                      default: FeatureCollection
                                  features:
                                      type: array
                                      items:
                                          schema:
                                              $ref: "#/definitions/GeoJsonFeature"
        responses:
            200:
                description: Intersecting tasks found successfully
            400:
                description: Client Error - Invalid Request
            500:
                description: Internal Server Error
        """
        try:
            grid_dto = GridDTO(request.get_json())
            grid_dto.validate()
        except DataError as e:
            current_app.logger.error(f"error validating request: {str(e)}")
            return str(e), 400

        try:
            grid = GridService.trim_grid_to_aoi(grid_dto)
            return grid, 200
        except InvalidGeoJson as e:
            return {"error": f"{str(e)}"}, 400
        except Exception as e:
            error_msg = f"IntersectingTiles GET API - unhandled error: {str(e)}"
            current_app.logger.critical(error_msg)
            return {"error": error_msg}, 500