diff options
-rw-r--r-- | archaeological_context_records/models.py | 10 | ||||
-rw-r--r-- | archaeological_finds/urls.py | 13 | ||||
-rw-r--r-- | archaeological_finds/views.py | 16 | ||||
-rw-r--r-- | archaeological_operations/models.py | 20 | ||||
-rw-r--r-- | ishtar_common/models_common.py | 101 | ||||
-rw-r--r-- | ishtar_common/static/js/ishtar-map.js | 169 | ||||
-rw-r--r-- | ishtar_common/templates/ishtar/blocks/sheet_map.html | 98 | ||||
-rw-r--r-- | ishtar_common/tests.py | 483 | ||||
-rw-r--r-- | ishtar_common/utils.py | 4 |
9 files changed, 241 insertions, 673 deletions
diff --git a/archaeological_context_records/models.py b/archaeological_context_records/models.py index f0a277678..12d203a7c 100644 --- a/archaeological_context_records/models.py +++ b/archaeological_context_records/models.py @@ -959,21 +959,21 @@ class ContextRecord( return precise_poly return self.operation.get_precise_polygons() - def get_geo_items(self, get_polygons, rounded=True): - dict = super(ContextRecord, self).get_geo_items(get_polygons, rounded) + def get_geo_items(self, rounded=True): + dct = super(ContextRecord, self).get_geo_items(rounded=rounded) BaseFind = apps.get_model("archaeological_finds", "BaseFind") collection_base_finds = [] for bf in self.base_finds.distinct().all(): try: - geo_item = bf.get_geo_items(get_polygons, rounded) + geo_item = bf.get_geo_items(rounded=rounded) collection_base_finds.append(geo_item) except BaseFind.DoesNotExist: pass - dict["properties"]["base-finds"] = { + dct["properties"]["base-finds"] = { "type": "FeatureCollection", "features": collection_base_finds, } - return dict + return dct @classmethod def cached_label_bulk_update( diff --git a/archaeological_finds/urls.py b/archaeological_finds/urls.py index 4bb771359..5e90afd55 100644 --- a/archaeological_finds/urls.py +++ b/archaeological_finds/urls.py @@ -604,20 +604,11 @@ urlpatterns = [ r"api/public/find/$", views_api.PublicFindAPI.as_view(), name="api-public-find" ), url( - r"api/ishtar/base-finds/geo/polygons$", + r"api/ishtar/base-finds/get-geo$", check_rights(["view_find", "view_own_find"])( views.get_geo_items, ), - name="api-get-geo-polygons", - kwargs={"get_polygons": True}, - ), - url( - r"api/ishtar/base-finds/geo/points$", - check_rights(["view_find", "view_own_find"])( - views.get_geo_items, - ), - name="api-get-geo-points", - kwargs={"get_polygons": False}, + name="api-get-geo", ), url( r"api/facets/find/$", views_api.FacetFindAPIView.as_view(), diff --git a/archaeological_finds/views.py b/archaeological_finds/views.py index d643c81b7..514c0650a 100644 --- a/archaeological_finds/views.py +++ b/archaeological_finds/views.py @@ -1325,24 +1325,24 @@ class QAFindLockView(QABaseLockView): base_url = "find-qa-lock" -def get_geo_items(request, get_polygons, current_right=None): - operation_pk = request.GET.get("operation_pk") - context_record_pk = request.GET.get("context_record_pk") +def get_geo_items(request, current_right=None): + operation_pk = request.GET.get("operation_id") + context_record_pk = request.GET.get("context_record_id") pk = request.GET.get("pk") if operation_pk: try: - bf = Operation.objects.get(pk=operation_pk) + item = Operation.objects.get(pk=operation_pk) except Operation.DoesNotExist: raise Http404() elif context_record_pk: try: - bf = ContextRecord.objects.get(pk=context_record_pk) + item = ContextRecord.objects.get(pk=context_record_pk) except ContextRecord.DoesNotExist: raise Http404() else: try: - bf = models.BaseFind.objects.get(pk=pk) + item = models.BaseFind.objects.get(pk=pk) except models.BaseFind.DoesNotExist: raise Http404() - dic = bf.get_geo_items(get_polygons=get_polygons) - return HttpResponse(json.dumps(dic).encode("utf-8")) + geo = item.get_geo_items() + return HttpResponse(json.dumps(geo).encode("utf-8")) diff --git a/archaeological_operations/models.py b/archaeological_operations/models.py index bb41848a5..080ddddab 100644 --- a/archaeological_operations/models.py +++ b/archaeological_operations/models.py @@ -1728,23 +1728,33 @@ class Operation( return None return q.all()[0].poly, self._meta.verbose_name - def get_geo_items(self, get_polygons, rounded=True): - dict = super(Operation, self).get_geo_items(get_polygons, rounded) + def get_geo_items(self, rounded=True): + dct = super(Operation, self).get_geo_items(rounded=rounded) ContextRecord = apps.get_model( "archaeological_context_records", "ContextRecord" ) collection_context_records = [] + import datetime + n = datetime.datetime.now() + n1 = datetime.datetime.now() + times = [] + print("archaeological_operations.models.py", "get_geo_items", 1741) for cr in self.context_record.distinct().all(): try: - geo_item = cr.get_geo_items(get_polygons, rounded) + geo_item = cr.get_geo_items(rounded=rounded) collection_context_records.append(geo_item) + times.append((datetime.datetime.now() - n1).seconds) + n1 = datetime.datetime.now() except ContextRecord.DoesNotExist: pass - dict["properties"]["context-records"] = { + print("full", datetime.datetime.now() - n) + if times: + print("mean", sum(times)/len(times)) + dct["context-records"] = { "type": "FeatureCollection", "features": collection_context_records, } - return dict + return dct def context_record_relations_q(self): from archaeological_context_records.models import RecordRelations as CRRL diff --git a/ishtar_common/models_common.py b/ishtar_common/models_common.py index 83897768c..5d3cdbec2 100644 --- a/ishtar_common/models_common.py +++ b/ishtar_common/models_common.py @@ -48,6 +48,7 @@ from ishtar_common.utils import ( pgettext_lazy, get_image_path, human_date, + reverse_list_coordinates ) from simple_history.models import HistoricalRecords as BaseHistoricalRecords from simple_history.signals import ( @@ -2358,34 +2359,53 @@ class GeoVectorData(Imported, OwnPerms): profile = get_current_profile() return profile.srs - def get_geo_items(self, get_polygons, rounded=5): - label = self.label if hasattr(self, "label") else self.short_label - dct = {"type": "Feature", "geometry": {}, "properties": {"label": label}} - if get_polygons: + def get_geo_items(self, rounded=5): + dct = {"type": "Feature", "geometry": {}, "properties": {"label": str(self)}} + if self.multi_polygon: list_coords = [] - if self.multi_polygon: - for polygon in self.multi_polygon: - list_coords.append([]) - for linear_ring in range(len(polygon)): - list_coords[-1].append([]) - for coords in polygon[linear_ring].coords: - point_2d = Point( - coords[0], coords[1], srid=self.multi_polygon.srid - ) - list_coords[-1][linear_ring].append( - self.convert_coordinates(point_2d, rounded) - ) + for polygon in self.multi_polygon: + list_coords.append([]) + for linear_ring in range(len(polygon)): + list_coords[-1].append([]) + for coords in polygon[linear_ring].coords: + point_2d = Point( + coords[0], coords[1], srid=self.multi_polygon.srid + ) + list_coords[-1][linear_ring].append( + self.convert_coordinates(point_2d, rounded) + ) dct["geometry"]["type"] = "MultiPolygon" dct["geometry"]["coordinates"] = list_coords + elif self.multi_points: + list_coords = [] + for coords in self.multi_points: + point_2d = Point( + coords.x, coords.y, srid=self.multi_points.srid + ) + list_coords.append( + self.convert_coordinates(point_2d, rounded) + ) + dct["geometry"]["type"] = "MultiPoint" + dct["geometry"]["coordinates"] = list_coords + elif self.multi_line: + list_coords = [] + for idx, line in enumerate(self.multi_line): + if not idx: + list_coords.append([]) + for coords in line: + point_2d = Point( + coords.x, coords.y, srid=self.multi_points.srid + ) + list_coords[-1].append( + self.convert_coordinates(point_2d, rounded) + ) + dct["geometry"]["type"] = "MultiLine" + dct["geometry"]["coordinates"] = list_coords else: dct["geometry"]["type"] = "Point" - coords = self.display_coordinates() + coords = self.display_coordinates(srid=4326) if coords: dct["geometry"]["coordinates"] = coords - elif self.multi_polygon: - dct["geometry"]["coordinates"] = self.convert_coordinates( - self.multi_polygon.centroid, rounded - ) else: return {} return dct @@ -3537,41 +3557,10 @@ class GeoItem(GeographicItem): if self.multi_polygon_source == "P" and self.multi_polygon: return self.multi_polygon, self.multi_polygon_source_item - def get_geo_items(self, get_polygons, rounded=True): - try: - label = self.label - except: - label = self.short_label - dict = {"type": "Feature", "geometry": {}, "properties": {"label": label}} - if get_polygons: - list_coords = [] - if self.multi_polygon: - for polygon in self.multi_polygon: - list_coords.append([]) - for linear_ring in range(len(polygon)): - list_coords[-1].append([]) - for coords in polygon[linear_ring].coords: - point_2d = Point( - coords[0], coords[1], srid=self.multi_polygon.srid - ) - list_coords[-1][linear_ring].append( - self.convert_coordinates(point_2d, rounded) - ) - dict["geometry"]["type"] = "MultiPolygon" - dict["geometry"]["coordinates"] = list_coords - else: - dict["geometry"]["type"] = "Point" - if self.point_2d: - try: - x, y = self.display_coordinates - dict["geometry"]["coordinates"] = [x, y] - except ValueError: - dict["geometry"]["coordinates"] = [] - else: - dict["geometry"]["coordinates"] = self.convert_coordinates( - self.multi_polygon.centroid, rounded - ) - return dict + def get_geo_items(self, rounded=5): + if not self.main_geodata: + return {} + return self.main_geodata.get_geo_items(rounded) def convert_coordinates(self, point_2d, rounded): profile = get_current_profile() diff --git a/ishtar_common/static/js/ishtar-map.js b/ishtar_common/static/js/ishtar-map.js index 95f8ad3e3..a0709c059 100644 --- a/ishtar_common/static/js/ishtar-map.js +++ b/ishtar_common/static/js/ishtar-map.js @@ -32,7 +32,7 @@ var fetching_msg = "Fetching data..."; var base_maps_msg = "Base maps"; var _map_submit_search = function(query_vars, name, source, extra){ - if (!extra) extra = "default"; + if (!extra) extra = "default"; var modal_base_text = $('.modal-progress .modal-header').html(); $('.modal-progress .modal-header').html(fetching_msg); $('.modal-progress').modal('show'); @@ -175,7 +175,7 @@ var TrackPositionControl = (function (Control) { /* base layers */ var source_osm = function(options){ - options["source"] = new ol.source.OSM(); + options["source"] = new ol.source.OSM(); return new ol.layer.Tile(options); }; @@ -207,19 +207,19 @@ var ign_resolutions = [ var ign_key = "essentiels"; var source_ign = function(options){ - options["source"] = new ol.source.WMTS({ - url: "https://wxs.ign.fr/" + ign_key + "/geoportail/wmts", - layer: "ORTHOIMAGERY.ORTHOPHOTOS", - matrixSet: "PM", - format: "image/jpeg", - style: "normal", - tileGrid : new ol.tilegrid.WMTS({ - origin: [-20037508,20037508], // topLeftCorner - resolutions: ign_resolutions, // résolutions - matrixIds: ["0","1","2","3","4","5","6","7","8","9","10","11","12","13","14","15","16","17","18","19"] // ids des TileMatrix - }) - }); - return new ol.layer.Tile(options); + options["source"] = new ol.source.WMTS({ + url: "https://wxs.ign.fr/" + ign_key + "/geoportail/wmts", + layer: "ORTHOIMAGERY.ORTHOPHOTOS", + matrixSet: "PM", + format: "image/jpeg", + style: "normal", + tileGrid : new ol.tilegrid.WMTS({ + origin: [-20037508,20037508], // topLeftCorner + resolutions: ign_resolutions, // résolutions + matrixIds: ["0","1","2","3","4","5","6","7","8","9","10","11","12","13","14","15","16","17","18","19"] // ids des TileMatrix + }) + }); + return new ol.layer.Tile(options); } var default_map_layers = { @@ -230,14 +230,14 @@ var default_map_layers = { var get_layers = function(layers){ if (!layers){ layers = [ - { - 'type': 'ign', - 'options': {'title': "IGN aérien (France)", 'visible': false, "type": 'base'} - }, - { - 'type': 'osm', - 'options': {'title': "OpenStreetMap", 'visible': true, "type": 'base'} - } + { + 'type': 'ign', + 'options': {'title': "IGN aérien (France)", 'visible': false, "type": 'base'} + }, + { + 'type': 'osm', + 'options': {'title': "OpenStreetMap", 'visible': true, "type": 'base'} + } ]; } var ol_layers = []; @@ -627,12 +627,12 @@ var initialize_base_map = function(map_id, layers){ center = wkt_format.readGeometry(map_default_center).getCoordinates(); map_layers[map_id] = [ - new ol.layer.Group({ - title: base_maps_msg, - visible: true, - layers: get_layers(layers) - }) - ]; + new ol.layer.Group({ + title: base_maps_msg, + visible: true, + layers: get_layers(layers) + }) + ]; map_view[map_id] = new ol.View({ projection: view_projection, @@ -661,14 +661,14 @@ var initialize_base_map = function(map_id, layers){ view: map_view[map_id] }); var layer_switcher = new ol.control.LayerSwitcher({ - tipLabel: 'Légende', - groupSelectStyle: 'children' - }); - map[map_id].addControl(layer_switcher); + tipLabel: 'Légende', + groupSelectStyle: 'children' + }); + map[map_id].addControl(layer_switcher); } var redraw_map = function(map_id, layers){ - if (!map || !map[map_id]) return; + if (!map || !map[map_id]) return; map[map_id].setTarget(null); map[map_id] = null; initialize_base_map(map_id, layers); @@ -705,7 +705,6 @@ var display_map = function(map_id, points, lines_and_polys, layers){ var display_points = function(map_id, points, first_init){ if (!points) return; point_features[map_id] = geojson_format.readFeatures(points); - console.log(708); if (!cluster_source[map_id]){ enable_clustering(map_id); } else { @@ -736,7 +735,6 @@ var display_lines_and_polys = function(map_id, lines_and_polys, first_init){ style: get_vector_style }); - console.log(738); map[map_id].addLayer(vector_layer[map_id]); if (first_init && lines_and_polys.features && lines_and_polys.features.length){ map_view[map_id].fit(vector_source[map_id].getExtent()); @@ -896,3 +894,102 @@ var base_features_type = function (id) { } else { return 'Point and MultiPolygon' } } + +var _geo_points = new Array(); +var _geo_other = new Array(); + +var _point_list_crs = new Array(); +var _other_list_crs = new Array(); +var _point_list_finds = new Array(); +var _other_list_finds = new Array(); + +const _refresh_map_crs = function(idx) { + if (idx in _geo_points && idx in _point_list_crs){ + for (const feat of _point_list_crs[idx]){ + _geo_points[idx]["features"].push(feat); + } + } + if (idx in _geo_other && idx in _other_list_crs){ + for (const feat of _other_list_crs[idx]){ + _geo_other[idx]["features"].push(feat); + } + } +} +const _refresh_map_finds = function(idx) { + if (idx in _geo_points && idx in _point_list_finds){ + for (const feat of _point_list_finds[idx]){ + _geo_points[idx]["features"].push(feat); + } + } + if (idx in _geo_other && idx in _other_list_finds){ + for (const feat of _other_list_finds[idx]){ + _geo_other[idx]["features"].push(feat); + } + } +} + +const refresh_map_finds_crs = function(url, attrs, idx, crs_check, find_check) { + if (idx in _point_list_finds){ + if (crs_check) _refresh_map_crs(idx); + if (find_check) _refresh_map_finds(idx); + return; + } + _point_list_crs[idx] = new Array(); + _other_list_crs[idx] = new Array(); + _point_list_finds[idx] = new Array(); + _other_list_finds[idx] = new Array(); + $.get(url, attrs).done( + function(data) { + data = JSON.parse(data); + if (data) { + if (data["context-records"] && data["context-records"]["features"]) { + for (let feat of data["context-records"]["features"]){ + if (feat["geometry"]["type"] === 'Point' || + feat["geometry"]["type"] === 'MultiPoint'){ + _point_list_crs[idx].push(feat); + } else { + _other_list_crs[idx].push(feat); + } + } + if (crs_check) _refresh_map_crs(idx); + } + if (data["finds"] && data["finds"]["features"]) { + for (let feat of data["finds"]["features"]){ + if (feat["geometry"]["type"] === 'Point' || + feat["geometry"]["type"] === 'MultiPoint'){ + _point_list_finds[idx].push(feat); + } else { + _other_list_finds[idx].push(feat); + } + } + if (finds_check) _refresh_map_finds(idx); + } + } + } + ); +} + + +const refresh_map = function(idx, geodata_list, url, attrs) { + _geo_points[idx] = {"type": "FeatureCollection", "features": []}; + _geo_other[idx] = {"type": "FeatureCollection", "features": []}; + for (const key in geodata_list){ + if ($("#map-ol-" + key).prop('checked')){ + let geo_type = geodata_list[key][0]; + let geojson = geodata_list[key][1]; + if (geo_type === 'POINT'){ + Array.prototype.push.apply( + _geo_points[idx]["features"], geojson["features"]); + } else { + Array.prototype.push.apply( + _geo_other[idx]["features"], geojson["features"]); + } + } + } + if (url && attrs){ + let find_check = $("#map-ol-" + idx + "-finds").prop('checked'); + let crs_check = $("#map-ol-" + idx + "-crs").prop('checked'); + refresh_map_finds_crs(url, attrs, idx, crs_check, find_check); + } +} + diff --git a/ishtar_common/templates/ishtar/blocks/sheet_map.html b/ishtar_common/templates/ishtar/blocks/sheet_map.html index 16e014b49..11780ae8a 100644 --- a/ishtar_common/templates/ishtar/blocks/sheet_map.html +++ b/ishtar_common/templates/ishtar/blocks/sheet_map.html @@ -10,6 +10,7 @@ <ul>{% for geodata in geodata_list %} <li> <input type="checkbox" name="map-ol-{{item.SLUG}}-{{item.pk}}-{{geodata.pk}}" + class="map-ol-{{item.SLUG}}-{{item.pk}}" id="map-ol-{{item.SLUG}}-{{item.pk}}-{{geodata.pk}}" {% if not forloop.counter0 %}checked{% endif %} > @@ -17,95 +18,54 @@ <strong>{{geodata.data_type}}</strong></label><br/> {{geodata.name}} </li>{% endfor %} + {% if geo_item.SLUG == "operation" %} + <li> + <input type="checkbox" name="map-ol-{{item.SLUG}}-{{item.pk}}-crs" + class="map-ol-{{item.SLUG}}-{{item.pk}}" + id="map-ol-{{item.SLUG}}-{{item.pk}}-crs"> + <label for="map-ol-{{item.SLUG}}-{{item.pk}}-crs"> + <strong>{% trans "Associated context records" %}</strong></label> + </li> + {% endif %} + {% if geo_item.SLUG == "operation" or geo_item.SLUG == "contextrecord" %} + <li> + <input type="checkbox" name="map-ol-{{item.SLUG}}-{{item.pk}}-finds" + class="map-ol-{{item.SLUG}}-{{item.pk}}" + id="map-ol-{{item.SLUG}}-{{item.pk}}-finds"> + <label for="map-ol-{{item.SLUG}}-{{item.pk}}-finds"> + <strong>{% trans "Associated finds" %}</strong></label> + </li> + {% endif %} </ul> </div> <script type="text/javascript"> - const refresh_map_{{item.SLUG}}_{{item.pk}} = function(first_init) { - var {{geo_item.SLUG}}{{geo_item.pk}}_point = {"type": "FeatureCollection", "features": []}; - var {{geo_item.SLUG}}{{geo_item.pk}}_other = {"type": "FeatureCollection", "features": []}; - {% for geodata in geodata_list %} - if ($("#map-ol-{{item.SLUG}}-{{item.pk}}-{{geodata.pk}}").prop('checked')){ - let geojson = {{geodata.geojson|safe}}; - {% if geodata.geometry_type == 'POINT' %} - Array.prototype.push.apply({{geo_item.SLUG}}{{geo_item.pk}}_point["features"], - geojson["features"]); - {% else %} - Array.prototype.push.apply({{geo_item.SLUG}}{{geo_item.pk}}_other["features"], - geojson["features"]); - {% endif %} - }{% endfor %} - display_lines_and_polys("map-{{window_id}}-{{geo_item.SLUG}}-{{geo_item.pk}}", {{geo_item.SLUG}}{{geo_item.pk}}_other, first_init); - display_points("map-{{window_id}}-{{geo_item.SLUG}}-{{geo_item.pk}}", {{geo_item.SLUG}}{{geo_item.pk}}_point, first_init); + let idx = "{{item.SLUG}}-{{item.pk}}"; + let geodata_list = { {% for geodata in geodata_list %} + "{{item.SLUG}}-{{item.pk}}-{{geodata.pk}}": ["{{geodata.geometry_type}}", {{geodata.geojson|safe}}]{% if not forloop.last %},{% endif %} + {% endfor %} }; + let url{% if geo_item.SLUG == "operation" or geo_item.SLUG == "contextrecord" %} = "{% url 'api-get-geo' %}"{% endif %}; + let attrs{% if geo_item.SLUG == "operation" %} = {"operation_id": "{{geo_item.pk}}"}{% elif geo_item.SLUG == "contextrecord" %} = {"context_record_id": "{{geo_item.pk}}"}{% endif %}; + refresh_map(idx, geodata_list, url, attrs); + display_lines_and_polys("map-{{window_id}}-" + idx, _geo_other[idx], first_init); + display_points("map-{{window_id}}-" + idx, _geo_points[idx], first_init); } const display_map_{{item.SLUG}}_{{item.pk}} = function() { const html = render_map("map-{{window_id}}-{{geo_item.SLUG}}-{{geo_item.pk}}", false, true); $("#map-content-{{window_id}}-{{geo_item.SLUG}}-{{geo_item.pk}}").html(html); display_map("map-{{window_id}}-{{geo_item.SLUG}}-{{geo_item.pk}}", null, null); - {% for geodata in geodata_list %} - $("#map-ol-{{item.SLUG}}-{{item.pk}}-{{geodata.pk}}").change( + $(".map-ol-{{item.SLUG}}-{{item.pk}}").change( function(){ refresh_map_{{item.SLUG}}_{{item.pk}}(false); } ); - {% endfor %} } display_map_{{item.SLUG}}_{{item.pk}}(); refresh_map_{{item.SLUG}}_{{item.pk}}(true); -{% if geo_item.SLUG == "operation" or geo_item.SLUG == "contextrecord" %} -const disp_geo_items = function(disp_cr, disp_bf, get_polygons) { - if (disp_cr || disp_bf) { - const get_poly = (get_polygons === "polygons"); - let url = null; - if (get_poly) { - url = "{% url 'api-get-geo-polygons' %}"; - } - else { - url = "{% url 'api-get-geo-points' %}"; - } - display_geo_items("map-{{window_id}}-{{geo_item.SLUG}}-{{geo_item.pk}}", url, "{{geo_item.SLUG}}", - "{{geo_item.pk}}", disp_cr, disp_bf, get_poly); - } -} -let geo_items_displayed_once = false; -const disp_bf = $("#disp-bf-for-{{geo_item.SLUG}}-{{geo_item.pk}}"); -const get_polygons = $("#get-poly-for-{{geo_item.SLUG}}-{{geo_item.pk}}"); - -{% if geo_item.SLUG == "operation" %} -const disp_cr = $("#disp-cr-for-{{geo_item.SLUG}}-{{geo_item.pk}}"); -const event_func_disp_geo_items = function () { - if (geo_items_displayed_once) { - disp_map(); - } - else { geo_items_displayed_once = true; } - disp_geo_items(disp_cr.prop('checked'), disp_bf.prop('checked'), get_polygons.val()); -} -disp_cr.change( event_func_disp_geo_items ); -disp_bf.change( event_func_disp_geo_items ); -get_polygons.change( function () { - disp_map(); - disp_geo_items(disp_cr.prop('checked'), disp_bf.prop('checked'), get_polygons.val()); -}) -{% else %} -const event_func_disp_geo_items = function () { - if (geo_items_displayed_once) { - disp_map(); - } - else { geo_items_displayed_once = true; } - disp_geo_items(false, disp_bf.prop('checked'), get_polygons.val()); -} -disp_bf.change( event_func_disp_geo_items ); -get_polygons.change( function () { - disp_map(); - disp_geo_items(false, disp_bf.prop('checked'), get_polygons.val()); -}) -{% endif %} -{% endif %} - </script> {% endwith %} {% endif %} diff --git a/ishtar_common/tests.py b/ishtar_common/tests.py index dfae6c164..25d4d8e85 100644 --- a/ishtar_common/tests.py +++ b/ishtar_common/tests.py @@ -2839,489 +2839,6 @@ class IshtarBasicTest(TestCase): self.assertEqual(town.cached_label, "Sin City - 99 (2050)") -class GeomaticTest(TestCase): - fixtures = FIND_FIXTURES - - def setUp(self): - profile = models.get_current_profile() - profile.mapping = True - profile.save() - - def test_post_save_point(self): - class FakeGeomaticObject(object): - _meta = models.GeoItem._meta - - def __init__( - self, x, y, z, spatial_reference_system, point=None, point_2d=None - ): - self.x = x - self.y = y - self.z = z - self.spatial_reference_system = spatial_reference_system - self.point_source = "P" - self.point_source_item = "" - self.point = point - self.point_2d = point_2d - self.pk = 42 - - def save(self, *args, **kwargs): - pass - - srs, __ = models.SpatialReferenceSystem.objects.get_or_create( - srid=4326, defaults={"label": "WGS84", "txt_idx": "wgs84"} - ) - obj = FakeGeomaticObject(x=2, y=3, z=4, spatial_reference_system=srs) - self.assertIsNone(obj.point_2d) - post_save_geo(FakeGeomaticObject, instance=obj) - self.assertIsNotNone(obj.point_2d) - self.assertIsNotNone(obj.point) - - @staticmethod - def create_cr_with_bfs(ope, geom_ope, geom_cr, list_geom_bf, label_cr): - Operation = apps.get_model("archaeological_operations", "Operation") - ContextRecord = apps.get_model( - "archaeological_context_records", "ContextRecord" - ) - Find = apps.get_model("archaeological_finds", "Find") - BaseFind = apps.get_model("archaeological_finds", "BaseFind") - - wgs84 = models_common.SpatialReferenceSystem.objects.get(srid=4326) - poly_ope = ( - "MULTIPOLYGON(((1 1,5 1,5 5,1 5,1 1),(2 2,2 3,3 3,3 2,2 2))," - "((6 3,9 2,9 4,6 3)))" - ) - point_ope = GEOSGeometry("POINT({} {} {})".format(3.8, 3, 1), srid=4326) - point_2d_ope = GEOSGeometry("POINT({} {})".format(3.8, 3), srid=4326) - xy_ope = 3.8, 3 - poly_cr = ( - "MULTIPOLYGON(((2 1,5 1,5 5,1 5,2 1),(2 2,2 3,3 3,3 2,2 2))," - "((6 3,9 2,9 4,6 3)))" - ) - point_cr = GEOSGeometry("POINT({} {} {})".format(3.9, 3, 1), srid=4326) - point_2d_cr = GEOSGeometry("POINT({} {})".format(3.9, 3), srid=4326) - xy_cr = 3.9, 3 - poly_bf = ( - "MULTIPOLYGON(((2 1,4 1,4 4,1 4,2 1),(2 2,2 3,3 3,3 2,2 2))," - "((6 3,9 2,9 4,6 3)))" - ) - point_bf = GEOSGeometry("POINT({} {} {})".format(3.9, 2.9, 1), srid=4326) - point_2d_bf = GEOSGeometry("POINT({} {})".format(3.9, 2.9), srid=4326) - xy_bf = 3.9, 2.9 - - pks = {} - - ope.multi_polygon = "SRID=4326;" + poly_ope - ope.multi_polygon_source = "P" - ope.multi_polygon_source_item = str(ope._meta.verbose_name) - ope.spatial_reference_system = wgs84 - if geom_ope == "Point": - ope.point = point_ope - ope.point_source = "P" - ope.point_source_item = str(ope._meta.verbose_name) - ope.x, ope.y = xy_ope - ope.point_2d = point_2d_ope - ope.save() # needs 2 saves because point_2d is none for multi_polygon - ope = Operation.objects.get(pk=ope.pk) - ope.save() - ope = Operation.objects.get(pk=ope.pk) - - default = { - "label": label_cr, - "operation": ope, - } - cr = ContextRecord.objects.create(**default) - cr = ContextRecord.objects.get(pk=cr.pk) - cr.multi_polygon = "SRID=4326;" + poly_cr - cr.multi_polygon_source = "P" - cr.multi_polygon_source_item = str(cr._meta.verbose_name) - cr.spatial_reference_system = wgs84 - if geom_cr == "Point": - cr.point = point_cr - cr.point_source = "P" - cr.point_source_item = str(cr._meta.verbose_name) - cr.x, cr.y = xy_cr - cr.point_2d = point_2d_cr - cr.save() - cr = ContextRecord.objects.get(pk=cr.pk) - pks[label_cr] = cr.pk - - bfs = [] - for bf_geom in list_geom_bf: - default = { - "label": "Find " + bf_geom + " from " + label_cr, - "context_record": cr, - } - bf = BaseFind.objects.create(**default) - bf.multi_polygon = "SRID=4326;" + poly_bf - bf.multi_polygon_source = "P" - bf.multi_polygon_source_item = str(bf._meta.verbose_name) - bf.spatial_reference_system = wgs84 - if bf_geom == "Point": - bf.point = point_bf - bf.point_source = "P" - bf.point_source_item = str(bf._meta.verbose_name) - bf.x, bf.y = xy_bf - bf.point_2d = point_2d_bf - bf.save() - bf = BaseFind.objects.get(pk=bf.pk) - bfs.append(bf) - pks[default["label"]] = bf.pk - - find = Find.objects.create() - find.base_finds.add(bf) - find.save() - return pks - - @staticmethod - def setUpDefaultGeoItems(user): - from archaeological_operations.tests import create_operation - - ope1 = create_operation(user) - ope2 = create_operation(user) - pks = {"Pt": ope1.pk, "Poly": ope2.pk} - - pks.update( - GeomaticTest.create_cr_with_bfs( - ope1, "Point", "Point", ["Polygon", "Point"], "CR Pt Pt" - ) - ) - pks.update( - GeomaticTest.create_cr_with_bfs( - ope1, "Point", "Polygon", ["Polygon", "Point"], "CR Pt Poly" - ) - ) - pks.update( - GeomaticTest.create_cr_with_bfs( - ope2, "Polygon", "Point", ["Polygon", "Point"], "CR Poly Pt" - ) - ) - pks.update( - GeomaticTest.create_cr_with_bfs( - ope2, "Polygon", "Polygon", ["Polygon", "Point"], "CR Poly Poly" - ) - ) - - geom_ope = [ - [ - [ - [[1, 1], [5, 1], [5, 5], [1, 5], [1, 1]], - [[2, 2], [2, 3], [3, 3], [3, 2], [2, 2]], - ], - [[[6, 3], [9, 2], [9, 4], [6, 3]]], - ], - [3.86111, 3.02778], - [3.8, 3], - ] - geom_cr = [ - [ - [ - [[2, 1], [5, 1], [5, 5], [1, 5], [2, 1]], - [[2, 2], [2, 3], [3, 3], [3, 2], [2, 2]], - ], - [[[6, 3], [9, 2], [9, 4], [6, 3]]], - ], - [4.17708, 3.11458], - [3.9, 3], - ] - geom_bf = [ - [ - [ - [[2, 1], [4, 1], [4, 4], [1, 4], [2, 1]], - [[2, 2], [2, 3], [3, 3], [3, 2], [2, 2]], - ], - [[[6, 3], [9, 2], [9, 4], [6, 3]]], - ], - [4.42105, 2.73684], - [3.9, 2.9], - ] - return [geom_ope, geom_cr, geom_bf], pks - - @staticmethod - def pt_coords_from_label(label, geoms): - if label[:2] == "Pt": - return geoms[0][2], True - if label[:4] == "Poly": - return geoms[0][1], False - if label[:2] == "CR": - if label[-2:] == "Pt": - return geoms[1][2], True - if label[3:5] == "Pt": - return geoms[0][2], True - return geoms[1][1], False - if label[5:10] == "Point": - return geoms[2][2], True - # label has shape Find Polygon from CR xxx xxx - if label[-2:] == "Pt": - return geoms[1][2], True - if label[21:23] == "Pt": - return geoms[0][2], True - return geoms[2][1], False - - def assertPt(self, item, geom): - self.assertEqual(item.multi_polygon.coords, geom[0].coords) - self.assertEqual(item.point_2d.coords, geom[2].coords) - - def assertPoly(self, item, geom, real_point=None): - self.assertEqual(item.multi_polygon.coords, geom[0].coords) - if real_point: - self.assertEqual((round(item.x, 5), round(item.y, 5)), real_point.coords) - else: - self.assertEqual((round(item.x, 5), round(item.y, 5)), geom[1].coords) - - def test_setUpDefaultGeoItems(self): - # TODO: remove and clean - Operation = apps.get_model("archaeological_operations", "Operation") - - """ - username, password, user = create_superuser() - base_geoms, pks = self.setUpDefaultGeoItems(user) - geoms = [] - for geom in base_geoms: - poly = GEOSGeometry( - json.dumps({"type": "MultiPolygon", "coordinates": geom[0]}) - ) - centr = GEOSGeometry(json.dumps({"type": "Point", "coordinates": geom[1]})) - pt = GEOSGeometry(json.dumps({"type": "Point", "coordinates": geom[2]})) - geoms.append([poly, centr, pt]) - ope_pt = Operation.objects.get(pk=pks["Pt"]) - self.assertPt(ope_pt, geoms[0]) - ope_poly = Operation.objects.get(pk=pks["Poly"]) - self.assertPoly(ope_poly, geoms[0]) - - cr_poly_poly = ope_poly.context_record.get(pk=pks["CR Poly Poly"]) - self.assertPoly(cr_poly_poly, geoms[1]) - cr_poly_pt = ope_poly.context_record.get(pk=pks["CR Poly Pt"]) - self.assertPt(cr_poly_pt, geoms[1]) - cr_pt_poly = ope_pt.context_record.get(pk=pks["CR Pt Poly"]) - self.assertPoly(cr_pt_poly, geoms[1], geoms[0][2]) - cr_pt_pt = ope_pt.context_record.get(pk=pks["CR Pt Pt"]) - self.assertPt(cr_pt_pt, geoms[1]) - - self.assertPt( - cr_pt_pt.base_finds.get(pk=pks["Find Point from CR Pt Pt"]), geoms[2] - ) - self.assertPoly( - cr_pt_pt.base_finds.get(pk=pks["Find Polygon from CR Pt Pt"]), - geoms[2], - geoms[1][2], - ) - self.assertPt( - cr_poly_pt.base_finds.get(pk=pks["Find Point from CR Poly Pt"]), geoms[2] - ) - self.assertPoly( - cr_poly_pt.base_finds.get(pk=pks["Find Polygon from CR Poly Pt"]), - geoms[2], - geoms[1][2], - ) - self.assertPt( - cr_pt_poly.base_finds.get(pk=pks["Find Point from CR Pt Poly"]), geoms[2] - ) - self.assertPoly( - cr_pt_poly.base_finds.get(pk=pks["Find Polygon from CR Pt Poly"]), - geoms[2], - geoms[0][2], - ) - self.assertPt( - cr_poly_poly.base_finds.get(pk=pks["Find Point from CR Poly Poly"]), - geoms[2], - ) - self.assertPoly( - cr_poly_poly.base_finds.get(pk=pks["Find Polygon from CR Poly Poly"]), - geoms[2], - ) - """ - - @staticmethod - def geojson_geo_items(geoms, pks, test_get_geo_items=False): - Operation = apps.get_model("archaeological_operations", "Operation") - ContextRecord = apps.get_model( - "archaeological_context_records", "ContextRecord" - ) - BaseFind = apps.get_model("archaeological_finds", "BaseFind") - - cache_dics_t, cache_dics_f = {}, {} - res = {} - - def finds_first(x): - if x[:2] == "CR": - return 0 - if x[:4] == "Find": - return -1 - else: - return 1 - - labels = list(pks.keys()) - labels.sort(key=finds_first) - for label in labels: - pk = pks[label] - pt_coords, precise = GeomaticTest.pt_coords_from_label(label, geoms) - if label[:4] == "Find": - dic_t = { - "type": "Feature", - "geometry": {"type": "MultiPolygon", "coordinates": geoms[2][0]}, - "properties": {"label": label}, - } - dic_f = { - "type": "Feature", - "geometry": { - "type": "Point", - "coordinates": pt_coords, - }, - "properties": {"label": label}, - } - cache_dics_t[label] = dic_t - cache_dics_f[label] = dic_f - if test_get_geo_items: - res_t = BaseFind.objects.get(pk=pk).get_geo_items(get_polygons=True) - res_f = BaseFind.objects.get(pk=pk).get_geo_items( - get_polygons=False - ) - get_pk = "?pk=" - else: - get_polys = dic_t - get_pts = dic_f - - elif label[:2] == "CR": - cache_key = lambda x: "Find " + x + " from " + label - dic_t = { - "type": "Feature", - "geometry": {"type": "MultiPolygon", "coordinates": geoms[1][0]}, - "properties": { - "label": label, - "base-finds": { - "type": "FeatureCollection", - "features": [ - cache_dics_t[cache_key("Polygon")], - cache_dics_t[cache_key("Point")], - ], - }, - }, - } - dic_f = { - "type": "Feature", - "geometry": { - "type": "Point", - "coordinates": pt_coords, - }, - "properties": { - "label": label, - "base-finds": { - "type": "FeatureCollection", - "features": [ - cache_dics_f[cache_key("Polygon")], - cache_dics_f[cache_key("Point")], - ], - }, - }, - } - cache_dics_t[label] = dic_t - cache_dics_f[label] = dic_f - if test_get_geo_items: - res_t = ContextRecord.objects.get(pk=pk).get_geo_items( - get_polygons=True - ) - res_f = ContextRecord.objects.get(pk=pk).get_geo_items( - get_polygons=False - ) - get_pk = "?context_record_pk=" - else: - get_polys = copy.deepcopy(dic_t) - get_polys["properties"]["base-finds"] = [ - cache_key("Polygon"), - cache_key("Point"), - ] - get_pts = copy.deepcopy(dic_f) - get_pts["properties"]["base-finds"] = [ - cache_key("Polygon"), - cache_key("Point"), - ] - else: - real_label = "OA3" - cache_key_prefix = "CR " + label + " " - if label == "Pt": - real_label = "OA2" - dic_t = { - "type": "Feature", - "geometry": {"type": "MultiPolygon", "coordinates": geoms[0][0]}, - "properties": { - "label": real_label, - "context-records": { - "type": "FeatureCollection", - "features": [ - cache_dics_t[cache_key_prefix + "Poly"], - cache_dics_t[cache_key_prefix + "Pt"], - ], - }, - }, - } - dic_f = { - "type": "Feature", - "geometry": { - "type": "Point", - "coordinates": pt_coords, - }, - "properties": { - "label": real_label, - "context-records": { - "type": "FeatureCollection", - "features": [ - cache_dics_f[cache_key_prefix + "Poly"], - cache_dics_f[cache_key_prefix + "Pt"], - ], - }, - }, - } - if test_get_geo_items: - res_t = Operation.objects.get(pk=pk).get_geo_items( - get_polygons=True - ) - res_f = Operation.objects.get(pk=pk).get_geo_items( - get_polygons=False - ) - get_pk = "?operation_pk=" - else: - get_polys = copy.deepcopy(dic_t) - bf_labels = [] - for cr in dic_t["properties"]["context-records"]["features"]: - for bf in cr["properties"]["base-finds"]["features"]: - bf_labels.append(bf["properties"]["label"]) - get_polys["properties"] = { - "context-records": [ - cache_key_prefix + "Poly", - cache_key_prefix + "Pt", - ], - "base-finds": bf_labels, - } - get_pts = copy.deepcopy(dic_f) - bf_labels = [] - for cr in dic_f["properties"]["context-records"]["features"]: - for bf in cr["properties"]["base-finds"]["features"]: - bf_labels.append(bf["properties"]["label"]) - get_pts["properties"] = { - "context-records": [ - cache_key_prefix + "Poly", - cache_key_prefix + "Pt", - ], - "base-finds": bf_labels, - } - - if test_get_geo_items: - res[label] = { - "get_polys": dic_t, - "get_pts": dic_f, - "res_polys": res_t, - "res_pts": res_f, - "get_pk": get_pk, - } - else: - res[label] = { - "get_polys": get_polys, - "get_pts": get_pts, - "precise": precise, - } - return res - - class NewItems(TestCase): fixtures = COMMON_FIXTURES diff --git a/ishtar_common/utils.py b/ishtar_common/utils.py index 2a41ab0aa..a99a40d02 100644 --- a/ishtar_common/utils.py +++ b/ishtar_common/utils.py @@ -2363,3 +2363,7 @@ RE_COORDS = r"(" + RE_NUMBER + r") (" + RE_NUMBER + r")" def reverse_coordinates(wkt): return re.sub(RE_COORDS, r"\2 \1", wkt) + + +def reverse_list_coordinates(lst): + return list(reversed(lst))
\ No newline at end of file |