Map.cpp
Go to the documentation of this file.
00001 // Copyright (c) 2013-2014 by Wayne C. Gramlich.  All rights reserved.
00002 
00009 
00010 typedef struct Map__Struct *Map_Doxygen_Fake_Out;
00011 
00012 #include <assert.h>
00013 #include <angles/angles.h>
00014 
00015 #include "Arc.hpp"
00016 #include "CV.hpp"
00017 #include "Camera_Tag.hpp"
00018 #include "File.hpp"
00019 #include "Location.hpp"
00020 #include "Map.hpp"
00021 #include "Tag.hpp"
00022 
00023 // *Map* routines:
00024 
00033 
00034 void Map__arc_announce(Map map,
00035   Arc *arc, CV_Image image, unsigned int sequence_number) {
00036    Tag *from_tag = arc->from_tag;
00037    Tag *to_tag = arc->to_tag;
00038    map->arc_announce_routine(map->announce_object,
00039      from_tag->id, from_tag->x, from_tag->y, from_tag->z,
00040      to_tag->id, to_tag->x, to_tag->y, to_tag->z,
00041      arc->goodness, arc->in_tree);
00042    Map__image_log(map, image, sequence_number);
00043 }
00044 
00050 
00051 void Map__arc_append(Map map, Arc *arc) {
00052     map->all_arcs.push_back(arc);
00053     map->changes_count += 1;
00054     map->is_changed = (bool)1;
00055     map->is_saved = (bool)0;
00056 }
00057 
00066 
00067 Arc *Map__arc_lookup(Map map, Tag *from_tag, Tag *to_tag) {
00068     // Make sure that *from_tag* has the lower id:
00069     if (from_tag->id > to_tag->id) {
00070         Tag *temporary_tag = from_tag;
00071         from_tag = to_tag;
00072         to_tag = temporary_tag;
00073     }
00074 
00075     // See whether or not an *Arc* with these two tags preexists:
00076     std::pair<unsigned int, unsigned int> id(from_tag->id, to_tag->id);
00077     Arc *arc;
00078     if( map->arcs_.count(id) == 0 ) {
00079         // No preexisting *Arc*; create one:
00080         arc = new Arc(from_tag, 0.0, 0.0, to_tag, 0.0, 123456789.0);
00081         map->arcs_[id] = arc;
00082     } else {
00083         arc = map->arcs_[id];
00084     }
00085     return arc;
00086 }
00087 
00098 
00099 unsigned int Map__arc_update(Map map, CameraTag *camera_from, CameraTag *camera_to,
00100   CV_Image image, unsigned int sequence_number) {
00101     // Get the *width* and *height*:
00102     int rows = CV_Image__height_get(image);
00103     int columns = CV_Image__width_get(image);
00104     double height = (double)rows;
00105     double width = (double)columns;
00106 
00107     // Compute some constants:
00108     double half_width = width / 2.0;
00109     double half_height = height / 2.0;
00110     double pi = 3.14159265358979323846264;
00111     double r2d = 180.0 / pi;
00112 
00113     // Extract some field values from *camera_from*:
00114     Tag *from_tag = camera_from->tag;
00115     double camera_from_twist = camera_from->twist;
00116     double camera_from_x = camera_from->x;
00117     double camera_from_y = camera_from->y;
00118 
00119     // Extract some values from *from_tag*:
00120     Tag *to_tag = camera_to->tag;
00121     double camera_to_twist = camera_to->twist;
00122     double camera_to_x = camera_to->x;
00123     double camera_to_y = camera_to->y;
00124 
00125     // Find associated *Arc* that contains *from_tag* and *to_tag*:
00126     Arc *arc = Map__arc_lookup(map, from_tag, to_tag);
00127 
00128     // Compute the polar distance (in pixels) and angle from the camera
00129     // center to the *from_tag* center:
00130     double camera_from_dx = camera_from->x - half_width;
00131     double camera_from_dy = camera_from->y - half_height;
00132     double camera_from_polar_distance = hypot(camera_from_dx, camera_from_dy);
00133     double camera_from_polar_angle = atan2(camera_from_dy, camera_from_dx);
00134 
00135     // Compute the polar_distance (in pixels) and angle from the camera
00136     // center to the *to_tag* center:
00137     double camera_to_dx = camera_to_x - half_width;
00138     double camera_to_dy = camera_to_y - half_height;
00139     double camera_to_polar_distance = hypot(camera_to_dx, camera_to_dy);
00140     double camera_to_polar_angle = atan2(camera_to_dy, camera_to_dx);
00141 
00142     // To minimize camera distortion effects, we want to use images where
00143     // *from* and *to* are about equidistant from the image center.  Thus,
00144     // we want to minimum the absolute value of the distance difference:
00145     double goodness = std::abs(camera_from_polar_distance - camera_to_polar_distance);
00146 
00147     // Now see if the new *goodness* is better than the previous one:
00148     //File__format(stderr,
00149     //  "goodness=%.4f arc_goodness=%.4f\n", goodness, arc->goodness);
00150     unsigned int changed = 0;
00151     if (goodness < arc->goodness) {
00152         // We have a better *goodness* metric, compute the new values to
00153         // load into *arc*:
00154 
00155         // Get two *distance_from_pixel* values which may not be
00156         // the same because the fiducials are at different heights:
00157         double from_distance_per_pixel = 
00158           from_tag->world_diagonal / from_tag->diagonal;
00159         double to_distance_per_pixel = 
00160           to_tag->world_diagonal / to_tag->diagonal;
00161 
00162         // Now compute floor to/from X/Y's that coorrespond to the (X,Y)
00163         // projection of each tag center onto the floor as if the camera
00164         // is located at the floor origin:
00165         double from_floor_x = from_distance_per_pixel *
00166           camera_from_polar_distance * cos(camera_from_polar_angle);
00167         double from_floor_y = from_distance_per_pixel *
00168           camera_from_polar_distance * sin(camera_from_polar_angle);
00169         double to_floor_x = to_distance_per_pixel *
00170           camera_to_polar_distance * cos(camera_to_polar_angle);
00171         double to_floor_y = to_distance_per_pixel *
00172           camera_to_polar_distance * sin(camera_to_polar_angle);
00173 
00174         // Now we can compute the floor distance between the two two
00175         // projected points:
00176         double floor_dx = from_floor_x - to_floor_x;
00177         double floor_dy = from_floor_y - to_floor_y;
00178         double floor_distance = hypot(floor_dx, floor_dy);
00179 
00180         // Compute *angle* to line segment connecting both tags:
00181         double camera_dx = camera_to_x - camera_from_x;
00182         double camera_dy = camera_to_y - camera_from_y;
00183          double arc_angle = atan2(camera_dy, camera_dx);
00184         double from_twist =
00185           angles::normalize_angle(camera_from_twist - arc_angle);
00186         double to_twist =
00187           angles::normalize_angle(camera_to_twist + pi - arc_angle);
00188 
00189         // OLD: Compute the distance between *origin* and *to*:
00190         //double distance_per_pixel = from_tag->distance_per_pixel;
00191         //double camera_distance =
00192         //  double__square_root(camera_dx * camera_dx + camera_dy * camera_dy);
00193         //double old_floor_distance = camera_distance * distance_per_pixel;
00194         //File__format(stderr, "floor_distance=%.2f old_floor_distance=%.2f\n",
00195         //  floor_distance, old_floor_distance);
00196 
00197         //File__format(stderr,
00198         //  "Map__arc_update: camera_from_twist=%.2f camera_to_twist=%.2f\n",
00199          //  camera_from_twist * r2d, camera_to_twist * r2d);
00200         //File__format(stderr,
00201         //  "Map__arc_update: arc_angle=%.2f from_twist=%.2f to_twist=%.2f\n",
00202         //  arc_angle * r2d, from_twist * r2d, to_twist * r2d);
00203 
00204         // Finally, upate *arc*:
00205         arc->update(from_twist, floor_distance, to_twist, goodness);
00206         map->changes_count += 1;
00207         map->is_changed = (bool)1;
00208         map->is_saved = (bool)0;
00209 
00210         // Let interested parties know that *arc* has been updated:
00211         Map__arc_announce(map, arc, image, sequence_number);
00212 
00213         changed = 1;
00214     }
00215     return changed;
00216 }
00217 
00227 
00228 bool Map__equals(Map map1, Map map2) {
00229     // First make sure all of the *Tag*'s match up:
00230     unsigned int all_tags1_size = map1->all_tags.size();
00231     unsigned int all_tags2_size = map2->all_tags.size();
00232     if (all_tags1_size == all_tags2_size) {
00233         // Visit each *Tag*:
00234         for (unsigned int index = 0; index < all_tags1_size; index++) {
00235             Tag *tag1 = map1->all_tags[index];
00236             Tag *tag2 = map2->all_tags[index];
00237             if (!Tag::equal(tag1, tag2)) {
00238               return false;
00239             }
00240         }
00241     } else {
00242         return false;
00243     }
00244 
00245     // Second make sure all of the *Arc*'s match up:
00246     unsigned int all_arcs1_size = map1->all_arcs.size();
00247     unsigned int all_arcs2_size = map2->all_arcs.size();
00248     if (all_arcs1_size == all_arcs2_size) {
00249         // Visit each *Arc*:
00250         for (unsigned int index = 0; index < all_arcs1_size; index++) {
00251             Arc * arc1 = map1->all_arcs[index];
00252             Arc * arc2 = map2->all_arcs[index];
00253             if( !Arc::equal(arc1, arc2)) {
00254               return false;
00255             }
00256         }
00257     } else {
00258       return false;
00259     }
00260     return true;
00261 }
00262 
00275 
00276 Map Map__create(String_Const file_path, String_Const file_base,
00277   void *announce_object, Fiducials_Arc_Announce_Routine arc_announce_routine,
00278   Fiducials_Tag_Announce_Routine tag_announce_routine,
00279   String_Const tag_heights_file_name, String_Const from) {
00280     // Create and fill in *map*:
00281     Map map = Memory__new(Map, from);
00282     map = new(map) Map__Struct();
00283     map->arc_announce_routine = arc_announce_routine;
00284     map->announce_object = announce_object;
00285     map->changes_count = 0;
00286     map->file_base = file_base;
00287     map->file_path = file_path;
00288     map->is_changed = (bool)0;
00289     map->is_saved = (bool)1;
00290     map->image_log = (bool)0;
00291     map->tag_announce_routine = tag_announce_routine;
00292     map->temporary_arc = new Arc();
00293     map->visit = 0;
00294 
00295     // Read in the contents of *map_heights_file_name* into *map*:
00296     Map__tag_heights_xml_read(map, tag_heights_file_name);
00297 
00298     // Restore *map* from "*map_path*/*map_base*{0,1}.xml".
00299     // We try to read "...1.xml" first, followed by "...0.xml":
00300     String full_map_file_name =
00301       String__format("%s/%s1.xml", file_path, file_base);
00302     File in_file = File__open(full_map_file_name, "r");
00303     if (in_file == (File)0) {
00304         // We failed to open "...1.xml"; now try "...0.xml":
00305         String__free(full_map_file_name);
00306         String full_map_file_name =
00307           String__format("%s/%s0.xml", file_path, file_base);
00308         in_file = File__open(full_map_file_name, "r");
00309         if (in_file != (File)0) {
00310             // We opened "...0.xml", read it in:
00311             Map__restore(map, in_file);
00312             File__close(in_file);
00313         }
00314     } else {
00315         // We opened "...1.xml", read it in:
00316         printf("Reading %s\n", full_map_file_name);
00317         Map__restore(map, in_file);
00318         File__close(in_file);
00319     }
00320     return map;
00321 }
00322 
00327 
00328 void Map__free(Map map) {
00329     // Save the map:
00330     Map__save(map);
00331 
00332     // Release all the *Arc*'s:
00333     unsigned int arcs_size = map->all_arcs.size();
00334     for (unsigned int index = 0; index < arcs_size; index++) {
00335         delete map->all_arcs[index];
00336     }
00337     delete map->temporary_arc;
00338 
00339     // Release all the *Tag*'s:
00340     unsigned int tags_size = map->all_tags.size();
00341     for (unsigned int index = 0; index < tags_size; index++) {
00342         delete map->all_tags[index];
00343     }
00344 
00345     // Release all the *Tag_Height*'s:
00346     unsigned int tag_heights_size = map->tag_heights.size();
00347     for (unsigned int index = 0; index < tag_heights_size; index++) {
00348         delete map->tag_heights[index];
00349     }
00350 
00351     Memory__free((Memory)map);
00352 }
00353 
00359 
00360 static int last_sequence_number = 0xffffffff;
00361 
00362 void Map__image_log(Map map, CV_Image image, unsigned int sequence_number) {
00363     if (image != (CV_Image)0 && map->image_log &&
00364       sequence_number != last_sequence_number) {
00365         // Log the image here:
00366         String file_name = String__format("log%05d.tga", sequence_number);
00367         CV_Image__tga_write(image, file_name);
00368         last_sequence_number = sequence_number;
00369     }
00370 }
00371 
00378 
00379 void Map__restore(Map map, File in_file) {
00380     // Read in Map XML tag '<Map Tags_Count="xx" Arcs_Count="xx">' :
00381     File__tag_match(in_file, "Map");
00382     unsigned int all_tags_size =
00383       (unsigned int)File__integer_attribute_read(in_file, "Tags_Count");
00384     unsigned int all_arcs_size =
00385       (unsigned int)File__integer_attribute_read(in_file, "Arcs_Count");
00386     File__string_match(in_file, ">\n");
00387 
00388     // Read in the *all_tags_size* *Tag* objects:
00389     for (unsigned int index = 0; index < all_tags_size; index++) {
00390         Tag * tag = Tag::read(in_file, map);
00391 
00392         map->tag_announce_routine(map->announce_object,
00393         tag->id, tag->x, tag->y, tag->z, tag->twist,
00394         tag->diagonal, tag->world_diagonal/tag->diagonal,
00395         0, tag->hop_count);
00396     }
00397 
00398     // Read in the *all_arcs_size* *Arc* objects:
00399     for (unsigned int index = 0; index < all_arcs_size; index++) {
00400         Arc * arc = Arc::read(in_file, map);
00401     }
00402 
00403     // Process the final Map XML tag "</MAP>":
00404     File__tag_match(in_file, "/Map");
00405     File__string_match(in_file, ">\n");
00406 
00407     // Do some final checks:
00408     assert (map->all_arcs.size() == all_arcs_size);
00409     assert (map->all_tags.size() == all_tags_size);
00410 }
00411 
00416 
00417 void Map__save(Map map) {
00418       File__format(stderr, "**********Map__save************\n");
00419       if (!map->is_saved) {
00420         String full_map_file_name =
00421           String__format("%s/%s", map->file_path, map->file_base);
00422         File out_file = File__open(full_map_file_name, "w");
00423         assert (out_file != (File)0);
00424         String__free(full_map_file_name);
00425         Map__write(map, out_file);
00426         File__close(out_file);
00427         map->is_saved = (bool)1;
00428     }
00429 }
00430 
00436 
00437 void Map__sort(Map map) {
00438     std::sort(map->all_tags.begin(), map->all_tags.end(), Tag::less);
00439     std::sort(map->all_arcs.begin(), map->all_arcs.end(), Arc::less);
00440 }
00441 
00448 
00449 void Map__svg_write(Map map, String_Const svg_base_name, 
00450     std::vector<Location*> &locations) {
00451     // Figure out how many *Arc*'s and *Tag*'s we have:
00452     unsigned int all_tags_size = map->all_tags.size();
00453     unsigned int all_arcs_size = map->all_arcs.size();
00454 
00455     // Compute the *bounding_box*:
00456     BoundingBox * bounding_box = new BoundingBox();
00457     for (unsigned int index = 0; index < all_tags_size; index++) {
00458         Tag * tag = map->all_tags[index];
00459         tag->bounding_box_update(bounding_box);
00460     }
00461 
00462     // Open the Scalable Vector Graphics file:
00463     SVG * svg = new SVG(svg_base_name, 8.0, 10.5, 1.0, 1.0, "in");
00464 
00465     svg->cartesian_scale(8.0, 10.5, bounding_box);
00466 
00467     // Draw the X/Y axes:
00468     String_Const color = "cyan";
00469     svg->line(bounding_box->min_x(), 0.0, bounding_box->max_x(), 0.0, color);
00470     svg->line(0.0, bounding_box->min_y(), 0.0, bounding_box->max_y(), color);
00471 
00472     // Output each *tag in *all_tags*:
00473     double world_diagonal = 0.1;
00474     for (unsigned int index = 0; index < all_tags_size; index++) {
00475         Tag * tag = map->all_tags[index];
00476         world_diagonal = tag->world_diagonal;
00477         tag->svg_write(svg);
00478     }
00479 
00480     // Output each *tag in *all_tags*:
00481     for (unsigned int index = 0; index < all_arcs_size; index++) {
00482         Arc *arc = map->all_arcs[index];
00483         arc->svg_write(svg);
00484         // publish rviz marker here
00485 
00486     }
00487 
00488     unsigned int locations_size = locations.size();
00489     double last_x = 0.0;
00490     double last_y = 0.0;
00491     for (unsigned int index = 0; index < locations_size; index++) {
00492         Location * location = locations[index];
00493         double x = location->x;
00494         double y = location->y;
00495         double bearing = location->bearing;
00496         //File__format(stderr, "Location[%d]: id:%d x:%f y:%f bearing:%f\n",
00497         //  index, location->id, x, y, bearing * 180 / 3.1415926);
00498 
00499         // Draw a triangle that shows the bearing:
00500         double k1 = world_diagonal / 2.0;
00501         double k2 = k1 / 2.0;
00502         double angle = 3.14159 * 0.75;
00503         double x0 = x + k1 * cos(bearing);
00504         double y0 = y + k1 * sin(bearing);
00505         double x1 = x + k2 * cos(bearing + angle);
00506         double y1 = y + k2 * sin(bearing + angle);
00507         double x2 = x + k2 * cos(bearing - angle);
00508         double y2 = y + k2 * sin(bearing - angle);
00509         svg->line(x0, y0, x1, y1, "black");
00510         svg->line(x1, y1, x2, y2, "black");
00511         svg->line(x2, y2, x0, y0, "black");
00512 
00513         // Draw a line that connects the centers of the triangles:
00514         if (index > 0) {
00515             svg->line(last_x, last_y, x, y, "purple");
00516         }
00517         last_x = x;
00518         last_y = y;
00519     }
00520 
00521     // Close *svg*:
00522     delete svg;
00523 
00524     delete bounding_box;
00525 }
00526 
00536 
00537 void Map__tag_announce(Map map,
00538   Tag * tag, bool visible, CV_Image image, unsigned int sequence_number) {
00539     map->tag_announce_routine(map->announce_object,
00540       tag->id, tag->x, tag->y, tag->z, tag->twist,
00541       tag->diagonal, tag->world_diagonal/tag->diagonal,
00542       visible, tag->hop_count);
00543     if (visible) {
00544         //Map__image_log(map, image, sequence_number);
00545     }
00546 }
00547 
00557 
00558 TagHeight * Map__tag_height_lookup(Map map, unsigned int id) {
00559     //double distance_per_pixel = 0.0;
00560     TagHeight * tag_height = NULL;
00561     unsigned int size = map->tag_heights.size();
00562     for (unsigned int index = 0; index < size; index++) {
00563         tag_height = map->tag_heights[index];
00564         if (tag_height->first_id <= id && id <= tag_height->last_id) {
00565             //distance_per_pixel = tag_height->distance_per_pixel;
00566           
00567             break;
00568         }
00569         tag_height = NULL;
00570     }
00571     return tag_height;
00572 }
00573 
00580 
00581 void Map__tag_heights_xml_read(Map map, String_Const tag_heights_file_name) {
00582     // Open *tag_height_file_name* for reading:
00583     File xml_in_file = File__open(tag_heights_file_name, "r");
00584     if (xml_in_file == (File)0) {
00585         File__format(stderr, "Could not open '%s'\n", tag_heights_file_name);
00586         assert(0);
00587     }
00588 
00589     // Read in Map XML tag '<Map_Tag_Heights Count="xx">' :
00590     File__tag_match(xml_in_file, "Map_Tag_Heights");
00591     unsigned int count =
00592       (unsigned int)File__integer_attribute_read(xml_in_file, "Count");
00593     File__string_match(xml_in_file, ">\n");
00594 
00595     // Read in the *count* *Tag_Height* objects into *tag_heights*:
00596     for (unsigned int index = 0; index < count; index++) {
00597         TagHeight * tag_height = TagHeight::xml_read(xml_in_file);
00598         map->tag_heights.push_back(tag_height);
00599     }
00600 
00601     // Process the final Map XML tag "</Map_Tag_Heights>":
00602     File__tag_match(xml_in_file, "/Map_Tag_Heights");
00603     File__string_match(xml_in_file, ">\n");
00604 
00605     // Close out *xml_in_file*:
00606     File__close(xml_in_file);
00607 
00608     // Sort *tag_heights*:
00609     std::sort(map->tag_heights.begin(), map->tag_heights.end(),
00610         TagHeight::less);
00611 }
00612 
00621 
00622 Tag * Map__tag_lookup(Map map, unsigned int tag_id) {
00623     if( map->tags_.count(tag_id) == 0 ) {
00624         Tag * tag = new Tag(tag_id, map);
00625         map->tags_[tag_id] = tag;
00626         map->all_tags.push_back(tag);
00627         map->changes_count += 1;
00628         map->is_changed = (bool)1;
00629         map->is_saved = (bool)0;
00630     }
00631     return map->tags_[tag_id];
00632 }
00633 
00639 
00640 void Map__write(Map map, File out_file) {
00641     // Figure out how many *Arc*'s and *Tag*'s we have:
00642     unsigned int all_tags_size = map->all_tags.size();
00643     unsigned int all_arcs_size = map->all_arcs.size();
00644 
00645     // Output <Map ...> tag:
00646     File__format(out_file, "<Map");
00647     File__format(out_file, " Tags_Count=\"%d\"", all_tags_size);
00648     File__format(out_file, " Arcs_Count=\"%d\"", all_arcs_size);
00649     File__format(out_file, ">\n");
00650 
00651     // Put the tags out in sorted order:
00652     Map__sort(map);
00653 
00654     // Output each *tag in *all_tags*:
00655     for (unsigned int index = 0; index < all_tags_size; index++) {
00656         Tag * tag = map->all_tags[index];
00657         tag->write(out_file);
00658     }
00659 
00660     // Output each *tag in *all_tags*:
00661     for (unsigned int index = 0; index < all_arcs_size; index++) {
00662         map->all_arcs[index]->write(out_file);
00663     }
00664 
00665     // Output the closing </Map> tag:
00666     File__format(out_file, "</Map>\n");
00667 }
00668 
00675 
00676 void Map__update(Map map, CV_Image image, unsigned int sequence_number) {
00677     if (map->is_changed) {
00678         // Increment *visit* to the next value to use for updating:
00679         unsigned int visit = map->visit + 1;
00680         map->visit = visit;
00681 
00682         // We want the tag with the lowest id number to be the origin.
00683         // Sort *tags* from lowest tag id to greatest:
00684         std::sort(map->all_tags.begin(), map->all_tags.end(), Tag::less);
00685 
00686         // The first tag in {tags} has the lowest id and is forced to be the
00687         // map origin:
00688         Tag * origin_tag = map->all_tags[0];
00689         origin_tag->visit = visit;
00690         origin_tag->hop_count = 0;
00691         
00692         // The first step is to identify all of the *Arc*'s that make a
00693         // spanning tree of the *map* *Tags*'s.
00694 
00695         // Initializd *pending_arcs* with the *Arc*'s from *orgin_tag*:
00696         map->pending_arcs.insert(map->pending_arcs.end(),
00697             origin_tag->arcs_.begin(), origin_tag->arcs_.end());
00698 
00699         // We always want to keep *pending_arcs* sorted from longest to
00700         // shortest at the end.  *Arc__distance_compare*() sorts longest first:
00701         std::sort(map->pending_arcs.begin(), map->pending_arcs.end(),
00702             Arc::distance_less);
00703 
00704         // We keep iterating across *pending_arcs* until it goes empty.
00705         // since we keep it sorted from longest to shortest (and we always
00706         // look at the end), we are building a spanning tree using the shortest
00707         // possible *Arc*'s:
00708         while (map->pending_arcs.size() != 0) {
00709             // Pop the shortest *arc* off the end of *pending_arcs*:
00710             Arc * arc = map->pending_arcs.back();
00711             map->pending_arcs.pop_back();
00712 
00713             // For debugging only:
00714             //File__format(stderr, "----------\n");
00715             //unsigned int size = List__size(pending_arcs);
00716             //for (unsigned int index = 0; index < size; index++) {
00717             //    Arc arc = (Arc)List__fetch(pending_arcs, index);
00718             //    File__format(stderr,
00719             //      "pending_arcs[%d]: Arc[%d,%d] dist=%f\n",
00720             //      index, arc->origin->id, arc->target->id, arc->distance);
00721             //}
00722 
00723             // If we already visited *arc*, just ignore it:
00724             if (arc->visit != visit) {
00725                 // We have not visited this *arc* in this cycle, so now we
00726                 // mark it as being *visit*'ed:
00727                 arc->visit = visit;
00728 
00729                 // Figure out if *origin* or *target* have been added to the
00730                 // spanning tree yet:
00731                 Tag * from_tag = arc->from_tag;
00732                 Tag * to_tag = arc->to_tag;
00733                 bool from_is_new = (bool)(from_tag->visit != visit);
00734                 bool to_is_new = (bool)(to_tag->visit != visit);
00735 
00736                 if (from_is_new || to_is_new) {
00737                     if (from_is_new) {
00738                         // Add *to* to spanning tree:
00739                         assert (!to_is_new);
00740                         from_tag->hop_count = to_tag->hop_count + 1;
00741                         map->pending_arcs.insert(map->pending_arcs.end(),
00742                             from_tag->arcs_.begin(), from_tag->arcs_.end());
00743                         from_tag->visit = visit;
00744                         from_tag->update_via_arc(arc, image, sequence_number);
00745                     } else {
00746                         // Add *from* to spanning tree:
00747                         assert (!from_is_new);
00748                         to_tag->hop_count = from_tag->hop_count + 1;
00749                         map->pending_arcs.insert(map->pending_arcs.end(),
00750                             to_tag->arcs_.begin(), to_tag->arcs_.end());
00751                         to_tag->visit = visit;
00752                         to_tag->update_via_arc(arc, image, sequence_number);
00753                     }
00754 
00755                     // Mark that *arc* is part of the spanning tree:
00756                     arc->in_tree = (bool)1;
00757 
00758                     // Resort *pending_arcs* to that the shortest distance
00759                     // sorts to the end:
00760                     std::sort(map->pending_arcs.begin(),
00761                         map->pending_arcs.end(), Arc::distance_less);
00762                 } else {
00763                     // *arc* connects across two nodes of spanning tree:
00764                     arc->in_tree = (bool)0;
00765                 }
00766             }
00767         }
00768 
00769         if (map->is_changed) {
00770             Map__save(map);
00771         }
00772 
00773         // Mark that *map* is fully updated:
00774         map->is_changed = (bool)0;
00775         map->is_saved = (bool)0;
00776     }
00777 }
00778 


fiducial_lib
Author(s): Wayne Gramlich
autogenerated on Thu Jun 6 2019 18:08:04