Exemple #1
0
int
main(int argc, char * argv[])
{
  string mesh_path;
  string samples_path;
  string out_path;

  int curr_opt = 0;
  for (int i = 1; i < argc; ++i)
  {
    string arg = argv[i];
    if (!beginsWith(arg, "-"))
    {
      switch (curr_opt)
      {
        case 0: mesh_path = arg; break;
        case 1: samples_path = arg; break;
        case 2: out_path = arg; break;
      }

      curr_opt++;
      if (curr_opt > 3)
        break;
    }
    else
    {
      if (beginsWith(arg, "--max-nbrs="))
      {
        if (sscanf(arg.c_str(), "--max-nbrs=%d", &max_nbrs) != 1 || max_nbrs <= 0)
        {
          THEA_ERROR << "Invalid --max-nbrs parameter";
          return -1;
        }
      }
      else if (beginsWith(arg, "--min-samples="))
      {
        if (sscanf(arg.c_str(), "--min-samples=%ld", &min_samples) != 1 || min_samples <= 0)
        {
          THEA_ERROR << "Invalid --min-samples parameter";
          return -1;
        }
      }
      else if (arg == "-n" || arg == "--normals")
      {
        consistent_normals = true;
      }
      else if (arg == "-r" || arg == "--reachability")
      {
        reachability = true;
      }
      else
      {
        THEA_ERROR << "Unknown parameter: " << arg;
        return -1;
      }
    }
  }

  if (curr_opt != 3)
  {
    THEA_CONSOLE << "";
    THEA_CONSOLE << "Usage: " << argv[0] << " [OPTIONS] <mesh|dense-points> <points> <graph-outfile>";
    THEA_CONSOLE << "";
    THEA_CONSOLE << "Options:";
    THEA_CONSOLE << "  --max-nbrs=N          Maximum degree of proximity graph";
    THEA_CONSOLE << "  --min-samples=N       Minimum number of original plus generated samples";
    THEA_CONSOLE << "  --normals | -n        Run extra tests assuming consistently oriented mesh normals";
    THEA_CONSOLE << "  --reachability | -r   Reachability test for adjacency (requires -n)";
    THEA_CONSOLE << "";

    return -1;
  }

  if (reachability && !consistent_normals)
  {
    THEA_ERROR << "Reachability test requires consistent normals";
    return -1;
  }

  //===========================================================================================================================
  // Load points
  //===========================================================================================================================

  TheaArray<Vector3> sample_positions;
  TheaArray<Vector3> sample_normals;
  if (loadSamples(samples_path, sample_positions, sample_normals))
    return -1;

  bool has_normals = (!sample_positions.empty() && sample_normals.size() == sample_positions.size());

  THEA_CONSOLE << "Loaded " << sample_positions.size() << " sample(s) from " << samples_path;

  //===========================================================================================================================
  // Load mesh or dense samples
  //===========================================================================================================================

  TheaArray<Vector3> dense_positions;
  TheaArray<Vector3> dense_normals;
  bool dense_has_normals = false;
  KDTree kdtree;
  if (mesh_path != "-")
  {
    // First try to load the file as a set of points
    int dense_load_status = loadSamples(mesh_path, dense_positions, dense_normals);
    dense_has_normals = (!dense_positions.empty() && dense_normals.size() == dense_positions.size());

    if (dense_load_status != 0 && dense_load_status != UNSUPPORTED_FORMAT)
    {
      return -1;
    }
    else if (dense_load_status == 0)
    {
      THEA_CONSOLE << dense_positions.size() << " extra samples added from: " << mesh_path;
    }
    else  // Now try to load the file as a mesh, if the above failed
    {
      MG mg;
      try
      {
        mg.load(mesh_path);
      }
      THEA_STANDARD_CATCH_BLOCKS(return -1;, ERROR, "Could not load mesh %s", mesh_path.c_str())

      THEA_CONSOLE << "Loaded mesh from " << mesh_path;

      // Make sure the mesh is properly scaled
      AxisAlignedBox3 mesh_bounds = mg.getBounds();
      AxisAlignedBox3 samples_bounds;
      for (array_size_t i = 0; i < sample_positions.size(); ++i)
        samples_bounds.merge(sample_positions[i]);

      Real scale_error = (mesh_bounds.getLow()  - samples_bounds.getLow()).length()
                       + (mesh_bounds.getHigh() - samples_bounds.getHigh()).length();
      if (scale_error > 0.01 * mesh_bounds.getExtent().length())
      {
        // Rescale the mesh
        Real scale = (samples_bounds.getExtent() / mesh_bounds.getExtent()).max();  // samples give a smaller bound than the
                                                                                    // true bound, so take the axis in which
                                                                                    // the approximation is best

        AffineTransform3 tr = AffineTransform3::translation(samples_bounds.getCenter())
                            * AffineTransform3::scaling(scale)
                            * AffineTransform3::translation(-mesh_bounds.getCenter());
        MeshTransformer func(tr);
        mg.forEachMeshUntil(&func);
        mg.updateBounds();

        THEA_CONSOLE << "Matched scale of source mesh and original samples";
      }

      kdtree.add(mg);
      kdtree.init();

      // If the samples have no normals, compute them
      if (consistent_normals && !has_normals)
      {
        sample_normals.resize(sample_positions.size());

        for (array_size_t i = 0; i < sample_positions.size(); ++i)
        {
          long elem = kdtree.closestElement<MetricL2>(sample_positions[i]);
          if (elem < 0)
          {
            THEA_ERROR << "Could not find nearest neighbor of sample " << i << " on mesh";
            return false;
          }

          sample_normals[i] = kdtree.getElements()[(array_size_t)elem].getNormal();
        }

        has_normals = true;

        THEA_CONSOLE << "Computed sample normals";
      }

      // Augment the number of samples if necessary
      if ((long)sample_positions.size() < min_samples)
      {
        dense_positions.clear();
        dense_normals.clear();

        MeshSampler<Mesh> sampler(mg);
        sampler.sampleEvenlyByArea((long)(min_samples - sample_positions.size()), dense_positions,
                                   (consistent_normals ? &dense_normals : NULL));

        if (!dense_positions.empty())
          THEA_CONSOLE << dense_positions.size() << " extra samples added to original set, for density";

        dense_has_normals = (!dense_positions.empty() && dense_normals.size() == dense_positions.size());
      }
    }