smoothglue_django_map 0.0.5__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,11 @@
1
+ Copyright 2020–2025, BrainGu LLC. All rights reserved.
2
+
3
+ This software is part of SmoothGlue™, a proprietary product developed by BrainGu LLC.
4
+
5
+ This software is proprietary and confidential. It may not be copied, modified, distributed,
6
+ or used in any form except under a valid commercial license agreement with BrainGu.
7
+
8
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EXPRESS OR IMPLIED,
9
+ INCLUDING BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
10
+
11
+ To inquire about licensing, contact: legal@braingu.com
@@ -0,0 +1,104 @@
1
+ Metadata-Version: 2.3
2
+ Name: smoothglue_django_map
3
+ Version: 0.0.5
4
+ Summary: A Django app to do anything with Django.
5
+ License: Proprietary
6
+ Keywords: Interoperability,API Integration,Edge Computing,Application Framework,Data-Driven Development,Map
7
+ Author: SmoothGlue
8
+ Maintainer: BrainGu
9
+ Maintainer-email: smoothglue@braingu.com
10
+ Requires-Python: >= 3.12
11
+ Classifier: License :: Other/Proprietary License
12
+ Classifier: Programming Language :: Python :: 3
13
+ Classifier: Programming Language :: Python :: 3.12
14
+ Classifier: Programming Language :: Python :: 3.13
15
+ Requires-Dist: django (>=3.2)
16
+ Requires-Dist: smoothglue-django-core (>=1.5.3,<2.0.0)
17
+ Project-URL: Homepage, https://braingu.com/solutions/smoothglue/
18
+ Description-Content-Type: text/markdown
19
+
20
+ # SmoothGlue Django Map App
21
+
22
+ This Django app provides backend api to support front end Map features such as Map Imagery Layers, CZML / GeoJSON python helper classes (coming soon), etc.
23
+
24
+ ## Development
25
+
26
+ ### Set Up Virtual Environment and Install Required Packages
27
+
28
+ This project uses [Poetry](https://python-poetry.org/) for dependency management and packaging.
29
+
30
+ 1. Install Poetry if you haven't already.
31
+ 2. Run `poetry install` to create a virtual environment and install dependencies.
32
+
33
+ ### Running Management Commands With Your App
34
+
35
+ - **smoothglue/map/tests/boot_django.py** to set up a Django environment using Django’s settings.configure() and django.setup() to allow interacting with your app outside of a project.
36
+
37
+ - The settings.configure() call inside this file takes a list of arguments that are equivalent to the variables defined in a settings.py file. Anything you would need in your settings.py to make your app run gets passed into settings.configure().
38
+ - This file is used by the test runner and other scripts to bootstrap the environment.
39
+
40
+ - **djangoshell.py** to spawn a Django shell that’s aware of your app
41
+ - **loaddata.py "some argument"** load fixture data into your app's database and test out
42
+ - **run_test.sh** to run all tests for your app (executes `smoothglue/map/tests/loadtests.py`)
43
+ - **makemigrations.py** to create a migration file
44
+ - **migrate.py** to perform table migrations
45
+
46
+ ## Using App Package (Locally)
47
+
48
+ The steps for using your package locally are:
49
+
50
+ ### Build Your App
51
+
52
+ Run `poetry build` inside the main level of this repo. This creates a directory called `dist` and builds your new package into source and binary formats (e.g., **smoothglue_django_map-<version>.tar.gz** and **smoothglue_django_map-<version>-py3-none-any.whl**).
53
+
54
+ ### Install App Inside a Django Project
55
+
56
+ 1. Before installing the package, make sure that there is a virtual environment set up inside of the Django project you want to install your app into.
57
+
58
+ 2. Then use pip or poetry to install the package:
59
+
60
+ ```bash
61
+ # Using pip
62
+ pip install [path to your newly packaged file]
63
+
64
+ # Using Poetry
65
+ poetry add [path to your newly packaged file]
66
+ ```
67
+
68
+ 3. Update the `settings.py` file inside that Django project to point to the new app name:
69
+
70
+ ```python
71
+ INSTALLED_APPS = [
72
+ "smoothglue.map",
73
+ ...,
74
+ ]
75
+ ```
76
+
77
+ 4. Update the `urls.py` file inside that Django project to point to the new app name: :
78
+
79
+ ```python
80
+ urlpatterns = [
81
+ path("", include("smoothglue.map.urls")),
82
+ ...,
83
+ ]
84
+ ```
85
+
86
+ 5. Run the development server to confirm the project continues to work.
87
+
88
+ [GIF COMING SOON]
89
+
90
+ ## Install App From Gitlab PyPI Package (Official Use)
91
+
92
+ 1. Before installing the package, make sure that there is a virtual environment set up inside of the Django project you want to install the app into.
93
+
94
+ 2. Use pip and the following command inside the Django project:
95
+ ```python
96
+ pip install <app_name> --index-url https://__token__:<your_personal_token>@code.dsop.structsure.io/api/v4/projects/<project_id>/packages/pypi/simple
97
+ ```
98
+
99
+ ## Other File Descriptions
100
+
101
+ - MANIFEST.in - Tells the build process which non common files and folders that should be packaged
102
+ - pyproject.toml - Package and project metadata / configuration
103
+ - tox.ini - Used to configure different types of packages,
104
+
@@ -0,0 +1,84 @@
1
+ # SmoothGlue Django Map App
2
+
3
+ This Django app provides backend api to support front end Map features such as Map Imagery Layers, CZML / GeoJSON python helper classes (coming soon), etc.
4
+
5
+ ## Development
6
+
7
+ ### Set Up Virtual Environment and Install Required Packages
8
+
9
+ This project uses [Poetry](https://python-poetry.org/) for dependency management and packaging.
10
+
11
+ 1. Install Poetry if you haven't already.
12
+ 2. Run `poetry install` to create a virtual environment and install dependencies.
13
+
14
+ ### Running Management Commands With Your App
15
+
16
+ - **smoothglue/map/tests/boot_django.py** to set up a Django environment using Django’s settings.configure() and django.setup() to allow interacting with your app outside of a project.
17
+
18
+ - The settings.configure() call inside this file takes a list of arguments that are equivalent to the variables defined in a settings.py file. Anything you would need in your settings.py to make your app run gets passed into settings.configure().
19
+ - This file is used by the test runner and other scripts to bootstrap the environment.
20
+
21
+ - **djangoshell.py** to spawn a Django shell that’s aware of your app
22
+ - **loaddata.py "some argument"** load fixture data into your app's database and test out
23
+ - **run_test.sh** to run all tests for your app (executes `smoothglue/map/tests/loadtests.py`)
24
+ - **makemigrations.py** to create a migration file
25
+ - **migrate.py** to perform table migrations
26
+
27
+ ## Using App Package (Locally)
28
+
29
+ The steps for using your package locally are:
30
+
31
+ ### Build Your App
32
+
33
+ Run `poetry build` inside the main level of this repo. This creates a directory called `dist` and builds your new package into source and binary formats (e.g., **smoothglue_django_map-<version>.tar.gz** and **smoothglue_django_map-<version>-py3-none-any.whl**).
34
+
35
+ ### Install App Inside a Django Project
36
+
37
+ 1. Before installing the package, make sure that there is a virtual environment set up inside of the Django project you want to install your app into.
38
+
39
+ 2. Then use pip or poetry to install the package:
40
+
41
+ ```bash
42
+ # Using pip
43
+ pip install [path to your newly packaged file]
44
+
45
+ # Using Poetry
46
+ poetry add [path to your newly packaged file]
47
+ ```
48
+
49
+ 3. Update the `settings.py` file inside that Django project to point to the new app name:
50
+
51
+ ```python
52
+ INSTALLED_APPS = [
53
+ "smoothglue.map",
54
+ ...,
55
+ ]
56
+ ```
57
+
58
+ 4. Update the `urls.py` file inside that Django project to point to the new app name: :
59
+
60
+ ```python
61
+ urlpatterns = [
62
+ path("", include("smoothglue.map.urls")),
63
+ ...,
64
+ ]
65
+ ```
66
+
67
+ 5. Run the development server to confirm the project continues to work.
68
+
69
+ [GIF COMING SOON]
70
+
71
+ ## Install App From Gitlab PyPI Package (Official Use)
72
+
73
+ 1. Before installing the package, make sure that there is a virtual environment set up inside of the Django project you want to install the app into.
74
+
75
+ 2. Use pip and the following command inside the Django project:
76
+ ```python
77
+ pip install <app_name> --index-url https://__token__:<your_personal_token>@code.dsop.structsure.io/api/v4/projects/<project_id>/packages/pypi/simple
78
+ ```
79
+
80
+ ## Other File Descriptions
81
+
82
+ - MANIFEST.in - Tells the build process which non common files and folders that should be packaged
83
+ - pyproject.toml - Package and project metadata / configuration
84
+ - tox.ini - Used to configure different types of packages,
@@ -0,0 +1,108 @@
1
+ [tool.poetry]
2
+ name = "smoothglue_django_map"
3
+ version = "0.0.6"
4
+ description = "Enhance your development with SmoothGlue™, Map component for providing backend related map APIs."
5
+ authors = ["BrainGu <smoothglue@braingu.com>"]
6
+ maintainers = ["BrainGu <smoothglue@braingu.com>"]
7
+ license = "Proprietary"
8
+ readme = "README.md"
9
+ homepage = "https://braingu.com/solutions/smoothglue/"
10
+ keywords = [
11
+ "Interoperability",
12
+ "API Integration",
13
+ "Edge Computing",
14
+ "Application Framework",
15
+ "Data-Driven Development",
16
+ "Map"
17
+ ]
18
+ packages = [
19
+ { include = "smoothglue" },
20
+ { include = "smoothglue/map" },
21
+ { include = "smoothglue/map/serializers" },
22
+ { include = "smoothglue/map/migrations" },
23
+ ]
24
+
25
+ [tool.poetry.dependencies]
26
+ python = "^3.12"
27
+
28
+ [tool.poetry.group.dev.dependencies]
29
+ pre-commit = "^3.7.1"
30
+ black = "^24.4.2"
31
+ isort = "^5.13.2"
32
+
33
+ pylint = "^3.2.5"
34
+ pylint-plugin-utils = "^0.8.2"
35
+ pylint-django = "^2.5.5"
36
+ [build-system]
37
+ requires = ["poetry-core"]
38
+ build-backend = "poetry.core.masonry.api"
39
+
40
+ [project]
41
+ name = "smoothglue_django_map"
42
+ version = "0.0.5"
43
+ dependencies = [
44
+ "django>=3.2",
45
+ "smoothglue-django-core (>=1.5.3,<2.0.0)",
46
+ ]
47
+ description = "A Django app to do anything with Django."
48
+ readme = "README.md"
49
+ requires-python = ">= 3.12"
50
+ authors = [
51
+ {name = "SmoothGlue"},
52
+ ]
53
+
54
+ [tool.setuptools]
55
+ packages = ["smoothglue.map", "smoothglue.map.serializers", "smoothglue.map.migrations", "smoothglue.map.fixtures"]
56
+
57
+ [project.urls]
58
+ Homepage = "https://braingu.com/solutions/smoothglue/"
59
+
60
+
61
+ [tool.black]
62
+ exclude = '''
63
+ /(
64
+ | venv
65
+ | migrations
66
+ )/
67
+ '''
68
+
69
+ [tool.pylint.main]
70
+ recursive = true
71
+ fail-under = 10
72
+ max-attributes = 15
73
+ ignore-paths = [
74
+ "^.*migrations\\/.*$",
75
+ "^.*venv\\/.*$"
76
+ ]
77
+ no-docstring-rgx = "(?:^_|^[Tt]est.+|Mock.+)"
78
+ load-plugins = ["pylint_django"]
79
+
80
+ [tool.pylint."messages control"]
81
+ disable = [
82
+ "missing-module-docstring",
83
+ "E5110",
84
+ ]
85
+
86
+ [tool.isort]
87
+ profile = "black"
88
+
89
+ [tool.pylint.design]
90
+ exclude-too-few-public-methods = ["abc.ABC"]
91
+
92
+ [tool.coverage.run]
93
+ include = [
94
+ "smoothglue/*",
95
+ ]
96
+
97
+ [tool.coverage.report]
98
+ exclude_also = [
99
+ "class DefaultUploadProcessor",
100
+ "class DefaultValidator",
101
+ "class TestValidator",
102
+ "class TestPostProcessor",
103
+ # ignore abstract base classes
104
+ "class .+\\((?:abc\\.)?ABC\\)",
105
+ # ignore storage provider initalizers
106
+ "def init_minio_client",
107
+ "def init_s3_client"
108
+ ]
File without changes
File without changes
@@ -0,0 +1,17 @@
1
+ from django.contrib import admin
2
+
3
+ from smoothglue.core.admin import DataAdmin
4
+ from smoothglue.map.models import ImageryLayer
5
+
6
+
7
+ class ImageryLayerAdmin(DataAdmin):
8
+ list_display = (
9
+ "name",
10
+ "provider_type",
11
+ "is_active",
12
+ )
13
+ list_editable = ("is_active",)
14
+ list_filter = ("provider_type",)
15
+
16
+
17
+ admin.site.register(ImageryLayer, ImageryLayerAdmin)
@@ -0,0 +1,7 @@
1
+ from django.apps import AppConfig
2
+
3
+
4
+ class MapConfig(AppConfig):
5
+ default_auto_field = "django.db.models.BigAutoField"
6
+ name = "smoothglue.map"
7
+ verbose_name = "SmoothGlue Map"
@@ -0,0 +1,82 @@
1
+ [
2
+ {
3
+ "model": "map.imagerylayer",
4
+ "pk": "021904c4-68f0-4207-8bee-9efed7ec56fe",
5
+ "fields": {
6
+ "name": "World Physical Map",
7
+ "url": "https://services.arcgisonline.com/arcgis/rest/services/World_Physical_Map/MapServer",
8
+ "provider_type": "AG",
9
+ "sort_order": 8
10
+ }
11
+ },
12
+ {
13
+ "model": "map.imagerylayer",
14
+ "pk": "319836c0-2812-4454-8e26-137f4e80f8de",
15
+ "fields": {
16
+ "name": "NatGeo World Map",
17
+ "url": "https://services.arcgisonline.com/arcgis/rest/services/NatGeo_World_Map/MapServer",
18
+ "provider_type": "AG",
19
+ "sort_order": 7
20
+ }
21
+ },
22
+ {
23
+ "model": "map.imagerylayer",
24
+ "pk": "421d599f-9898-4cac-bcb0-48c9d123a57f",
25
+ "fields": {
26
+ "name": "FAA Sectional",
27
+ "url": "https://tfsgis.tfs.tamu.edu/arcgis/rest/services/Aviation/FAA_Sectional_Charts/MapServer",
28
+ "provider_type": "AG",
29
+ "sort_order": 6
30
+ }
31
+ },
32
+ {
33
+ "model": "map.imagerylayer",
34
+ "pk": "4835b616-f678-442c-a9ba-5b96eecdf405",
35
+ "fields": {
36
+ "name": "World Shaded Relief",
37
+ "url": "https://services.arcgisonline.com/arcgis/rest/services/World_Shaded_Relief/MapServer",
38
+ "provider_type": "AG",
39
+ "sort_order": 5
40
+ }
41
+ },
42
+ {
43
+ "model": "map.imagerylayer",
44
+ "pk": "6667aa56-34b4-43fe-ab33-7da3d038ed6e",
45
+ "fields": {
46
+ "name": "World Street Map",
47
+ "url": "https://services.arcgisonline.com/arcgis/rest/services/World_Street_Map/MapServer",
48
+ "provider_type": "AG",
49
+ "sort_order": 4
50
+ }
51
+ },
52
+ {
53
+ "model": "map.imagerylayer",
54
+ "pk": "89fcdb03-eed9-4b23-a3e7-5fb1ec6ca56d",
55
+ "fields": {
56
+ "name": "World Topo Maps",
57
+ "url": "https://services.arcgisonline.com/arcgis/rest/services/World_Topo_Map/MapServer",
58
+ "provider_type": "AG",
59
+ "sort_order": 3
60
+ }
61
+ },
62
+ {
63
+ "model": "map.imagerylayer",
64
+ "pk": "e4611332-23d9-4a08-96db-b7860ebc4d00",
65
+ "fields": {
66
+ "name": "World Terrain Base",
67
+ "url": "https://services.arcgisonline.com/arcgis/rest/services/World_Terrain_Base/MapServer",
68
+ "provider_type": "NO",
69
+ "sort_order": 2
70
+ }
71
+ },
72
+ {
73
+ "model": "map.imagerylayer",
74
+ "pk": "e6227ca5-9e8a-4793-9e63-d8ffa6e858b7",
75
+ "fields": {
76
+ "name": "World Imagery",
77
+ "url": "https://services.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer",
78
+ "provider_type": "AG",
79
+ "sort_order": 1
80
+ }
81
+ }
82
+ ]
@@ -0,0 +1,51 @@
1
+ # Generated by Django 4.2.13 on 2024-06-18 00:51
2
+
3
+ import uuid
4
+
5
+ from django.db import migrations, models
6
+
7
+
8
+ class Migration(migrations.Migration):
9
+ initial = True
10
+
11
+ dependencies = []
12
+
13
+ operations = [
14
+ migrations.CreateModel(
15
+ name="ImageryLayer",
16
+ fields=[
17
+ (
18
+ "id",
19
+ models.UUIDField(
20
+ default=uuid.uuid4,
21
+ editable=False,
22
+ primary_key=True,
23
+ serialize=False,
24
+ unique=True,
25
+ ),
26
+ ),
27
+ ("name", models.CharField(blank=True, max_length=64, unique=True)),
28
+ ("url", models.CharField(blank=True, max_length=512)),
29
+ (
30
+ "provider_type",
31
+ models.CharField(
32
+ choices=[
33
+ ("NO", "None"),
34
+ ("AG", "ArcGis Map Server"),
35
+ ("TL", "Tile Map Service"),
36
+ ("BG", "Bing Map Imagery"),
37
+ ("GG", "Google Earth Enterprise"),
38
+ ("OS", "Open Street Map"),
39
+ ("WM", "Web Map Tile Service"),
40
+ ("UT", "Url Template Imagery"),
41
+ ("GO", "Geo Server"),
42
+ ],
43
+ default="NO",
44
+ max_length=2,
45
+ ),
46
+ ),
47
+ ("sort_order", models.IntegerField(blank=True, null=True)),
48
+ ("is_active", models.BooleanField(default=True)),
49
+ ],
50
+ ),
51
+ ]
@@ -0,0 +1,32 @@
1
+ import uuid
2
+
3
+ from django.db import models
4
+
5
+
6
+ class ImageryLayer(models.Model):
7
+ class MapImageryProviderType(models.TextChoices):
8
+ NONE = "NO", "None"
9
+ ARCGIS = "AG", "ArcGis Map Server"
10
+ TILE = "TL", "Tile Map Service"
11
+ BING = "BG", "Bing Map Imagery"
12
+ GOOGLE = "GG", "Google Earth Enterprise"
13
+ OPEN = "OS", "Open Street Map"
14
+ WEBMAP = "WM", "Web Map Tile Service"
15
+ URL = "UT", "Url Template Imagery"
16
+ GEO = "GO", "Geo Server"
17
+
18
+ id = models.UUIDField(
19
+ primary_key=True, unique=True, default=uuid.uuid4, editable=False
20
+ )
21
+ name = models.CharField(max_length=64, unique=True, blank=True, null=False)
22
+ url = models.CharField(max_length=512, blank=True, null=False)
23
+ provider_type = models.CharField(
24
+ max_length=2,
25
+ choices=MapImageryProviderType.choices,
26
+ default=MapImageryProviderType.NONE,
27
+ )
28
+ sort_order = models.IntegerField(blank=True, null=True)
29
+ is_active = models.BooleanField(default=True)
30
+
31
+ def __str__(self) -> str:
32
+ return f"{self.name} - {self.provider_type}"
@@ -0,0 +1,15 @@
1
+ from rest_framework import serializers
2
+
3
+ from smoothglue.core.serializers.dynamic import DynamicModelSerializer
4
+ from smoothglue.map.models import ImageryLayer
5
+
6
+
7
+ class ImageryLayerSerializer(DynamicModelSerializer):
8
+
9
+ provider_type = serializers.CharField(
10
+ source="get_provider_type_display", read_only=True
11
+ )
12
+
13
+ class Meta:
14
+ model = ImageryLayer
15
+ fields = ["id", "name", "url", "provider_type", "sort_order", "is_active"]
@@ -0,0 +1,34 @@
1
+ # boot_django.py
2
+ #
3
+ # This file sets up and configures Django. It's used by scripts that need to
4
+ # execute as if running in a Django server.
5
+ import os
6
+
7
+ import django
8
+ from django.conf import settings
9
+
10
+ BASE_DIR = os.path.abspath(os.path.join(os.path.dirname(__file__), "smoothglue/map"))
11
+
12
+
13
+ def boot_django():
14
+ # The settings.configure() call takes a list of args that are equivalent to variables
15
+ # defined in a settings.py file.
16
+ # Anything you would need in your settings.py to make your app run gets passed here
17
+ settings.configure(
18
+ BASE_DIR=BASE_DIR,
19
+ DEBUG=True,
20
+ DATABASES={
21
+ "default": {
22
+ "ENGINE": "django.db.backends.sqlite3",
23
+ "NAME": os.path.join(BASE_DIR, "db.sqlite3"),
24
+ }
25
+ },
26
+ INSTALLED_APPS=[
27
+ "django.contrib.contenttypes",
28
+ "django.contrib.auth",
29
+ "smoothglue.map",
30
+ ],
31
+ TIME_ZONE="UTC",
32
+ USE_TZ=True,
33
+ )
34
+ django.setup()
@@ -0,0 +1,30 @@
1
+ #!/usr/bin/env python
2
+
3
+ import sys
4
+ from unittest import TestSuite
5
+
6
+ from smoothglue.map.tests.boot_django import boot_django
7
+
8
+ boot_django()
9
+
10
+ default_labels = ["smoothglue/map/tests"]
11
+
12
+
13
+ def get_suite(labels=default_labels):
14
+ from django.test.runner import DiscoverRunner
15
+
16
+ runner = DiscoverRunner(verbosity=1)
17
+ failures = runner.run_tests(labels)
18
+ if failures:
19
+ sys.exit(failures)
20
+
21
+ # In case this is called from setuptools, return a test suite
22
+ return TestSuite()
23
+
24
+
25
+ if __name__ == "__main__":
26
+ labels = default_labels
27
+ if len(sys.argv[1:]) > 0:
28
+ labels = sys.argv[1:]
29
+
30
+ get_suite(labels)
@@ -0,0 +1,12 @@
1
+ from django.test import TestCase
2
+
3
+ from smoothglue.map.utils.coordinate_utils import get_decimal_degrees_from_dms_string
4
+
5
+
6
+ class TestCoordinateUtilsSerializer(TestCase):
7
+
8
+ def test_serializer_valid(self):
9
+
10
+ coordinate_str = "373420.50N1272218.92E"
11
+ result = get_decimal_degrees_from_dms_string(coordinate_str)
12
+ self.assertEqual(result, [127.37192222222221, 37.572361111111114])
@@ -0,0 +1,23 @@
1
+ from django.test import TestCase
2
+
3
+ from smoothglue.core.tests.utils import CommonSerializer
4
+ from smoothglue.map.models import ImageryLayer
5
+ from smoothglue.map.serializers.imagery_layer import ImageryLayerSerializer
6
+
7
+
8
+ class TestImageryLayerJsonSerializer(TestCase):
9
+ def setUp(self):
10
+ self.image_layer_data = {
11
+ "name": "test",
12
+ "url": "http://braingu.com",
13
+ "provider_type": "ArcGisMapServerImageryProvider",
14
+ }
15
+
16
+ self.required_fields = []
17
+
18
+ def test_serializer_valid(self):
19
+ CommonSerializer(serializer=ImageryLayerSerializer).test_model_serializer_valid(
20
+ model=ImageryLayer,
21
+ required_fields=self.required_fields,
22
+ data=self.image_layer_data,
23
+ )
@@ -0,0 +1,13 @@
1
+ from django.urls import include, path
2
+ from rest_framework import routers
3
+
4
+ from smoothglue.map import views
5
+
6
+ ROUTER = routers.DefaultRouter()
7
+
8
+ ROUTER.register(
9
+ r"imagelayersviews", views.ImageryLayerViewset, basename="imagelayersviews"
10
+ )
11
+
12
+
13
+ urlpatterns = [path("", include(ROUTER.urls))]
@@ -0,0 +1,70 @@
1
+ import re
2
+
3
+
4
+ def get_decimal_degrees_from_dms_string(dms_string):
5
+ """
6
+ Convert set data representing lat lon as a Degree Minute Second (DMS) value to Decimal Degrees
7
+ using formula: Decimal Degrees = degrees + (minutes/60) + (seconds/3600)
8
+
9
+ ACO coordinate set data comes in 2 varieties:
10
+ LATS (e.g. LATS:431026N1165028W) and LATM (e.g. LATM:4302N11553W)
11
+ Assumptions:
12
+ LATS format is Degrees Minutes Seconds and broken down as follows:
13
+ Index: 0 1 2 3 4 5 6 7
14
+ LATS: 43 10 26 N 116 50 28 W
15
+
16
+ """
17
+ index_dict = {
18
+ "lat_degree_index": 0,
19
+ "lat_minute_index": 1,
20
+ "lat_second_index": 2,
21
+ "lat_millisecond_index": 3,
22
+ "lat_direction_index": 4,
23
+ "lon_degree_index": 5,
24
+ "lon_minute_index": 6,
25
+ "lon_second_index": 7,
26
+ "lon_millisecond_index": 8,
27
+ "lon_direction_index": 9,
28
+ }
29
+
30
+ pattern = r"\s*(\d{2})+(\d{2})+(\d{2})+(\.\d{2})+([N|S])*(\d{3})+(\d{2})+(\d{2})+(\.\d{2})+([E|W])"
31
+
32
+ try:
33
+ lat_lon_set = re.findall(pattern, dms_string)[0]
34
+ except IndexError as exc:
35
+ raise ValueError(
36
+ f"There was an error parsing coordinate: {dms_string}."
37
+ ) from exc
38
+
39
+ lat_decimal = (
40
+ int(lat_lon_set[index_dict["lat_degree_index"]])
41
+ + int(lat_lon_set[index_dict["lat_minute_index"]]) / 60
42
+ )
43
+ lon_decimal = (
44
+ int(lat_lon_set[index_dict["lon_degree_index"]])
45
+ + int(lat_lon_set[index_dict["lon_minute_index"]]) / 60
46
+ )
47
+
48
+ lat_decimal += (
49
+ float(
50
+ lat_lon_set[index_dict["lat_second_index"]]
51
+ + lat_lon_set[index_dict["lat_millisecond_index"]]
52
+ )
53
+ / 3600
54
+ )
55
+ lon_decimal += (
56
+ float(
57
+ lat_lon_set[index_dict["lon_second_index"]]
58
+ + lat_lon_set[index_dict["lon_millisecond_index"]]
59
+ )
60
+ / 3600
61
+ )
62
+
63
+ if (
64
+ lat_lon_set[index_dict["lon_direction_index"]] == "S"
65
+ or lat_lon_set[index_dict["lon_direction_index"]] == "W"
66
+ ):
67
+ lon_decimal *= -1
68
+
69
+ # GeoJSON coordinates are in (lon, lat) format
70
+ return [lon_decimal, lat_decimal]
@@ -0,0 +1,11 @@
1
+ from django_filters.rest_framework import DjangoFilterBackend
2
+
3
+ from smoothglue.core.views import ListModelViewSet
4
+ from smoothglue.map.models import ImageryLayer
5
+ from smoothglue.map.serializers.imagery_layer import ImageryLayerSerializer
6
+
7
+
8
+ class ImageryLayerViewset(ListModelViewSet):
9
+ filter_backends = [DjangoFilterBackend]
10
+ queryset = ImageryLayer.objects.filter(is_active=True).order_by("sort_order")
11
+ serializer_class = ImageryLayerSerializer