Skip to content

Commit

Permalink
Merge pull request #172 from hotosm/enhance/tms_negative_url
Browse files Browse the repository at this point in the history
Feature : TMS Support for Local tiles and Tiles with {-y}
  • Loading branch information
kshitijrajsharma authored Oct 5, 2023
2 parents 7ec1f77 + 46801ba commit 9e44525
Show file tree
Hide file tree
Showing 4 changed files with 99 additions and 20 deletions.
34 changes: 22 additions & 12 deletions backend/core/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -122,18 +122,13 @@ def is_dir_empty(directory_path):
def download_image(url, base_path, source_name):
response = requests.get(url)

# Check if the URL request was successful
if response.status_code != 200:
raise ValueError(
f"Failed to download image from {url}. Status code: {response.status_code}"
)

image = response.content

url = re.sub(r"\.(png|jpeg)$", "", url)
url_splitted_list = url.split("/")
pattern = r"/(\d+)/(\d+)/(\d+)(?:\.\w+)?"
match = re.search(pattern, url)
# filename = z-x-y
filename = f"{base_path}/{source_name}-{match.group(2)}-{match.group(3)}-{match.group(1)}.png"

filename = f"{base_path}/{source_name}-{url_splitted_list[-2]}-{url_splitted_list[-1]}-{url_splitted_list[-3]}.png"

with open(filename, "wb") as f:
f.write(image)
Expand Down Expand Up @@ -178,15 +173,30 @@ def download_imagery(start: list, end: list, zm_level, base_path, source="maxar"
# add multiple logic on supported sources here
else:
# source should be url as string , like this : https://tiles.openaerialmap.org/62dbd947d8499800053796ec/0/62dbd947d8499800053796ed/{z}/{x}/{y}
download_url = source.format(
x=download_path[0], y=download_path[1], z=zm_level
)
if "{-y}" in source:
## negative TMS
source_value = source.replace("{-y}", "{y}")
# conversion from normal tms
y_value = int((2**zm_level) - download_path[1] - 1)

else:
# If it doesn't, use the positive y-coordinate
y_value = download_path[1]
source_value = source
download_url = source_value.format(
x=download_path[0], y=y_value, z=zm_level)
download_urls.append(download_url)

start_y = start_y - 1 # decrease the y

start_x = start_x + 1 # increase the x

# Use the ThreadPoolExecutor to download the images in parallel

# with concurrent.futures.ThreadPoolExecutor() as executor:
# for url in download_urls:
# executor.submit(download_image, url, base_path, source_name)

with concurrent.futures.ThreadPoolExecutor() as executor:
futures = [
executor.submit(download_image, url, base_path, source_name)
Expand Down
21 changes: 21 additions & 0 deletions backend/core/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,27 @@ class LabelViewSet(viewsets.ModelViewSet):
)
filterset_fields = ["aoi", "aoi__dataset"]

def create(self, request, *args, **kwargs):
aoi_id = request.data.get("aoi")
geom = request.data.get("geom")

# Check if a label with the same AOI and geometry exists
existing_label = Label.objects.filter(aoi=aoi_id, geom=geom).first()

if existing_label:
# If it exists, update the existing label
serializer = LabelSerializer(existing_label, data=request.data)
else:
# If it doesn't exist, create a new label
serializer = LabelSerializer(data=request.data)

if serializer.is_valid():
serializer.save()
return Response(
serializer.data, status=status.HTTP_200_OK
) # 200 for update, 201 for create
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)


class RawdataApiFeedbackView(APIView):
authentication_classes = [OsmAuthentication]
Expand Down
54 changes: 54 additions & 0 deletions docs/Docker-installation.md
Original file line number Diff line number Diff line change
Expand Up @@ -130,3 +130,57 @@ Docker Compose is created with redis , worker , postgis database , api and fron
```
Frontend will be available on 5000 port , Backend will be on 8000 , Flower will be on 5500
10. Want to run your local tiles ?
You can use [titler](https://github.com/developmentseed/titiler) , [gdals2tiles](https://gdal.org/programs/gdal2tiles.html) or nginx to run your own TMS server and add following to docker compose in order to access your localhost through docker containers . Add those to API and Worker . Make sure you update the .env variable accordingly
```
network_mode: "host"
```
Example docker compose :
```
backend-api:
build:
context: ./backend
dockerfile: Dockerfile_CPU
container_name: api
command: python manage.py runserver 0.0.0.0:8000
ports:
- 8000:8000
volumes:
- ./backend:/app
- ${RAMP_HOME}:/RAMP_HOME
- ${TRAINING_WORKSPACE}:/TRAINING_WORKSPACE
depends_on:
- redis
- postgres
network_mode: "host"
backend-worker:
build:
context: ./backend
dockerfile: Dockerfile_CPU
container_name: worker
command: celery -A aiproject worker --loglevel=INFO --concurrency=1
volumes:
- ./backend:/app
- ${RAMP_HOME}:/RAMP_HOME
- ${TRAINING_WORKSPACE}:/TRAINING_WORKSPACE
depends_on:
- backend-api
- redis
- postgres
network_mode: "host"
```
Example .env after host change :
```
DATABASE_URL=postgis://postgres:admin@localhost:5434/ai
CELERY_BROKER_URL="redis://localhost:6379/0"
CELERY_RESULT_BACKEND="redis://localhost:6379/0"
```
Original file line number Diff line number Diff line change
Expand Up @@ -91,17 +91,11 @@ const DatasetNew = (props) => {
fullWidth
onChange={(e) => {
let trimmedValue = e.target.value.trim();
// let regUrl = /^(https?|chrome):\/\/[^\s$.?#].[^\s]*$/;
// let endsWithPng =
// trimmedValue.endsWith(".png") ||
// trimmedValue.endsWith(".jpeg");
// if (endsWithPng) {
// trimmedValue = trimmedValue.slice(0, -4);
// }
let hasZXY = trimmedValue.includes("{z}/{x}/{y}");
let hasZXYNegative = trimmedValue.includes("{z}/{x}/{-y}");
let isValid =
regUrl.test(trimmedValue) &&
hasZXY &&
(hasZXY || hasZXYNegative) &&
trimmedValue !== "" &&
trimmedValue != null;
setError(!isValid);
Expand Down

0 comments on commit 9e44525

Please sign in to comment.