Skip to content

Commit

Permalink
Merge b5187c3 into f7cce51
Browse files Browse the repository at this point in the history
  • Loading branch information
LePetitTim committed Jun 26, 2018
2 parents f7cce51 + b5187c3 commit 66d0f95
Show file tree
Hide file tree
Showing 6 changed files with 100 additions and 22 deletions.
3 changes: 2 additions & 1 deletion docs/changelog.rst
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ CHANGELOG
* Fix virtualenv install
* Upgrade celery to 4.1.1
* Keep inode and mtime when synced file don't change
* Fix Implantation year duplication and None value
* Fix the bug which remove a path when we merge 2 paths with a 3rd path on the point of merge. (ref #1747)



2.19.1 (2018-05-28)
Expand Down
2 changes: 2 additions & 0 deletions geotrek/common/utils/postgresql.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
# -*- coding: utf-8 -*-

import logging
import traceback
from functools import wraps
Expand Down
3 changes: 3 additions & 0 deletions geotrek/core/locale/fr/LC_MESSAGES/django.po
Original file line number Diff line number Diff line change
Expand Up @@ -223,3 +223,6 @@ msgstr "Les tronçons ont été fusionnés."

msgid "No matching points to merge paths found"
msgstr "Aucun point de correspondance trouvé pour fusionner les tronçons"

msgid "You can't merge 2 paths with a 3rd path in the intersection"
msgstr "Vous ne pouvez pas fusionner deux tronçons qui intersectent un troisième tronçon"
20 changes: 15 additions & 5 deletions geotrek/core/sql/70_troncons_merge.sql
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
CREATE OR REPLACE FUNCTION geotrek.ft_merge_path(updated integer, merged integer)
RETURNS boolean AS $$
DROP FUNCTION IF EXISTS geotrek.ft_merge_path(integer,integer) CASCADE;
CREATE FUNCTION geotrek.ft_merge_path(updated integer, merged integer)
RETURNS integer AS $$

DECLARE
element RECORD;
Expand All @@ -19,7 +20,7 @@ BEGIN
IF updated = merged
THEN
-- can't merged a path itself !
return FALSE;
RETURN 0;

END IF;

Expand Down Expand Up @@ -69,10 +70,19 @@ BEGIN

ELSE
-- no snapping -> END !
RETURN FALSE;
RETURN 0;

END IF;

FOR element IN
SELECT * FROM l_t_troncon WHERE id != updated AND id != merged
LOOP
IF ST_EQUALS(ST_STARTPOINT(updated_geom), ST_STARTPOINT(element.geom)) OR ST_EQUALS(ST_ENDPOINT(updated_geom), ST_STARTPOINT(element.geom)) OR ST_EQUALS(ST_STARTPOINT(updated_geom), ST_ENDPOINT(element.geom)) OR ST_EQUALS(ST_ENDPOINT(updated_geom), ST_ENDPOINT(element.geom))
THEN
RETURN 2;
END IF;
END LOOP;

-- update events on updated path
FOR element IN
SELECT * FROM e_r_evenement_troncon et
Expand Down Expand Up @@ -162,7 +172,7 @@ BEGIN
-- Delete merged Path
DELETE FROM l_t_troncon WHERE id = merged;

RETURN TRUE;
RETURN 1;

END;
$$ LANGUAGE plpgsql;
59 changes: 59 additions & 0 deletions geotrek/core/tests/test_path_merge.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@ def test_path_merge_without_snap(self):
self.assertEqual(path_AB.geom, LineString((0.0, 0.0), (4.0, 0.0), (8.0, 0.0), srid=settings.SRID))
self.assertEqual(path_AB.length, original_AB_length + original_CD_length)

path_AB.delete()
path_CD.delete()

path_AB = PathFactory.create(name="path_AB", geom=LineString((4, 0), (0, 0)))
path_CD = PathFactory.create(name="path_CD", geom=LineString((4, 0), (8, 0)))
original_AB_length = path_AB.length
Expand All @@ -40,6 +43,9 @@ def test_path_merge_without_snap(self):
self.assertEqual(path_AB.geom, LineString((0, 0), (4, 0), (8, 0), srid=settings.SRID))
self.assertEqual(path_AB.length, original_AB_length + original_CD_length)

path_AB.delete()
path_CD.delete()

path_AB = PathFactory.create(name="path_AB", geom=LineString((4, 0), (0, 0)))
path_CD = PathFactory.create(name="path_CD", geom=LineString((8, 0), (4, 0)))
original_AB_length = path_AB.length
Expand All @@ -49,6 +55,9 @@ def test_path_merge_without_snap(self):
self.assertEqual(path_AB.geom, LineString((0, 0), (4, 0), (8, 0), srid=settings.SRID))
self.assertEqual(path_AB.length, original_AB_length + original_CD_length)

path_AB.delete()
path_CD.delete()

path_AB = PathFactory.create(name="path_AB", geom=LineString((0, 0), (4, 0)))
path_CD = PathFactory.create(name="path_CD", geom=LineString((8, 0), (4, 0)))
original_AB_length = path_AB.length
Expand Down Expand Up @@ -82,29 +91,56 @@ def test_path_merge_with_snap(self):
self.assertEqual(path_AB.merge_path(path_CD), True)
self.assertEqual(path_AB.geom, LineString((0, 0), (15, 0), (16, 0), (30, 0), srid=settings.SRID))

path_AB.delete()
path_CD.delete()

path_AB = PathFactory.create(name="path_AB", geom=LineString((15, 0), (0, 0)))
path_CD = PathFactory.create(name="path_CD", geom=LineString((16, 0), (30, 0)))

self.assertEqual(path_AB.merge_path(path_CD), True)
self.assertEqual(path_AB.geom, LineString((0, 0), (15, 0), (16, 0), (30, 0), srid=settings.SRID))

path_AB.delete()
path_CD.delete()

path_AB = PathFactory.create(name="path_AB", geom=LineString((15, 0), (0, 0)))
path_CD = PathFactory.create(name="path_CD", geom=LineString((30, 0), (16, 0)))

self.assertEqual(path_AB.merge_path(path_CD), True)
self.assertEqual(path_AB.geom, LineString((0, 0), (15, 0), (16, 0), (30, 0), srid=settings.SRID))

path_AB.delete()
path_CD.delete()

path_AB = PathFactory.create(name="path_AB", geom=LineString((0, 0), (15, 0)))
path_CD = PathFactory.create(name="path_CD", geom=LineString((30, 0), (16, 0)))

self.assertEqual(path_AB.merge_path(path_CD), True)
self.assertEqual(path_AB.geom, LineString((0, 0), (15, 0), (16, 0), (30, 0), srid=settings.SRID))

path_AB.delete()
path_CD.delete()

path_AB = PathFactory.create(name="PATH_AB", geom=LineString((0, 0), (5, 0)))
path_CD = PathFactory.create(name="PATH_CD", geom=LineString((50, 0), (100, 0)))

self.assertEqual(path_AB.merge_path(path_CD), False)

def test_path_merge_with_other_path_next_ws(self):
"""
F
|
|
E
A---------------B + C-------------------D
Do not merge !
"""
path_AB = PathFactory.create(name="PATH_AB", geom=LineString((0, 1), (10, 1)))
path_CD = PathFactory.create(name="PATH_CD", geom=LineString((10, 1), (20, 1)))
PathFactory.create(name="PATH_EF", geom=LineString((10, 1), (10, 5)))
self.assertEqual(path_AB.merge_path(path_CD), 2)

def test_recompute_pk_no_reverse(self):
"""
A---------------B + C-------------------D A----------------BC----------------D
Expand Down Expand Up @@ -154,6 +190,29 @@ def test_recompute_pk_no_reverse(self):
self.assertEqual(a4_updated.start_position, a4.start_position * (path_CD_original_length / path_AB.length) + path_AB_original_length / path_AB.length)
self.assertEqual(a4_updated.end_position, a4.end_position * (path_CD_original_length / path_AB.length) + path_AB_original_length / path_AB.length)

def test_path_aggregation(self):
"""
A---------------B + C-------------------D A-----------------BC----------------D
|---------------------| |------------------|
E1 E1
2 path aggregations
"""
path_AB = PathFactory.create(name="PATH_AB", geom=LineString((0, 1), (10, 1)))
path_CD = PathFactory.create(name="PATH_CD", geom=LineString((10, 1), (20, 1)))
e1 = TopologyFactory.create(no_path=True)
PathAggregationFactory.create(path=path_AB, topo_object=e1, start_position=0.5, end_position=1, order=0)
PathAggregationFactory.create(path=path_CD, topo_object=e1, start_position=0, end_position=0.5, order=1)
path_AB.merge_path(path_CD)
self.assertEqual(path_AB.geom, LineString((0, 1), (10, 1), (20, 1), srid=settings.SRID))
self.assertEqual(PathAggregation.objects.filter(topo_object=e1).count(), 2)
self.assertEqual(PathAggregation.objects.count(), 2)
first = PathAggregation.objects.first()
last = PathAggregation.objects.last()
self.assertEqual((first.start_position, first.end_position), (0.25, 0.5))
self.assertEqual((last.start_position, last.end_position), (0.5, 0.75))
self.assertEqual(Topology.objects.count(), 1)

def test_recompute_pk_reverse_AB(self):
"""
A---------------B + C-------------------D B-----------------AC----------------D
Expand Down
35 changes: 19 additions & 16 deletions geotrek/core/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -240,29 +240,32 @@ def merge_path(request):
response = {}

if request.method == 'POST':
try:
ids_path_merge = request.POST.getlist('path[]')

if len(ids_path_merge) == 2:
path_a = Path.objects.get(pk=ids_path_merge[0])
path_b = Path.objects.get(pk=ids_path_merge[1])
if not path_a.same_structure(request.user) or not path_b.same_structure(request.user):
response = {'error': _(u"You don't have the right to change these paths")}
ids_path_merge = request.POST.getlist('path[]')

elif path_a.merge_path(path_b):
response = {'success': _(u"Paths merged successfully")}
messages.success(request, _(u"Paths merged successfully"))
assert len(ids_path_merge) == 2

else:
response = {'error': _(u"No matching points to merge paths found")}
path_a = Path.objects.get(pk=ids_path_merge[0])
path_b = Path.objects.get(pk=ids_path_merge[1])

else:
raise
if not path_a.same_structure(request.user) or not path_b.same_structure(request.user):
response = {'error': _(u"You don't have the right to change these paths")}
return HttpJSONResponse(response)

try:
result = path_a.merge_path(path_b)
except Exception as exc:
response = {'error': exc, }
return HttpJSONResponse(response)

if result == 2:
response = {'error': _(u"You can't merge 2 paths with a 3rd path in the intersection")}
elif result == 0:
response = {'error': _(u"No matching points to merge paths found")}
else:
response = {'success': _(u"Paths merged successfully")}
messages.success(request, _(u"Paths merged successfully"))

return HttpResponse(json.dumps(response), content_type="application/json")
return HttpJSONResponse(response)


class ParametersView(View):
Expand Down

0 comments on commit 66d0f95

Please sign in to comment.