-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmapcompare_d500_last.py
1411 lines (1111 loc) · 71.5 KB
/
mapcompare_d500_last.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
#
# Implementation of MapCompare algorithm.
# Author: James P. Biagioni ([email protected])
# Company: University of Illinois at Chicago
# Created: 6/7/11
#
# Author: Mahmuda Ahmed
# Company: The University of Texas at San Antonio
# Modified: 2013
#
# Author: Jorren Hendriks ([email protected])
# Institute: Eindhoven University of Technology (TU/e)
# Modified: 4/30/2020
#
# Author: Erfan Hosseini Sereshgi ([email protected])
# Company: Tulane University
# Modified: 6/10/2021
#
# Author: Jordi Aguilar Larruy ([email protected])
# Company: Universitat Politècnica de Catalunya
# Modified: 5/31/2021
#
import math
import os
import random
import csv
import sys
import getopt
import time
from streetmap import StreetMap
import spatialfunclib
from rtree import Rtree
import networkx as nx
import pandas as pd
# global parameters
breadcrumb_interval = 5.0 # meters
breadcrumb_max_distance = float('infinity') # meters
match_distance_threshold = 15.0 # meters
debug_mode = False
bearing_limit = 45.0 # degrees
compare_mode = "knn"
class Breadcrumb:
def __init__(self, id, latitude, longitude, bearing):
self.id = id
self.latitude = latitude
self.longitude = longitude
self.bearing = bearing
class BreadcrumbPath:
def __init__(self):
self.breadcrumbs = {}
self.breadcrumb_index = Rtree()
def add_breadcrumb(self, breadcrumb):
self.breadcrumbs[breadcrumb.id] = breadcrumb
self.breadcrumb_index.insert(breadcrumb.id, (breadcrumb.longitude, breadcrumb.latitude))
def delete_breadcrumb(self, breadcrumb):
del self.breadcrumbs[breadcrumb.id]
self.breadcrumb_index.delete(breadcrumb.id, [breadcrumb.longitude, breadcrumb.latitude, breadcrumb.longitude, breadcrumb.latitude])
class MatchedCrumbs:
def __init__(self, map1_breadcrumb, map2_breadcrumb, distance):
self.map1_breadcrumb = map1_breadcrumb
self.map2_breadcrumb = map2_breadcrumb
self.distance = distance
class MapCompare:
def __init__(self):
self.map1 = None
self.map2 = None
def load_maps(self, map1_filename, map2_filename):
map1_loaded = False
map2_loaded = False
# create new StreetMap object
self.map1 = StreetMap()
# load map1 OSMDB
if self.map1.load_textdb_osm(map1_filename):
map1_loaded = True
# create new StreetMap object
self.map2 = StreetMap()
# load map2 GraphDB
if self.map2.load_textdb_algo(map2_filename):
map2_loaded = True
print(map1_loaded,map2_loaded)
return map1_loaded, map2_loaded
def generate_root_locations(self, root_locations_filename):
print("generating root locations...")
# output newline for formatting
sys.stdout.write("\n")
sys.stdout.flush()
# open evaluation output file
root_locations_file = open_mkdir(root_locations_filename, 'w')
# select root location from map1 and map2
root_location1 = self._find_components(self.map1)
root_location2 = self._find_components(self.map2)
#root_location1 = root_location1 + root_location2
#for rl in range(len(root_location1)):
# root_locations_file.write(str(rl) + "," + str(root_location1[rl][0]) + "," + str(root_location1[rl][1]) + "\n")
for rl in range(len(root_location1)):
root_locations_file.write("1," + str(rl) + "," + str(root_location1[rl][0]) + "," + str(root_location1[rl][1]) + "\n")
for rl in range(len(root_location2)):
root_locations_file.write("2," + str(rl) + "," + str(root_location2[rl][0]) + "," + str(root_location2[rl][1]) + "\n")
root_locations_file.flush()
root_locations_file.close()
print("done.")
def compare_maps(self, eval_filename, root_locations_filename):
# if there are no nodes or edges in map2
if ((len(self.map2.nodes) == 0) or (len(self.map2.edges) == 0)):
# open evaluation output file
eval_file = open(eval_filename, 'w')
# write nothing into evaluation output file
eval_file.write("")
# close evaluation output file
eval_file.close()
# terminate comparison
return
# output newline for formatting
sys.stdout.write("\n")
sys.stdout.flush()
# output start of map comparison
sys.stdout.write("\nComparing maps...\n")
sys.stdout.flush()
print("reading root locations...")
rootlocations1 = {}
rootlocations2 = {}
# open evaluation output file
with open_mkdir(root_locations_filename, 'r') as f:
c = csv.reader(f, delimiter=',', skipinitialspace=True)
# iterate through all query results
for map, id, lat, lon in c:
if int(map) == 1:
rootlocations1[int(id)] = (float(lat), float(lon))
if int(map) == 2:
rootlocations2[int(id)] = (float(lat), float(lon))
# clear evaluation output file
open_mkdir(eval_filename, 'w').close()
print("Seeds on map1: "+str(len(rootlocations1)))
print("Seeds on map2: "+str(len(rootlocations2)))
# get breadcrumb edges of both maps
print("Getting breadcrumb edges")
map1_breadcrumb_edges = []
map2_breadcrumb_edges = []
for i in rootlocations1.values():
map1_breadcrumb_edges += self._get_breadcrumb_edges(self.map1, i, match_distance_threshold)
for i in rootlocations2.values():
map2_breadcrumb_edges += self._get_breadcrumb_edges(self.map2, i, match_distance_threshold)
print("Getting breadcrumb paths")
# get breadcrumb paths of both maps
map1_breadcrumb_path = self._get_breadcrumb_path(self.map1, rootlocations1[0], map1_breadcrumb_edges, None, None)
map2_breadcrumb_path = self._get_breadcrumb_path(self.map2, rootlocations2[0], map2_breadcrumb_edges,
None, None)
if (debug_mode):
print("root location: " + str(rootlocations1[0][0]) + "," + str(rootlocations1[0][1]))
self._write_breadcrumb_path_to_file(map1_breadcrumb_path, "map1_breadcrumb_path.txt")
self._write_breadcrumb_path_to_file(map2_breadcrumb_path, "map2_breadcrumb_path.txt")
print("Comparing breadcrumb paths using "+compare_mode)
# compare breadcrumb paths for map1 and map2
if compare_mode == "knn":
self._compare_breadcrumb_paths(map1_breadcrumb_path, map2_breadcrumb_path, eval_filename)
elif compare_mode == "wmm":
self._weighted_maximum_matching(map1_breadcrumb_path, map2_breadcrumb_path, eval_filename)
elif compare_mode == "mm":
self._maximum_matching(map1_breadcrumb_path, map2_breadcrumb_path, eval_filename)
elif compare_mode == "g":
self._compare_breadcrumb_paths_greedy(map1_breadcrumb_path, map2_breadcrumb_path, eval_filename)
elif compare_mode == "gs":
self._compare_breadcrumb_paths_greedy_shortest(map1_breadcrumb_path, map2_breadcrumb_path, eval_filename)
elif compare_mode == "gsb":
self._compare_breadcrumb_paths_greedy_shortest_bearing(map1_breadcrumb_path, map2_breadcrumb_path, eval_filename)
else:
print("Not a valid comparing option --- using the default k-nearest neighbors matching algorithm")
self._compare_breadcrumb_paths(map1_breadcrumb_path, map2_breadcrumb_path, eval_filename)
# reset edge visited flags in both maps
self.map1.reset_edge_visited_flags()
self.map2.reset_edge_visited_flags()
# finished with current evaluation
print("'\rEvaluation run " + "... " + "done.", end="")
# DEBUG -- terminate after one evaluation
if (debug_mode):
exit()
print(flush=True)
return(len(rootlocations1),len(rootlocations2))
def compute_results(self, eval_file_name):
counter = {
"gTot": 0,
"hTot": 0,
"pos": 0
}
# open evaluation output file
with open_mkdir(eval_file_name, 'r') as f:
c = csv.reader(f, delimiter=',', skipinitialspace=True)
# iterate through all results
for d, x, y, u, v in c:
dist = int(float(d))
if dist == 1000000:
counter["hTot"] += 1
elif dist == 2000000:
counter["gTot"] += 1
else:
for k in counter.keys():
counter[k] += 1
m, n, k = counter["gTot"], counter["hTot"], counter["pos"]
print(("-[ Sample Counts ]" + "-" * 42 + "\n"
"m = #samples in G | n = #samples in H | k = #matched samples\n"
"{m:17d} | {n:17d} | {k:20d}\n" + "-" * 60)
.format(m=m, n=n, k=k))
print(("-[ Sample Statistics ]" + "-" * 11 + "\n"
"precision | recall | F-score\n"
"{p:1.7f} | {r:1.7f} | {f:1.7f}\n" + "-" * 33)
.format(p=k / m, r=k / n, f=2 * k / (n + m)))
print('my parameters: ',breadcrumb_interval, bearing_limit, match_distance_threshold, compare_mode)
return(m,n,k,float(k/m),float(k / n),float(2 * k / (n + m)))
def _find_components(self, curr_map):
rootlocations = []
bfs_queue = []
list_of_edges = list(curr_map.edges.values())
# print(list_of_edges)
connected_component_nodes = []
connected_component = []
list_of_nodes = list(curr_map.nodes.values())
# print(list_of_nodes)
while len(list_of_nodes) > 0:
source_node = list_of_nodes[0]
if len(source_node.out_nodes) == 0:
list_of_nodes.remove(source_node)
continue
bfs_queue.append(source_node)
# print('bfs_queue: ',bfs_queue)
while (len(bfs_queue) > 0):
curr_node = bfs_queue.pop(0)
connected_component_nodes.append(curr_node)
list_of_nodes.remove(curr_node)
for out_node in curr_node.out_nodes:
if out_node not in bfs_queue and out_node in list_of_nodes:
bfs_queue.append(out_node)
# print('connected_component_nodes: ',connected_component_nodes)
for node in connected_component_nodes:
for edge in list_of_edges:
if edge.in_node.id == node.id or edge.out_node.id == node.id:
connected_component.append(edge)
list_of_edges.remove(edge)
# print('connected_component: ',connected_component)
rootlocations.append(self._select_map_root_location(connected_component))
# print('rootlocations: ',rootlocations)
connected_component = []
connected_component_nodes = []
return rootlocations
def _maximum_matching(self, map1_breadcrumb_path, map2_breadcrumb_path, eval_file_name):
# storage for list of matched breadcrumbs
matched_breadcrumbs = []
matched = 0
# DEBUG -- output number of breadcrumbs
if (debug_mode):
print("map1 breadcrumbs: " + str(len(map1_breadcrumb_path.breadcrumbs)))
print("map2 breadcrumbs: " + str(len(map2_breadcrumb_path.breadcrumbs)))
# append results to eval file
with open_mkdir(eval_file_name, 'a+') as eval_file:
graph = nx.Graph()
graph.add_nodes_from(map1_breadcrumb_path.breadcrumbs)
graph.add_nodes_from(map2_breadcrumb_path.breadcrumbs)
for node1 in map1_breadcrumb_path.breadcrumbs.values():
for node2 in map2_breadcrumb_path.breadcrumbs.values():
breadcrumb_distance = self._distance(node1,node2)
if breadcrumb_distance <= match_distance_threshold:
bearing_difference = spatialfunclib.bearing_difference(node1.bearing,node2.bearing)
if bearing_difference < bearing_limit:
graph.add_edge(node1,node2)
print("The graph is loaded - starting the matching algorithm")
matching = nx.algorithms.matching.max_weight_matching(graph, maxcardinality=True)
print("Matching is done - writing files")
for edge in matching:
breadcrumb_distance = self._distance(edge[0],edge[1])
if (edge[0] in map1_breadcrumb_path.breadcrumbs.values()) and (edge[1] in map2_breadcrumb_path.breadcrumbs.values()):
matched_breadcrumb = MatchedCrumbs(edge[0], edge[1], breadcrumb_distance)
else:
matched_breadcrumb = MatchedCrumbs(edge[1], edge[0], breadcrumb_distance)
eval_file.write(str(matched_breadcrumb.distance) + "," + str(
matched_breadcrumb.map1_breadcrumb.latitude) + "," + str(
matched_breadcrumb.map1_breadcrumb.longitude) + "," + str(
matched_breadcrumb.map2_breadcrumb.latitude) + "," + str(
matched_breadcrumb.map2_breadcrumb.longitude) + "\n")
matched += 1
if matched_breadcrumb.map1_breadcrumb in map1_breadcrumb_path.breadcrumbs.values():
map1_breadcrumb_path.delete_breadcrumb(matched_breadcrumb.map1_breadcrumb)
elif matched_breadcrumb.map1_breadcrumb in map2_breadcrumb_path.breadcrumbs.values():
map2_breadcrumb_path.delete_breadcrumb(matched_breadcrumb.map1_breadcrumb)
if matched_breadcrumb.map2_breadcrumb in map2_breadcrumb_path.breadcrumbs.values():
map2_breadcrumb_path.delete_breadcrumb(matched_breadcrumb.map2_breadcrumb)
elif matched_breadcrumb.map2_breadcrumb in map1_breadcrumb_path.breadcrumbs.values():
map1_breadcrumb_path.delete_breadcrumb(matched_breadcrumb.map2_breadcrumb)
for map1_breadcrumb in map1_breadcrumb_path.breadcrumbs.values():
# output map1 unmatched edge value
eval_file.write(
"1000000" + "," + str(map1_breadcrumb.latitude) + "," + str(map1_breadcrumb.longitude) + "," + str(
map1_breadcrumb.latitude) + "," + str(map1_breadcrumb.longitude) + "\n")
# iterate through remaining map2 breadcrumbs
for map2_breadcrumb in map2_breadcrumb_path.breadcrumbs.values():
# output map2 spurious edge value
eval_file.write(
"2000000" + "," + str(map2_breadcrumb.latitude) + "," + str(map2_breadcrumb.longitude) + "," + str(
map2_breadcrumb.latitude) + "," + str(map2_breadcrumb.longitude) + "\n")
eval_file.flush()
def _weighted_maximum_matching(self, map1_breadcrumb_path, map2_breadcrumb_path, eval_file_name):
# storage for list of matched breadcrumbs
matched_breadcrumbs = []
matched = 0
# DEBUG -- output number of breadcrumbs
if (debug_mode):
print("map1 breadcrumbs: " + str(len(map1_breadcrumb_path.breadcrumbs)))
print("map2 breadcrumbs: " + str(len(map2_breadcrumb_path.breadcrumbs)))
# append results to eval file
with open_mkdir(eval_file_name, 'a+') as eval_file:
graph = nx.Graph()
graph.add_nodes_from(map1_breadcrumb_path.breadcrumbs)
graph.add_nodes_from(map2_breadcrumb_path.breadcrumbs)
for node1 in map1_breadcrumb_path.breadcrumbs.values():
for node2 in map2_breadcrumb_path.breadcrumbs.values():
breadcrumb_distance = self._distance(node1,node2)
if breadcrumb_distance <= match_distance_threshold:
bearing_difference = spatialfunclib.bearing_difference(node1.bearing,node2.bearing)
if bearing_difference < bearing_limit:
graph.add_edge(node1,node2, weight=match_distance_threshold - breadcrumb_distance)
print("The graph is loaded - starting the matching algorithm")
matching = nx.algorithms.matching.max_weight_matching(graph)
print("Matching is done - writing files")
for edge in matching:
breadcrumb_distance = self._distance(edge[0],edge[1])
if (edge[0] in map1_breadcrumb_path.breadcrumbs.values()) and (edge[1] in map2_breadcrumb_path.breadcrumbs.values()):
matched_breadcrumb = MatchedCrumbs(edge[0], edge[1], breadcrumb_distance)
else:
matched_breadcrumb = MatchedCrumbs(edge[1], edge[0], breadcrumb_distance)
eval_file.write(str(matched_breadcrumb.distance) + "," + str(
matched_breadcrumb.map1_breadcrumb.latitude) + "," + str(
matched_breadcrumb.map1_breadcrumb.longitude) + "," + str(
matched_breadcrumb.map2_breadcrumb.latitude) + "," + str(
matched_breadcrumb.map2_breadcrumb.longitude) + "\n")
matched += 1
if matched_breadcrumb.map1_breadcrumb in map1_breadcrumb_path.breadcrumbs.values():
map1_breadcrumb_path.delete_breadcrumb(matched_breadcrumb.map1_breadcrumb)
elif matched_breadcrumb.map1_breadcrumb in map2_breadcrumb_path.breadcrumbs.values():
map2_breadcrumb_path.delete_breadcrumb(matched_breadcrumb.map1_breadcrumb)
if matched_breadcrumb.map2_breadcrumb in map2_breadcrumb_path.breadcrumbs.values():
map2_breadcrumb_path.delete_breadcrumb(matched_breadcrumb.map2_breadcrumb)
elif matched_breadcrumb.map2_breadcrumb in map1_breadcrumb_path.breadcrumbs.values():
map1_breadcrumb_path.delete_breadcrumb(matched_breadcrumb.map2_breadcrumb)
for map1_breadcrumb in map1_breadcrumb_path.breadcrumbs.values():
# output map1 unmatched edge value
eval_file.write(
"1000000" + "," + str(map1_breadcrumb.latitude) + "," + str(map1_breadcrumb.longitude) + "," + str(
map1_breadcrumb.latitude) + "," + str(map1_breadcrumb.longitude) + "\n")
# iterate through remaining map2 breadcrumbs
for map2_breadcrumb in map2_breadcrumb_path.breadcrumbs.values():
# output map2 spurious edge value
eval_file.write(
"2000000" + "," + str(map2_breadcrumb.latitude) + "," + str(map2_breadcrumb.longitude) + "," + str(
map2_breadcrumb.latitude) + "," + str(map2_breadcrumb.longitude) + "\n")
eval_file.flush()
def _compare_breadcrumb_paths_greedy_shortest_bearing(self, map1_breadcrumb_path, map2_breadcrumb_path, eval_file_name):
# storage for list of matched breadcrumbs
matched_breadcrumbs = []
matched = 0
# DEBUG -- output number of breadcrumbs
if (debug_mode):
print("map1 breadcrumbs: " + str(len(map1_breadcrumb_path.breadcrumbs)))
print("map2 breadcrumbs: " + str(len(map2_breadcrumb_path.breadcrumbs)))
# append results to eval file
with open_mkdir(eval_file_name, 'a+') as eval_file:
# iterate through map1 breadcrumbs, find nearest neighbor for each, and store in matched_breadcrumbs
# This computes a many-to-many matching
bearing_flag = 0
if (len(map2_breadcrumb_path.breadcrumbs) > 0):
for map1_breadcrumb in map1_breadcrumb_path.breadcrumbs.values():
while bearing_flag >= 0:
# find closest breadcrumb in map2. Make sure there are some breadcrumbs left
closest_map2_breadcrumb_id = list(map2_breadcrumb_path.breadcrumb_index.nearest((map1_breadcrumb.longitude, map1_breadcrumb.latitude), bearing_flag+1))[bearing_flag]
closest_map2_breadcrumb = map2_breadcrumb_path.breadcrumbs[closest_map2_breadcrumb_id]
breadcrumb_distance = self._distance(map1_breadcrumb, closest_map2_breadcrumb)
bearing_difference = spatialfunclib.bearing_difference(map1_breadcrumb.bearing, closest_map2_breadcrumb.bearing)
if bearing_difference < bearing_limit:
# create matched crumbs object
matched_breadcrumb = MatchedCrumbs(map1_breadcrumb, closest_map2_breadcrumb, breadcrumb_distance)
matched_breadcrumbs.append(matched_breadcrumb)
bearing_flag = -1
else:
bearing_flag+=1
bearing_flag = 0
# Now filter this matching to create a 1-to-1 matching, prioritizing shortest distances
# 1. Sort list of matched breadcrumbs in ascending order according to distance
matched_breadcrumbs.sort(key=lambda x: x.distance)
# 2. Continue while there are matched breadcrumbs to be processed
while (len(matched_breadcrumbs) > 0):
# if distance between closest matched breadcrumbs is greater than the threshold
if (matched_breadcrumbs[0].distance > match_distance_threshold):
# Exit loop early. All nearest neighbor matches are too far away.
break
# compute bearing difference between breadcrumbs
#bearing_difference = spatialfunclib.bearing_difference(matched_breadcrumbs[0].map1_breadcrumb.bearing, matched_breadcrumbs[0].map2_breadcrumb.bearing)
#print(bearing_difference)
# if map2 breadcrumb is still available
if ( (matched_breadcrumbs[0].map2_breadcrumb.id in map2_breadcrumb_path.breadcrumbs.keys())):
# Fix this matching.
# remove map1 breadcrumb from path
map1_breadcrumb_path.delete_breadcrumb(matched_breadcrumbs[0].map1_breadcrumb)
# remove map2 breadcrumb from path
map2_breadcrumb_path.delete_breadcrumb(matched_breadcrumbs[0].map2_breadcrumb)
matched += 1
# output distance between breadcrumbs for evaluation output file
eval_file.write(str(matched_breadcrumbs[0].distance) + "," + str(
matched_breadcrumbs[0].map1_breadcrumb.latitude) + "," + str(
matched_breadcrumbs[0].map1_breadcrumb.longitude) + "," + str(
matched_breadcrumbs[0].map2_breadcrumb.latitude) + "," + str(
matched_breadcrumbs[0].map2_breadcrumb.longitude) + "\n")
matched_breadcrumbs.pop(0)
# If map2 breadcrumb is no longer available, find a new nearest neighbor
else:
if (len(map2_breadcrumb_path.breadcrumbs) > 0):
bearing_flag = 0
while bearing_flag >= 0:
# find closest breadcrumb in map2.
closest_map2_breadcrumb_id = list(map2_breadcrumb_path.breadcrumb_index.nearest((matched_breadcrumbs[0].map1_breadcrumb.longitude, matched_breadcrumbs[0].map1_breadcrumb.latitude), bearing_flag+1))[bearing_flag]
bearing_difference = spatialfunclib.bearing_difference(map1_breadcrumb.bearing, map2_breadcrumb_path.breadcrumbs[closest_map2_breadcrumb_id].bearing)
if bearing_difference < bearing_limit:
matched_breadcrumbs[0].map2_breadcrumb = map2_breadcrumb_path.breadcrumbs[closest_map2_breadcrumb_id]
matched_breadcrumbs[0].distance = self._distance(matched_breadcrumbs[0].map1_breadcrumb, matched_breadcrumbs[0].map2_breadcrumb)
# sort list of matched breadcrumbs in ascending order according to distance
# Sadly, very inefficient
matched_breadcrumbs.sort(key=lambda x: x.distance)
bearing_flag = -1
else:
bearing_flag += 1
else:
# Can't find a match
map1_breadcrumb_path.delete_breadcrumb(map1_breadcrumb)
# output map1 unmatched edge value
eval_file.write(
"1000000" + "," + str(map1_breadcrumb.latitude) + "," + str(map1_breadcrumb.longitude) + "," + str(
map1_breadcrumb.latitude) + "," + str(map1_breadcrumb.longitude) + "\n")
# iterate through remaining map1 breadcrumbs
for map1_breadcrumb in map1_breadcrumb_path.breadcrumbs.values():
# output map1 unmatched edge value
eval_file.write(
"1000000" + "," + str(map1_breadcrumb.latitude) + "," + str(map1_breadcrumb.longitude) + "," + str(
map1_breadcrumb.latitude) + "," + str(map1_breadcrumb.longitude) + "\n")
#plt.scatter(map1_breadcrumb.latitude,map1_breadcrumb.longitude, c='#3FBFBF', s=2)
# iterate through remaining map2 breadcrumbs
for map2_breadcrumb in map2_breadcrumb_path.breadcrumbs.values():
# output map2 spurious edge value
eval_file.write(
"2000000" + "," + str(map2_breadcrumb.latitude) + "," + str(map2_breadcrumb.longitude) + "," + str(
map2_breadcrumb.latitude) + "," + str(map2_breadcrumb.longitude) + "\n")
#plt.scatter(map2_breadcrumb.latitude,map2_breadcrumb.longitude, c='#BF3F3F', s=2)
#eval_file.write("0,0,0,0,0\n")
# flush results to file
eval_file.flush()
def _compare_breadcrumb_paths_greedy_shortest(self, map1_breadcrumb_path, map2_breadcrumb_path, eval_file_name):
# storage for list of matched breadcrumbs
matched_breadcrumbs = []
matched = 0
# DEBUG -- output number of breadcrumbs
if (debug_mode):
print("map1 breadcrumbs: " + str(len(map1_breadcrumb_path.breadcrumbs)))
print("map2 breadcrumbs: " + str(len(map2_breadcrumb_path.breadcrumbs)))
# append results to eval file
with open_mkdir(eval_file_name, 'a+') as eval_file:
# iterate through map1 breadcrumbs, find nearest neighbor for each, and store in matched_breadcrumbs
# This computes a many-to-many matching
if (len(map2_breadcrumb_path.breadcrumbs) > 0):
for map1_breadcrumb in map1_breadcrumb_path.breadcrumbs.values():
# find closest breadcrumb in map2. Make sure there are some breadcrumbs left
closest_map2_breadcrumb_id = list(map2_breadcrumb_path.breadcrumb_index.nearest((map1_breadcrumb.longitude, map1_breadcrumb.latitude), 1))[0]
closest_map2_breadcrumb = map2_breadcrumb_path.breadcrumbs[closest_map2_breadcrumb_id]
breadcrumb_distance = self._distance(map1_breadcrumb, closest_map2_breadcrumb)
# create matched crumbs object
matched_breadcrumb = MatchedCrumbs(map1_breadcrumb, closest_map2_breadcrumb, breadcrumb_distance)
matched_breadcrumbs.append(matched_breadcrumb)
# Now filter this matching to create a 1-to-1 matching, prioritizing shortest distances
# 1. Sort list of matched breadcrumbs in ascending order according to distance
matched_breadcrumbs.sort(key=lambda x: x.distance)
# 2. Continue while there are matched breadcrumbs to be processed
while (len(matched_breadcrumbs) > 0):
# if distance between closest matched breadcrumbs is greater than the threshold
if (matched_breadcrumbs[0].distance > match_distance_threshold):
# Exit loop early. All nearest neighbor matches are too far away.
break
# if map2 breadcrumb is still available
if (matched_breadcrumbs[0].map2_breadcrumb.id in map2_breadcrumb_path.breadcrumbs.keys()):
# Fix this matching.
# remove map1 breadcrumb from path
map1_breadcrumb_path.delete_breadcrumb(matched_breadcrumbs[0].map1_breadcrumb)
# remove map2 breadcrumb from path
map2_breadcrumb_path.delete_breadcrumb(matched_breadcrumbs[0].map2_breadcrumb)
matched += 1
# output distance between breadcrumbs for evaluation output file
eval_file.write(str(matched_breadcrumbs[0].distance) + "," + str(
matched_breadcrumbs[0].map1_breadcrumb.latitude) + "," + str(
matched_breadcrumbs[0].map1_breadcrumb.longitude) + "," + str(
matched_breadcrumbs[0].map2_breadcrumb.latitude) + "," + str(
matched_breadcrumbs[0].map2_breadcrumb.longitude) + "\n")
matched_breadcrumbs.pop(0)
# If map2 breadcrumb is no longer available, find a new nearest neighbor
else:
if (len(map2_breadcrumb_path.breadcrumbs) > 0):
# find closest breadcrumb in map2.
closest_map2_breadcrumb_id = list(map2_breadcrumb_path.breadcrumb_index.nearest((matched_breadcrumbs[0].map1_breadcrumb.longitude, matched_breadcrumbs[0].map1_breadcrumb.latitude), 1))[0]
matched_breadcrumbs[0].map2_breadcrumb = map2_breadcrumb_path.breadcrumbs[closest_map2_breadcrumb_id]
matched_breadcrumbs[0].distance = self._distance(matched_breadcrumbs[0].map1_breadcrumb, matched_breadcrumbs[0].map2_breadcrumb)
# sort list of matched breadcrumbs in ascending order according to distance
# Sadly, very inefficient
matched_breadcrumbs.sort(key=lambda x: x.distance)
else:
# Can't find a match
map1_breadcrumb_path.delete_breadcrumb(map1_breadcrumb)
# output map1 unmatched edge value
eval_file.write(
"1000000" + "," + str(map1_breadcrumb.latitude) + "," + str(map1_breadcrumb.longitude) + "," + str(
map1_breadcrumb.latitude) + "," + str(map1_breadcrumb.longitude) + "\n")
# iterate through remaining map1 breadcrumbs
for map1_breadcrumb in map1_breadcrumb_path.breadcrumbs.values():
# output map1 unmatched edge value
eval_file.write(
"1000000" + "," + str(map1_breadcrumb.latitude) + "," + str(map1_breadcrumb.longitude) + "," + str(
map1_breadcrumb.latitude) + "," + str(map1_breadcrumb.longitude) + "\n")
#plt.scatter(map1_breadcrumb.latitude,map1_breadcrumb.longitude, c='#3FBFBF', s=2)
# iterate through remaining map2 breadcrumbs
for map2_breadcrumb in map2_breadcrumb_path.breadcrumbs.values():
# output map2 spurious edge value
eval_file.write(
"2000000" + "," + str(map2_breadcrumb.latitude) + "," + str(map2_breadcrumb.longitude) + "," + str(
map2_breadcrumb.latitude) + "," + str(map2_breadcrumb.longitude) + "\n")
#plt.scatter(map2_breadcrumb.latitude,map2_breadcrumb.longitude, c='#BF3F3F', s=2)
#eval_file.write("0,0,0,0,0\n")
# flush results to file
eval_file.flush()
def _compare_breadcrumb_paths_greedy(self, map1_breadcrumb_path, map2_breadcrumb_path, eval_file_name):
# storage for list of matched breadcrumbs
matched_breadcrumbs = []
matched = 0
# DEBUG -- output number of breadcrumbs
if (debug_mode):
print("map1 breadcrumbs: " + str(len(map1_breadcrumb_path.breadcrumbs)))
print("map2 breadcrumbs: " + str(len(map2_breadcrumb_path.breadcrumbs)))
# append results to eval file
with open_mkdir(eval_file_name, 'a+') as eval_file:
# iterate through map1 breadcrumbs
map1_breadcrumb = None
while len(map1_breadcrumb_path.breadcrumbs.values())>0:
map1_breadcrumb = list(map1_breadcrumb_path.breadcrumbs.items())[0][1]
# Are there breadcrumbs left to map to?
if(len(map2_breadcrumb_path.breadcrumbs) == 0):
break
# find closest breadcrumb in map2. Make sure there are some breadcrumbs left
closest_map2_breadcrumb_id = list(map2_breadcrumb_path.breadcrumb_index.nearest((map1_breadcrumb.longitude, map1_breadcrumb.latitude), 1))[0]
closest_map2_breadcrumb = map2_breadcrumb_path.breadcrumbs[closest_map2_breadcrumb_id]
breadcrumb_distance = self._distance(map1_breadcrumb, closest_map2_breadcrumb)
# Nearest neighbor is too far away. Can't find a match
if breadcrumb_distance > match_distance_threshold:
map1_breadcrumb_path.delete_breadcrumb(map1_breadcrumb)
# output map1 unmatched edge value
eval_file.write(
"1000000" + "," + str(map1_breadcrumb.latitude) + "," + str(map1_breadcrumb.longitude) + "," + str(
map1_breadcrumb.latitude) + "," + str(map1_breadcrumb.longitude) + "\n")
else:
# create matched crumbs object
# In this method, matched_breadcrumbs only contains one-to-one matched breadcrumbs
matched_breadcrumb = MatchedCrumbs(map1_breadcrumb, closest_map2_breadcrumb, breadcrumb_distance)
matched_breadcrumbs.append(matched_breadcrumb)
map1_breadcrumb_path.delete_breadcrumb(map1_breadcrumb)
map2_breadcrumb_path.delete_breadcrumb(closest_map2_breadcrumb)
matched += 1
# output distance between breadcrumbs for evaluation output file
eval_file.write(str(matched_breadcrumb.distance) + "," + str(
matched_breadcrumb.map1_breadcrumb.latitude) + "," + str(
matched_breadcrumb.map1_breadcrumb.longitude) + "," + str(
matched_breadcrumb.map2_breadcrumb.latitude) + "," + str(
matched_breadcrumb.map2_breadcrumb.longitude) + "\n")
# iterate through remaining map1 breadcrumbs
for map1_breadcrumb in map1_breadcrumb_path.breadcrumbs.values():
# output map1 unmatched edge value
eval_file.write(
"1000000" + "," + str(map1_breadcrumb.latitude) + "," + str(map1_breadcrumb.longitude) + "," + str(
map1_breadcrumb.latitude) + "," + str(map1_breadcrumb.longitude) + "\n")
#plt.scatter(map1_breadcrumb.latitude,map1_breadcrumb.longitude, c='#3FBFBF', s=2)
# iterate through remaining map2 breadcrumbs
for map2_breadcrumb in map2_breadcrumb_path.breadcrumbs.values():
# output map2 spurious edge value
eval_file.write(
"2000000" + "," + str(map2_breadcrumb.latitude) + "," + str(map2_breadcrumb.longitude) + "," + str(
map2_breadcrumb.latitude) + "," + str(map2_breadcrumb.longitude) + "\n")
#plt.scatter(map2_breadcrumb.latitude,map2_breadcrumb.longitude, c='#BF3F3F', s=2)
#eval_file.write("0,0,0,0,0\n")
# flush results to file
eval_file.flush()
def _compare_breadcrumb_paths(self, map1_breadcrumb_path, map2_breadcrumb_path, eval_file_name):
# storage for list of matched breadcrumbs
matched_breadcrumbs = []
matched = 0
# DEBUG -- output number of breadcrumbs
if (debug_mode):
print("map1 breadcrumbs: " + str(len(map1_breadcrumb_path.breadcrumbs)))
print("map2 breadcrumbs: " + str(len(map2_breadcrumb_path.breadcrumbs)))
# append results to eval file
with open_mkdir(eval_file_name, 'a+') as eval_file:
# if there are some map2 breadcrumbs
if (len(map2_breadcrumb_path.breadcrumbs) > 0):
# iterate through map1 breadcrumbs
for map1_breadcrumb in map1_breadcrumb_path.breadcrumbs.values():
# find closest breadcrumb in map2
# closest_map2_breadcrumb = map2_breadcrumb_path.breadcrumbs[list(map2_breadcrumb_path.breadcrumb_index.nearest((map1_breadcrumb.longitude, map1_breadcrumb.latitude), 1))[0]]
# find closest breadcrumb ids in map2
closest_map2_breadcrumb_ids = map2_breadcrumb_path.breadcrumb_index.nearest(
(map1_breadcrumb.longitude, map1_breadcrumb.latitude), 10)
# iterate through all breadcrumb ids
for map2_breadcrumb_id in closest_map2_breadcrumb_ids:
# grab map2 breadcrumb
map2_breadcrumb = map2_breadcrumb_path.breadcrumbs[map2_breadcrumb_id]
# compute bearing difference between breadcrumbs
bearing_difference = spatialfunclib.bearing_difference(map1_breadcrumb.bearing,
map2_breadcrumb.bearing)
# if bearing difference is less than 45 degrees
if (bearing_difference < bearing_limit):
# find distance to breadcrumb in map2
map2_breadcrumb_distance = self._distance(map1_breadcrumb, map2_breadcrumb)
# create matched crumbs object
matched_breadcrumbs.append(
MatchedCrumbs(map1_breadcrumb, map2_breadcrumb, map2_breadcrumb_distance))
# exit loop
break
else:
continue
# sort list of matched breadcrumbs in ascending order according to distance
matched_breadcrumbs.sort(key=lambda x: x.distance)
# continue while there are matched breadcrumbs to be processed
while (len(matched_breadcrumbs) > 0):
# if distance between closest matched breadcrumbs is greater than the threshold
if (matched_breadcrumbs[0].distance > match_distance_threshold):
# exit loop early
break
# if map2 breadcrumb is still available
if (matched_breadcrumbs[0].map2_breadcrumb.id in map2_breadcrumb_path.breadcrumbs.keys()):
# remove map1 breadcrumb from path
del map1_breadcrumb_path.breadcrumbs[matched_breadcrumbs[0].map1_breadcrumb.id]
# remove map2 breadcrumb from path
del map2_breadcrumb_path.breadcrumbs[matched_breadcrumbs[0].map2_breadcrumb.id]
matched += 1
# output distance between breadcrumbs for evaluation output file
eval_file.write(str(matched_breadcrumbs[0].distance) + "," + str(
matched_breadcrumbs[0].map1_breadcrumb.latitude) + "," + str(
matched_breadcrumbs[0].map1_breadcrumb.longitude) + "," + str(
matched_breadcrumbs[0].map2_breadcrumb.latitude) + "," + str(
matched_breadcrumbs[0].map2_breadcrumb.longitude) + "\n")
#plt.scatter(matched_breadcrumbs[0].map1_breadcrumb.latitude,matched_breadcrumbs[0].map1_breadcrumb.longitude, c='blue', s=2)
#plt.scatter(matched_breadcrumbs[0].map2_breadcrumb.latitude,matched_breadcrumbs[0].map2_breadcrumb.longitude, c='red', s=2)
#plt.plot([matched_breadcrumbs[0].map1_breadcrumb.latitude,matched_breadcrumbs[0].map2_breadcrumb.latitude],[matched_breadcrumbs[0].map1_breadcrumb.longitude,matched_breadcrumbs[0].map2_breadcrumb.longitude], c='green')
# remove matched breadcrumbs from list
matched_breadcrumbs.pop(0)
# else, if map2 breadcrumb is no longer available
else:
# set map2 matched breadcrumb to None
matched_breadcrumbs[0].map2_breadcrumb = None
# get list of all_closest breadcrumbs in map2
all_closest_map2_breadcrumbs = list(map2_breadcrumb_path.breadcrumb_index.nearest(
(matched_breadcrumbs[0].map1_breadcrumb.longitude,
matched_breadcrumbs[0].map1_breadcrumb.latitude),
10))
# iterate through list of all closest breadcrumbs in map2
for map2_breadcrumb_id in all_closest_map2_breadcrumbs:
# if map2 breadcrumb is still available
if (map2_breadcrumb_id in map2_breadcrumb_path.breadcrumbs.keys()):
# grab map2 breadcrumb
map2_breadcrumb = map2_breadcrumb_path.breadcrumbs[map2_breadcrumb_id]
# compute bearing difference between breadcrumbs
bearing_difference = spatialfunclib.bearing_difference(
matched_breadcrumbs[0].map1_breadcrumb.bearing, map2_breadcrumb.bearing)
# if bearing difference is less than 45 degrees
if (bearing_difference < bearing_limit):
# update map2 breadcrumb in matched crumbs object
matched_breadcrumbs[0].map2_breadcrumb = map2_breadcrumb
# update distance in matched crumbs object
matched_breadcrumbs[0].distance = self._distance(matched_breadcrumbs[0].map1_breadcrumb,
matched_breadcrumbs[0].map2_breadcrumb)
# break out of loop
break
# if there were no map2 breadcrumbs to match with
if (matched_breadcrumbs[0].map2_breadcrumb is None):
# remove matched breadcrumbs from list
matched_breadcrumbs.pop(0)
# otherwise, ...
else:
# sort list of matched breadcrumbs
matched_breadcrumbs.sort(key=lambda x: x.distance)
# iterate through remaining map1 breadcrumbs
for map1_breadcrumb in map1_breadcrumb_path.breadcrumbs.values():
# output map1 unmatched edge value
eval_file.write(
"1000000" + "," + str(map1_breadcrumb.latitude) + "," + str(map1_breadcrumb.longitude) + "," + str(
map1_breadcrumb.latitude) + "," + str(map1_breadcrumb.longitude) + "\n")
#plt.scatter(map1_breadcrumb.latitude,map1_breadcrumb.longitude, c='#3FBFBF', s=2)
# iterate through remaining map2 breadcrumbs
for map2_breadcrumb in map2_breadcrumb_path.breadcrumbs.values():
# output map2 spurious edge value
eval_file.write(
"2000000" + "," + str(map2_breadcrumb.latitude) + "," + str(map2_breadcrumb.longitude) + "," + str(
map2_breadcrumb.latitude) + "," + str(map2_breadcrumb.longitude) + "\n")
#plt.scatter(map2_breadcrumb.latitude,map2_breadcrumb.longitude, c='#BF3F3F', s=2)
#eval_file.write("0,0,0,0,0\n")
# flush results to file
eval_file.flush()
def _get_breadcrumb_path(self, curr_map, root_location, breadcrumb_edges, valid_edges, valid_edge_pairs):
# iterate through all edges in the current map
for edge in curr_map.edges.values():
# intialize breadcrumb storage for edge
edge.breadcrumbs = []
# create storage for breadcrumb path
breadcrumb_path = BreadcrumbPath()
# initialize breadcrumb id
breadcrumb_id = 0
# iterate through all breadcrumb edges
for breadcrumb_edge in breadcrumb_edges:
# if valid edges list is supplied, and the current breadcrumb edge is not on it
if ((valid_edges is not None) and (breadcrumb_edge[0] not in valid_edges)):
continue
# create breadcrumb path starting with current breadcrumb edge
(breadcrumb_path, breadcrumb_id) = self._create_breadcrumb_path(curr_map, root_location, breadcrumb_edge[0],
breadcrumb_edge[1], valid_edge_pairs,
breadcrumb_path, breadcrumb_id)
# return breadcrumb path
return breadcrumb_path
def _create_breadcrumb_path(self, curr_map, root_location, source_edge, source_location, valid_edge_pairs, breadcrumb_path, breadcrumb_id):
# initialize start distance for breadcrumbing
#source_edge.start_distance = self._distance_coords(source_edge.in_node.latitude, source_edge.in_node.longitude,source_location[0], source_location[1])
distance_to_source_location = self._distance_coords(source_edge.in_node.latitude, source_edge.in_node.longitude, source_location[0], source_location[1])
if(distance_to_source_location > breadcrumb_max_distance):
source_edge.start_distance = distance_to_source_location - breadcrumb_max_distance
else:
source_edge.start_distance = 0
#source_edge.start_distance = 0
# initialize maximum distance for breadcrumbing
source_edge.max_distance = 0.0
# create breadth-first edge queue for searching map
bfs_queue = []
# enqueue source edge
bfs_queue.append(source_edge)
# append edges adjacent to the beginning of the source edge
reciprocal_edge = curr_map.edge_lookup_table[(source_edge.out_node, source_edge.in_node)]
dist_from_root = self._distance_coords(root_location[0], root_location[1], reciprocal_edge.out_node.latitude, reciprocal_edge.out_node.longitude)
if dist_from_root < breadcrumb_max_distance:
for out_edge in self._find_valid_out_edges(curr_map, reciprocal_edge):
out_edge.start_distance = breadcrumb_interval
out_edge.max_distance = 0.0
bfs_queue.append(out_edge)
# while the edge queue is not empty
while (len(bfs_queue) > 0):
# dequeue first edge in the queue
curr_edge = bfs_queue.pop(0)
# if the current edge has no length
if (curr_edge.length == 0.0):
if ((valid_edge_pairs is not None) and (curr_edge in valid_edge_pairs)):
for out_edge in valid_edge_pairs[curr_edge]:
if (out_edge not in bfs_queue):
out_edge.start_distance = curr_edge.start_distance
out_edge.max_distance = curr_edge.max_distance
bfs_queue.append(out_edge)
else:
for out_edge in self._find_valid_out_edges(curr_map, curr_edge):
if (out_edge not in bfs_queue):
out_edge.start_distance = curr_edge.start_distance
out_edge.max_distance = curr_edge.max_distance
bfs_queue.append(out_edge)
# continue to next edge in queue
continue
# determine breadcrumb start location
#breadcrumb_start_location = self._point_along_line(curr_edge.in_node, curr_edge.out_node,(curr_edge.start_distance / curr_edge.length))
# see if there are any breadcrumbs nearby on the current edge
#closest_breadcrumb_distance = self._find_closest_breadcrumb_distance(curr_edge, breadcrumb_start_location)
# if the closest breadcrumb is further than (breadcrumb_interval + 1.0 meters) away
#if (closest_breadcrumb_distance > (breadcrumb_interval + 1.0)):
#if (len(curr_edge.breadcrumbs) == 0):
if (not curr_edge.visited):
curr_edge.visited = True
# grab reciprocal edge
reciprocal_edge = curr_map.edge_lookup_table[(curr_edge.out_node, curr_edge.in_node)]
reciprocal_edge.visited = True
# drop breadcrumbs along current edge
(breadcrumb_id, breadcrumb_start_distance,
breadcrumb_max_distance_from_source) = self._drop_breadcrumbs_along_edge(curr_edge, breadcrumb_path,
breadcrumb_id, root_location)
# if we should breadcrumb the successor edges
if (breadcrumb_start_distance is not None):
if ((valid_edge_pairs is not None) and (curr_edge in valid_edge_pairs)):
for out_edge in valid_edge_pairs[curr_edge]:
if (out_edge not in bfs_queue):
out_edge.start_distance = breadcrumb_start_distance
out_edge.max_distance = breadcrumb_max_distance_from_source
bfs_queue.append(out_edge)
else:
for out_edge in self._find_valid_out_edges(curr_map, curr_edge):
if (out_edge not in bfs_queue):
out_edge.start_distance = breadcrumb_start_distance
out_edge.max_distance = breadcrumb_max_distance_from_source
bfs_queue.append(out_edge)
# return breadcrumb path and id
return (breadcrumb_path, breadcrumb_id)
def _find_closest_breadcrumb_distance(self, edge, location):
# storage for closest breadcrumb
closest_breadcrumb_distance = float('infinity')
# if the edge has breadcrumbs
if (len(edge.breadcrumbs) > 0):
# iterate through all breadcrumbs
for curr_breadcrumb in edge.breadcrumbs:
# compute distance to current breadcrumb
curr_breadcrumb_distance = self._distance_coords(location[0], location[1], curr_breadcrumb.latitude,