Attach the perimeter to the polygons.

Change-Id: Ic278b68e2e0481d88869946a08588651e884a882
diff --git a/y2019/vision/debug_viewer.cc b/y2019/vision/debug_viewer.cc
index 2bc41ac..14063c2 100644
--- a/y2019/vision/debug_viewer.cc
+++ b/y2019/vision/debug_viewer.cc
@@ -96,23 +96,23 @@
     target_finder_.PreFilter(&imgs);
 
     // Find polygons from blobs.
-    std::vector<std::vector<Segment<2>>> raw_polys;
+    std::vector<Polygon> raw_polys;
     for (const RangeImage &blob : imgs) {
       // Convert blobs to contours in the corrected space.
       ContourNode *contour = target_finder_.GetContour(blob);
       if (draw_contours_) {
         DrawContour(contour, {255, 0, 0});
       }
-      const ::std::vector<::Eigen::Vector2f> unwarped_contour =
+      ::std::vector<::Eigen::Vector2f> unwarped_contour =
           target_finder_.UnWarpContour(contour);
       if (draw_contours_) {
         DrawContour(unwarped_contour, {0, 0, 255});
       }
 
       // Process to polygons.
-      std::vector<Segment<2>> polygon =
-          target_finder_.FillPolygon(unwarped_contour, draw_raw_poly_);
-      if (polygon.empty()) {
+      const Polygon polygon = target_finder_.FindPolygon(
+          ::std::move(unwarped_contour), draw_raw_poly_);
+      if (polygon.segments.empty()) {
         if (!draw_contours_) {
           DrawBlob(blob, {255, 0, 0});
         }
@@ -122,15 +122,16 @@
           DrawBlob(blob, {0, 0, 255});
         }
         if (draw_raw_poly_) {
-          std::vector<PixelRef> colors = GetNColors(polygon.size());
+          std::vector<PixelRef> colors = GetNColors(polygon.segments.size());
           std::vector<Vector<2>> corners;
-          for (size_t i = 0; i < polygon.size(); ++i) {
-            corners.push_back(
-                polygon[i].Intersect(polygon[(i + 1) % polygon.size()]));
+          for (size_t i = 0; i < polygon.segments.size(); ++i) {
+            corners.push_back(polygon.segments[i].Intersect(
+                polygon.segments[(i + 1) % polygon.segments.size()]));
           }
 
-          for (size_t i = 0; i < polygon.size(); ++i) {
-            overlay_.AddLine(corners[i], corners[(i + 1) % polygon.size()],
+          for (size_t i = 0; i < polygon.segments.size(); ++i) {
+            overlay_.AddLine(corners[i],
+                             corners[(i + 1) % polygon.segments.size()],
                              colors[i]);
           }
         }
diff --git a/y2019/vision/global_calibration.cc b/y2019/vision/global_calibration.cc
index 6d4a21e..3d1e91f 100644
--- a/y2019/vision/global_calibration.cc
+++ b/y2019/vision/global_calibration.cc
@@ -158,15 +158,15 @@
     target_finder.PreFilter(&imgs);
 
     constexpr bool verbose = false;
-    ::std::vector<std::vector<Segment<2>>> raw_polys;
+    ::std::vector<Polygon> raw_polys;
     for (const RangeImage &blob : imgs) {
       // Convert blobs to contours in the corrected space.
       ContourNode *contour = target_finder.GetContour(blob);
-      const ::std::vector<::Eigen::Vector2f> unwarped_contour =
+      ::std::vector<::Eigen::Vector2f> unwarped_contour =
           target_finder.UnWarpContour(contour);
-      const ::std::vector<Segment<2>> polygon =
-          target_finder.FillPolygon(unwarped_contour, verbose);
-      if (!polygon.empty()) {
+      const Polygon polygon =
+          target_finder.FindPolygon(::std::move(unwarped_contour), verbose);
+      if (!polygon.segments.empty()) {
         raw_polys.push_back(polygon);
       }
     }
diff --git a/y2019/vision/target_finder.cc b/y2019/vision/target_finder.cc
index 85cf452..e340702 100644
--- a/y2019/vision/target_finder.cc
+++ b/y2019/vision/target_finder.cc
@@ -90,8 +90,8 @@
 
 // TODO: Try hierarchical merge for this.
 // Convert blobs into polygons.
-std::vector<aos::vision::Segment<2>> TargetFinder::FillPolygon(
-    const ::std::vector<::Eigen::Vector2f> &contour, bool verbose) {
+Polygon TargetFinder::FindPolygon(::std::vector<::Eigen::Vector2f> &&contour,
+                                  bool verbose) {
   if (verbose) printf("Process Polygon.\n");
 
   ::std::vector<::Eigen::Vector2f> slopes;
@@ -249,7 +249,7 @@
   if (verbose) printf("Edge Count (%zu).\n", edges.size());
 
   // Run best-fits over each line segment.
-  ::std::vector<Segment<2>> seg_list;
+  Polygon polygon;
   if (edges.size() >= 3) {
     for (size_t i = 0; i < edges.size(); ++i) {
       // Include the corners in both line fits.
@@ -296,7 +296,7 @@
         x /= norm;
         y /= norm;
 
-        seg_list.push_back(
+        polygon.segments.push_back(
             Segment<2>(Vector<2>(mx, my), Vector<2>(mx + x, my + y)));
       }
 
@@ -312,23 +312,24 @@
       */
     }
   }
-  if (verbose) printf("Poly Count (%zu).\n", seg_list.size());
-  return seg_list;
+  if (verbose) printf("Poly Count (%zu).\n", polygon.segments.size());
+  polygon.contour = ::std::move(contour);
+  return polygon;
 }
 
 // Convert segments into target components (left or right)
-std::vector<TargetComponent> TargetFinder::FillTargetComponentList(
-    const std::vector<std::vector<Segment<2>>> &seg_list, bool verbose) {
-  std::vector<TargetComponent> list;
+::std::vector<TargetComponent> TargetFinder::FillTargetComponentList(
+    const ::std::vector<Polygon> &seg_list, bool verbose) {
+  ::std::vector<TargetComponent> list;
   TargetComponent new_target;
-  for (const std::vector<Segment<2>> &poly : seg_list) {
+  for (const Polygon &poly : seg_list) {
     // Reject missized pollygons for now. Maybe rectify them here in the future;
-    if (poly.size() != 4) {
+    if (poly.segments.size() != 4) {
       continue;
     }
     ::std::vector<Vector<2>> corners;
     for (size_t i = 0; i < 4; ++i) {
-      Vector<2> corner = poly[i].Intersect(poly[(i + 1) % 4]);
+      Vector<2> corner = poly.segments[i].Intersect(poly.segments[(i + 1) % 4]);
       if (::std::isnan(corner.x()) || ::std::isnan(corner.y())) {
         break;
       }
diff --git a/y2019/vision/target_finder.h b/y2019/vision/target_finder.h
index 83a1ebd..ebae3b4 100644
--- a/y2019/vision/target_finder.h
+++ b/y2019/vision/target_finder.h
@@ -18,6 +18,11 @@
 using aos::vision::Vector;
 using aos::vision::ContourNode;
 
+struct Polygon {
+  ::std::vector<aos::vision::Segment<2>> segments;
+  ::std::vector<::Eigen::Vector2f> contour;
+};
+
 class TargetFinder {
  public:
   TargetFinder();
@@ -34,13 +39,11 @@
   ::std::vector<::Eigen::Vector2f> UnWarpContour(ContourNode *start) const;
 
   // Turn a blob into a polgygon.
-  std::vector<aos::vision::Segment<2>> FillPolygon(
-      const ::std::vector<::Eigen::Vector2f> &contour, bool verbose);
+  Polygon FindPolygon(::std::vector<::Eigen::Vector2f> &&contour, bool verbose);
 
   // Turn a bloblist into components of a target.
   std::vector<TargetComponent> FillTargetComponentList(
-      const std::vector<std::vector<aos::vision::Segment<2>>> &seg_list,
-      bool verbose);
+      const ::std::vector<Polygon> &seg_list, bool verbose);
 
   // Piece the compenents together into a target.
   std::vector<Target> FindTargetsFromComponents(
diff --git a/y2019/vision/target_sender.cc b/y2019/vision/target_sender.cc
index f67cea1..6dcf6c0 100644
--- a/y2019/vision/target_sender.cc
+++ b/y2019/vision/target_sender.cc
@@ -308,15 +308,15 @@
     LOG(INFO, "Blobs: (%zu).\n", imgs.size());
 
     constexpr bool verbose = false;
-    ::std::vector<std::vector<Segment<2>>> raw_polys;
+    ::std::vector<Polygon> raw_polys;
     for (const RangeImage &blob : imgs) {
       // Convert blobs to contours in the corrected space.
       ContourNode* contour = finder_.GetContour(blob);
-      const ::std::vector<::Eigen::Vector2f> unwarped_contour =
+      ::std::vector<::Eigen::Vector2f> unwarped_contour =
           finder_.UnWarpContour(contour);
-      ::std::vector<Segment<2>> polygon =
-          finder_.FillPolygon(unwarped_contour, verbose);
-      if (!polygon.empty()) {
+      const Polygon polygon =
+          finder_.FindPolygon(::std::move(unwarped_contour), verbose);
+      if (!polygon.segments.empty()) {
         raw_polys.push_back(polygon);
       }
     }