Main Page | Modules | Namespace List | Class Hierarchy | Class List | File List | Namespace Members | Class Members | File Members | Related Pages

surftopgm.cpp

Go to the documentation of this file.
00001 #include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
00002 #include <CGAL/Triangulation_euclidean_traits_xy_3.h>
00003 #include <CGAL/Delaunay_triangulation_2.h>
00004 #include <CGAL/Bbox_2.h>
00005 #include <CGAL/intersection_3_1.h>
00006 
00007 #include <string>
00008 #include <iostream>
00009 #include <istream>
00010 #include <ostream>
00011 #include <fstream>
00012 
00013 #include "parsecl.hpp"
00014 
00015 struct K : CGAL::Exact_predicates_inexact_constructions_kernel {};
00016 
00017 typedef K::Plane_3 Plane;
00018 typedef K::Line_3 Line;
00019 typedef CGAL::Bbox_2 BoundingBox;
00020 
00021 typedef CGAL::Triangulation_euclidean_traits_xy_3<K>  Gt;
00022 typedef CGAL::Delaunay_triangulation_2<Gt> Delaunay;
00023 typedef Delaunay::Point Point;
00024 typedef Delaunay::Point_iterator PointIterator;
00025 typedef Delaunay::Vertex_handle VertexHandle;
00026 typedef Delaunay::Face_handle FaceHandle;
00027 typedef Delaunay::Vertex_circulator VertexCirculator;
00028 
00033 int main(int argc, char** argv) {
00034   using namespace Arak::Util;
00035   // Parse the command line.
00036   CommandLine cl;
00037   CommandLine::Parameter<double> 
00038     gamma("-g", "--gamma", "the gamma correction value", 1.0 / 0.45);
00039   cl.add(gamma);
00040   CommandLine::Parameter<int> 
00041     widthSpec("-w", "--width", "the image width", -1);
00042   cl.add(widthSpec);
00043   CommandLine::Parameter<int> 
00044     heightSpec("-h", "--height", "the image height", -1);
00045   cl.add(heightSpec);
00046   CommandLine::Parameter<int> 
00047     depth("-d", "--depth", "the image depth (# gray values)", 256);
00048   cl.add(depth);
00049   CommandLine::Parameter<double> 
00050     max("-min", "--min-intensity", "the surface value mapped to white", 0.0);
00051   cl.add(max);
00052   CommandLine::Parameter<double> 
00053     min("-max", "--max-intensity", "the surface value mapped to black", 1.0);
00054   cl.add(min);
00055   CommandLine::Option
00056     linear("-l", "--linear-interpolation", 
00057      "use linear instead of nearest-neighbor interpolation");
00058   cl.add(linear);
00059   CommandLine::Parameter<int> 
00060     def("-n", "--nan", 
00061   "the value to use for pixels outside the convex hull", 255);
00062   cl.add(def);
00063   CommandLine::Parameter<std::string> 
00064     inputPath("-i", "--input", 
00065         "the input file of point color estimates", std::string());
00066   cl.add(inputPath);
00067   CommandLine::Parameter<std::string> 
00068     outputPath("-o", "--output", "the output PGM file", std::string());
00069   cl.add(outputPath);
00070   if (!cl.parse(argc, argv, std::cerr)) {
00071     cl.printUsage(std::cerr);
00072     exit(1);
00073   }
00074 
00075   // Grab the input and output streams.
00076   std::istream* in = &std::cin;
00077   if (inputPath.supplied()) {
00078     in = new std::ifstream(inputPath.value().data());
00079     if (!in->good()) {
00080       std::cerr << "Error: cannot open file " << inputPath.value()
00081     << " for reading." << std::endl;
00082       exit(1);
00083     }
00084   }
00085   std::ostream* out = &std::cout;
00086   if (outputPath.supplied()) {
00087     out = new std::ofstream(outputPath.value().data());
00088     if (!out->good()) {
00089       std::cerr << "Error: cannot open file " << outputPath.value()
00090     << " for writing." << std::endl;
00091       exit(1);
00092     }
00093   }
00094 
00095   // Compute the gamma corrected values.
00096   int* gcv = new int[depth.value()];
00097   gcv[0] = 0;
00098   for (int i = 1; i < depth.value(); i++) {
00099     double raw = double(i) / double(depth.value() - 1);
00100     double corr = pow(raw, gamma.value());
00101     gcv[i] = int(round(corr * double(depth.value() - 1)));
00102   }
00103 
00104   // Read the point data.
00105   std::istream_iterator<Point> begin(*in);
00106   std::istream_iterator<Point> end;
00107   Delaunay dt;
00108   dt.insert(begin, end);
00109   std::cerr << "Read " << dt.number_of_vertices() 
00110       << " points." << std::endl;
00111   
00112   // Compute the bounding box by traversing the convex hull of the points.
00113   VertexHandle infVertexHandle = dt.infinite_vertex();
00114   VertexCirculator circ = dt.incident_vertices(infVertexHandle);
00115   VertexCirculator first = dt.incident_vertices(infVertexHandle);
00116   Point p = circ->point();
00117   BoundingBox bbox(CGAL::to_double(p.x()), CGAL::to_double(p.y()), 
00118        CGAL::to_double(p.x()), CGAL::to_double(p.y()));
00119   while (++circ != first) {
00120     p = circ->point();
00121     bbox = bbox + BoundingBox(CGAL::to_double(p.x()), CGAL::to_double(p.y()), 
00122             CGAL::to_double(p.x()), CGAL::to_double(p.y()));
00123   }
00124   std::cerr << "Bounding box: " << bbox << std::endl;
00125 
00126   // Compute the height and width from the specs and the aspect ratio
00127   // of the bounding box.
00128   int height, width;
00129   if (widthSpec.supplied() && heightSpec.supplied()) {
00130     // Use the specified values, ignoring the aspect ratio.
00131     height = heightSpec.value();
00132     width = widthSpec.value();
00133   } else if (!widthSpec.supplied() && !heightSpec.supplied()) {
00134     // Infer a good set of values from the aspect ratio and sampling
00135     // density.
00136     int size = dt.number_of_vertices();
00137     double aspectRatio = 
00138       (bbox.ymax() - bbox.ymin()) / (bbox.xmax() - bbox.xmin());
00139     width = int(round(sqrt(double(size) / aspectRatio)));
00140     height = int(aspectRatio * double(width));
00141   } else if (!heightSpec.supplied()) {
00142     // Use the supplied width and scale the height to maintain the
00143     // aspect ratio.
00144     width = widthSpec.value();
00145     double aspectRatio = 
00146       (bbox.ymax() - bbox.ymin()) / (bbox.xmax() - bbox.xmin());
00147     height = int(aspectRatio * double(width));
00148   } else {
00149     // Use the supplied height and scale the width to maintain the
00150     // aspect ratio.
00151     height = heightSpec.value();
00152     double aspectRatio = 
00153       (bbox.ymax() - bbox.ymin()) / (bbox.xmax() - bbox.xmin());
00154     width = int(double(height) / aspectRatio);
00155   }
00156 
00157   // Compute the units per dot (UPD) and report the resolution.
00158   K::FT upd((bbox.xmax() - bbox.xmin()) / double(width));
00159   std::cerr << "Output resolution: " << width << "x" << height << std::endl;
00160 
00161   // Compute the interpolated values and output the file.
00162   *out << "P2" << std::endl;                       // magic number
00163   *out << "# " << outputPath.value() << std::endl; // filename
00164   *out << width << " " << height << std::endl;     // resolution
00165   *out << (depth.value() - 1) << std::endl;        // max-value
00166   K::FT y = bbox.ymax();
00167   int num_def = 0;
00168   FaceHandle fh = dt.infinite_face();
00169   for (int i = height - 1; i >= 0; i--) {
00170     K::FT x = bbox.xmin();
00171     for (int j = 0; j < width; j++) {
00172       Point q(x, y, K::FT(0));
00173       fh = dt.locate(q, fh);
00174       if ((fh == NULL) || dt.is_infinite(fh)) {
00175   // Point lies outside convex hull.
00176   *out << def.value() << " ";
00177   num_def++;
00178       } else if (linear.supplied()) {
00179   // Use linear interpolation.  First form the plane containing
00180   // the vertices of the face.
00181   Plane plane(fh->vertex(0)->point(),
00182         fh->vertex(1)->point(),
00183         fh->vertex(2)->point());
00184   // Now form the vertical line at the query point.
00185   Line line(q, Point(x, y, K::FT(1.0)));
00186   // Compute the intersection point in 3-space.
00187   Point interp;
00188   CGAL::Object result = intersection(plane, line);
00189   assert(CGAL::assign(interp, result));
00190   // The interpolated value is the z-coordinate.
00191   double value = CGAL::to_double(interp.z());
00192   // Compute the intensity associated with this value.
00193   double intensity = 
00194     (value - min.value()) / (max.value() - min.value());
00195   intensity = (intensity < 0.0) ? 0.0 : intensity;
00196   intensity = (intensity > 1.0) ? 1.0 : intensity;
00197   // Compute the pixel value and then use gamma correction.
00198   *out << gcv[int(round(intensity * double(depth.value() - 1)))] << " ";
00199       } else {
00200   // Use nearest neighbor interpolation.
00201   Point p0 = fh->vertex(0)->point();
00202   Point p1 = fh->vertex(1)->point();
00203   Point p2 = fh->vertex(2)->point();
00204   // The interpolated value is the z-coordinate of the nearest
00205   // vertex.
00206   double value;
00207   if (CGAL::compare_distance_to_point(q, p0, p1) ==
00208       CGAL::SMALLER) {
00209     if (CGAL::compare_distance_to_point(q, p0, p2) ==
00210         CGAL::SMALLER) 
00211       value = CGAL::to_double(p0.z());
00212     else
00213       value = CGAL::to_double(p2.z());
00214   } else {
00215     if (CGAL::compare_distance_to_point(q, p1, p2) ==
00216         CGAL::SMALLER) 
00217       value = CGAL::to_double(p1.z());
00218     else
00219       value = CGAL::to_double(p2.z());
00220   }
00221   // Compute the intensity associated with this value.
00222   double intensity = 
00223     (value - min.value()) / (max.value() - min.value());
00224   intensity = (intensity < 0.0) ? 0.0 : intensity;
00225   intensity = (intensity > 1.0) ? 1.0 : intensity;
00226   // Compute the pixel value and then use gamma correction.
00227   *out << gcv[int(round(intensity * double(depth.value() - 1)))] << " ";
00228       }
00229       x += upd;
00230     }
00231     y -= upd;
00232     *out << std::endl;
00233   }
00234   *out << std::endl;
00235   out->flush();  
00236 
00237   // Delete any allocated streams.
00238   if (inputPath.supplied()) delete in;
00239   if (outputPath.supplied()) delete out;
00240   
00241   // Report on the number of default pixel values.
00242   if (num_def > 0)
00243     std::cerr << "Warning: " << num_def 
00244         << " pixel values defaulted to " 
00245         << def.value() << std::endl;
00246 
00247   return 0;
00248 }

Generated on Wed May 25 14:39:19 2005 for Arak by doxygen 1.3.6