Add PLY file logger before and after BA in order to ease visual comparison.

Change-Id: Ib14e8f4b2de686ab6494de270458392f81a0b946
diff --git a/examples/bal_problem.cc b/examples/bal_problem.cc
index 46fba4f..fa1d82a 100644
--- a/examples/bal_problem.cc
+++ b/examples/bal_problem.cc
@@ -32,6 +32,7 @@
 
 #include <cstdio>
 #include <cstdlib>
+#include <fstream>
 #include <string>
 #include <vector>
 #include "Eigen/Core"
@@ -176,9 +177,46 @@
   fclose(fptr);
 }
 
+// Write the problem to a PLY file for inspection in Matlab or CloudCompare.
+void BALProblem::WriteToPLYFile(const std::string& filename) const {
+  std::ofstream of(filename.c_str());
+
+  of << "ply"
+     << '\n' << "format ascii 1.0"
+     << '\n' << "element vertex " << num_cameras_ + num_points_
+     << '\n' << "property float x"
+     << '\n' << "property float y"
+     << '\n' << "property float z"
+     << '\n' << "property uchar red"
+     << '\n' << "property uchar green"
+     << '\n' << "property uchar blue"
+     << '\n' << "end_header" << std::endl;
+
+  // Export extrinsic data (i.e. camera centers) as green points.
+  double angle_axis[3];
+  double center[3];
+  for (int i = 0; i < num_cameras(); ++i)  {
+    const double* camera = cameras() + camera_block_size() * i;
+    CameraToAngleAxisAndCenter(camera, angle_axis, center);
+    of << center[0] << ' ' << center[1] << ' ' << center[2]
+       << " 0 255 0" << '\n';
+  }
+
+  // Export the structure (i.e. 3D Points) as white points.
+  const double* points = parameters_ + camera_block_size() * num_cameras_;
+  for (int i = 0; i < num_points(); ++i) {
+    const double* point = points + i * point_block_size();
+    for (int j = 0; j < point_block_size(); ++j) {
+      of << point[j] << ' ';
+    }
+    of << "255 255 255\n";
+  }
+  of.close();
+}
+
 void BALProblem::CameraToAngleAxisAndCenter(const double* camera,
                                             double* angle_axis,
-                                            double* center) {
+                                            double* center) const {
   VectorRef angle_axis_ref(angle_axis, 3);
   if (use_quaternions_) {
     QuaternionToAngleAxis(camera, angle_axis);
@@ -196,7 +234,7 @@
 
 void BALProblem::AngleAxisAndCenterToCamera(const double* angle_axis,
                                             const double* center,
-                                            double* camera) {
+                                            double* camera) const {
   ConstVectorRef angle_axis_ref(angle_axis, 3);
   if (use_quaternions_) {
     AngleAxisToQuaternion(angle_axis, camera);
diff --git a/examples/bal_problem.h b/examples/bal_problem.h
index d3b2aff..e9a348e 100644
--- a/examples/bal_problem.h
+++ b/examples/bal_problem.h
@@ -48,6 +48,7 @@
   ~BALProblem();
 
   void WriteToFile(const std::string& filename) const;
+  void WriteToPLYFile(const std::string& filename) const;
 
   // Move the "center" of the reconstruction to the origin, where the
   // center is determined by computing the marginal median of the
@@ -74,6 +75,7 @@
   const int* camera_index()    const { return camera_index_;             }
   const double* observations() const { return observations_;             }
   const double* parameters()   const { return parameters_;               }
+  const double* cameras()      const { return parameters_;               }
   double* mutable_cameras()          { return parameters_;               }
   double* mutable_points() {
     return parameters_  + camera_block_size() * num_cameras_;
@@ -82,11 +84,11 @@
  private:
   void CameraToAngleAxisAndCenter(const double* camera,
                                   double* angle_axis,
-                                  double* center);
+                                  double* center) const;
 
   void AngleAxisAndCenterToCamera(const double* angle_axis,
                                   const double* center,
-                                  double* camera);
+                                  double* camera) const;
   int num_cameras_;
   int num_points_;
   int num_observations_;
diff --git a/examples/bundle_adjuster.cc b/examples/bundle_adjuster.cc
index 495094b..e64fdb5 100644
--- a/examples/bundle_adjuster.cc
+++ b/examples/bundle_adjuster.cc
@@ -120,6 +120,9 @@
              "the pertubations.");
 DEFINE_bool(line_search, false, "Use a line search instead of trust region "
             "algorithm.");
+DEFINE_string(initial_ply, "", "Export the BAL file data as a PLY file.");
+DEFINE_string(final_ply, "", "Export the refined BAL file data as a PLY "
+            "file.");
 
 namespace ceres {
 namespace examples {
@@ -311,6 +314,11 @@
 
 void SolveProblem(const char* filename) {
   BALProblem bal_problem(filename, FLAGS_use_quaternions);
+
+  if (!FLAGS_initial_ply.empty()) {
+    bal_problem.WriteToPLYFile(FLAGS_initial_ply);
+  }
+
   Problem problem;
 
   srand(FLAGS_random_seed);
@@ -327,6 +335,10 @@
   Solver::Summary summary;
   Solve(options, &problem, &summary);
   std::cout << summary.FullReport() << "\n";
+
+  if (!FLAGS_final_ply.empty()) {
+    bal_problem.WriteToPLYFile(FLAGS_final_ply);
+  }
 }
 
 }  // namespace examples