CGAL kết nối 2 hình học


11

Hiện tại tôi cố gắng tham gia các phần khác nhau của Lưới, không được kết nối. Từ ví dụ tôi tìm thấy cái này (blobby_3cc.off).

Với keep_large_connected_componentskeep_largest_connected_componentstôi loại bỏ tất cả các thành phần nhỏ hơn. Mà giữ 3 dưới đây.

Tôi không thể tìm thấy một cách trong tài liệu để kết hợp chúng lại với nhau và điền vào những phần còn thiếu. Một giải pháp là tạo 1 tam giác và lấp đầy các lỗ (từ đó nó là 1 đối tượng, với các lỗ rất lớn). Nhưng tôi không thể tìm ra cách để tham gia cùng nhau.

Bất cứ ai cũng có một giải pháp cho điều này?

Tôi đang sử dụng CGAL cho C ++.

nhập mô tả hình ảnh ở đây

Câu trả lời:


3

Khi tôi bắt đầu với CGAL, tôi gần như ngay lập tức gặp phải vấn đề này. Tôi đã có thể tìm ra giải pháp sau khi đọc kỹ tài liệu lưới đa giác . Về cơ bản, thông qua một phiên bản sửa đổi của Corefinement , bạn có thể kết hợp trơn tru hai hình học riêng biệt, bất kể số lượng hoặc hình dạng poly của chúng (tuy nhiên, sự khác biệt của đa giác càng lớn, nó sẽ càng kém hiệu quả).

Điều bạn phải làm là trước tiên, hãy chắc chắn rằng hình học không tự giao nhau. Thứ hai, đảm bảo rằng đó CGAL::Polygon_mesh_processing::clip()là hoạt động trên hai hình học (tôi khuyên bạn nên sử dụng close_volumes=false). Tiếp theo, tính toán liên kết của hai lưới mới:

#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Surface_mesh.h>
#include <CGAL/Polygon_mesh_processing/corefinement.h>
#include <fstream>
typedef CGAL::Exact_predicates_inexact_constructions_kernel K;
typedef CGAL::Surface_mesh<K::Point_3>             Mesh;
namespace PMP = CGAL::Polygon_mesh_processing;
int main(int argc, char* argv[])
{
  const char* filename1 = (argc > 1) ? argv[1] : "data/blobby.off";
  const char* filename2 = (argc > 2) ? argv[2] : "data/eight.off";
  std::ifstream input(filename1);
  Mesh mesh1, mesh2;
  if (!input || !(input >> mesh1))
  {
    std::cerr << "First mesh is not a valid off file." << std::endl;
    return 1;
  }
  input.close();
  input.open(filename2);
  if (!input || !(input >> mesh2))
  {
    std::cerr << "Second mesh is not a valid off file." << std::endl;
    return 1;
  }
  Mesh out;
  bool valid_union = PMP::corefine_and_compute_union(mesh1,mesh2, out);
  if (valid_union)
  {
    std::cout << "Union was successfully computed\n";
    std::ofstream output("union.off");
    output << out;
    return 0;
  }
  std::cout << "Union could not be computed\n";
  return 1;
}

Thay vì sử dụng một lưới có một điểm từ một hạt nhân với các cấu trúc chính xác, các điểm chính xác là một thuộc tính của các đỉnh lưới mà chúng ta có thể sử dụng lại trong các hoạt động sau này. Với đặc tính đó, chúng ta có thể điều khiển một lưới với các điểm có tọa độ điểm nổi nhưng được hưởng lợi từ sự mạnh mẽ được cung cấp bởi các công trình chính xác:

#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Exact_predicates_exact_constructions_kernel.h>
#include <CGAL/Surface_mesh.h>
#include <CGAL/Polygon_mesh_processing/corefinement.h>
#include <fstream>
typedef CGAL::Exact_predicates_inexact_constructions_kernel K;
typedef CGAL::Exact_predicates_exact_constructions_kernel EK;
typedef CGAL::Surface_mesh<K::Point_3> Mesh;
typedef boost::graph_traits<Mesh>::vertex_descriptor vertex_descriptor;
typedef Mesh::Property_map<vertex_descriptor,EK::Point_3> Exact_point_map;
typedef Mesh::Property_map<vertex_descriptor,bool> Exact_point_computed;
namespace PMP = CGAL::Polygon_mesh_processing;
namespace params = PMP::parameters;
struct Coref_point_map
{
  // typedef for the property map
  typedef boost::property_traits<Exact_point_map>::value_type value_type;
  typedef boost::property_traits<Exact_point_map>::reference reference;
  typedef boost::property_traits<Exact_point_map>::category category;
  typedef boost::property_traits<Exact_point_map>::key_type key_type;
  // exterior references
  Exact_point_computed* exact_point_computed_ptr;
  Exact_point_map* exact_point_ptr;
  Mesh* mesh_ptr;
  Exact_point_computed& exact_point_computed() const
  {
    CGAL_assertion(exact_point_computed_ptr!=NULL);
    return *exact_point_computed_ptr;
  }
  Exact_point_map& exact_point() const
  {
    CGAL_assertion(exact_point_ptr!=NULL);
    return *exact_point_ptr;
  }
  Mesh& mesh() const
  {
    CGAL_assertion(mesh_ptr!=NULL);
    return *mesh_ptr;
  }
  // Converters
  CGAL::Cartesian_converter<K, EK> to_exact;
  CGAL::Cartesian_converter<EK, K> to_input;
  Coref_point_map()
    : exact_point_computed_ptr(NULL)
    , exact_point_ptr(NULL)
    , mesh_ptr(NULL)
  {}
  Coref_point_map(Exact_point_map& ep,
                  Exact_point_computed& epc,
                  Mesh& m)
    : exact_point_computed_ptr(&epc)
    , exact_point_ptr(&ep)
    , mesh_ptr(&m)
  {}
  friend
  reference get(const Coref_point_map& map, key_type k)
  {
    // create exact point if it does not exist
    if (!map.exact_point_computed()[k]){
      map.exact_point()[k]=map.to_exact(map.mesh().point(k));
      map.exact_point_computed()[k]=true;
    }
    return map.exact_point()[k];
  }
  friend
  void put(const Coref_point_map& map, key_type k, const EK::Point_3& p)
  {
    map.exact_point_computed()[k]=true;
    map.exact_point()[k]=p;
    // create the input point from the exact one
    map.mesh().point(k)=map.to_input(p);
  }
};
int main(int argc, char* argv[])
{
  const char* filename1 = (argc > 1) ? argv[1] : "data/blobby.off";
  const char* filename2 = (argc > 2) ? argv[2] : "data/eight.off";
  std::ifstream input(filename1);
  Mesh mesh1, mesh2;
  if (!input || !(input >> mesh1))
  {
    std::cerr << "First mesh is not a valid off file." << std::endl;
    return 1;
  }
  input.close();
  input.open(filename2);
  if (!input || !(input >> mesh2))
  {
    std::cerr << "Second mesh is not a valid off file." << std::endl;
    return 1;
  }
  Exact_point_map mesh1_exact_points =
    mesh1.add_property_map<vertex_descriptor,EK::Point_3>("e:exact_point").first;
  Exact_point_computed mesh1_exact_points_computed =
    mesh1.add_property_map<vertex_descriptor,bool>("e:exact_points_computed").first;
  Exact_point_map mesh2_exact_points =
    mesh2.add_property_map<vertex_descriptor,EK::Point_3>("e:exact_point").first;
  Exact_point_computed mesh2_exact_points_computed =
    mesh2.add_property_map<vertex_descriptor,bool>("e:exact_points_computed").first;
  Coref_point_map mesh1_pm(mesh1_exact_points, mesh1_exact_points_computed, mesh1);
  Coref_point_map mesh2_pm(mesh2_exact_points, mesh2_exact_points_computed, mesh2);
  if ( PMP::corefine_and_compute_intersection(mesh1,
                                              mesh2,
                                              mesh1,
                                              params::vertex_point_map(mesh1_pm),
                                              params::vertex_point_map(mesh2_pm),
                                              params::vertex_point_map(mesh1_pm) ) )
  {
    if ( PMP::corefine_and_compute_union(mesh1,
                                         mesh2,
                                         mesh2,
                                         params::vertex_point_map(mesh1_pm),
                                         params::vertex_point_map(mesh2_pm),
                                         params::vertex_point_map(mesh2_pm) ) )
    {
      std::cout << "Intersection and union were successfully computed\n";
      std::ofstream output("inter_union.off");
      output << mesh2;
      return 0;
    }
    std::cout << "Union could not be computed\n";
    return 1;
  }
  std::cout << "Intersection could not be computed\n";
  return 1;
}

Và để lấp đầy bất kỳ lỗ hổng nào, hãy xem Sửa chữa kết hợplấp lỗ hổng
Death Waltz

Cảm ơn bạn đã trả lời của bạn. Tôi cố gắng hiểu mã của bạn, nhưng một số chức năng tôi dường như không hiểu corefine_and_compute_union, corefine_and_compute_intersection. Tôi không có được sự hiểu biết rõ ràng trong các tài liệu. Bạn có thể giải thích một chút?
Niels

Về cơ bản, corefine_and_compute_uniontính toán các phân đoạn của lưới chồng lấp, và cần phải được loại bỏ và thay thế bằng một hình đa giác. corefine_and_compute_intersectiongần giống với điều tương tự, nhưng sử dụng lưới hiện có để lấp đầy vết cắt thay vì tạo ra lưới lấp đầy. Hàm đầu tiên thường yêu cầu một đầu vào chính xác để hoạt động, nhưng hàm thứ hai cho phép nó tự vượt qua như một tham số.
Death Waltz

Tôi phải kiểm tra nó vào cuối tuần này và xem kết quả để tôi biết nó hoạt động như thế nào. Tôi sẽ chấp nhận câu trả lời này là câu trả lời đúng trước khi hết tiền thưởng.
Niels

Được rồi, nếu nó không hoạt động, hãy cho tôi biết
Death Waltz

0

Làm thế nào để lưới trông ban đầu? nó có khả thi để hợp nhất các thành phần khác nhau thay vì loại bỏ các phần nhỏ nhất không? Xem sửa chữa kết hợp CGAL để biết thêm.

Kết nối các thành phần khác nhau là một vấn đề khá khó khăn. Tôi tin rằng các thuật toán lấp lỗ thông thường chỉ hoạt động trên các lỗ bị giới hạn, tức là có một cạnh mở đi xung quanh lỗ và kết thúc khi bắt đầu.

Đề nghị của tôi sẽ là phân tích lưới để tìm các cạnh mở - danh sách cần được kết nối, tức là các đường màu đỏ, xanh lá cây, xanh dương và tím. Tìm cách ghép nối những thứ này với nhau, ví dụ reg-green và blue-tím. Trong ví dụ này chỉ cần sử dụng trung bình của các cạnh để ghép.

Sau đó, bạn sẽ cần một số phương pháp để tam giác khoảng cách giữa các cạnh. Như bạn đã đề cập, cần tạo ra một hình tam giác (hoặc hai) để kết nối các bộ phận và sử dụng một cái gì đó như CGAL :: Polygon_mesh_ Processing :: triangulation_Vfine_and_fair_hole để lấp đầy phần còn lại.

Để làm điều này, bạn có thể cố gắng tìm hai cạnh của mỗi danh sách gần nhau. Tức là tổng khoảng cách điểm càng nhỏ càng tốt. Vì vậy, chọn một cạnh từ một danh sách và tìm cạnh gần nhất trong danh sách khác. Khi bạn có hai cạnh, thêm một cặp hình tam giác và sử dụng CGAL để điền vào phần còn lại. Các bộ phận khác nhau nên có cùng định hướng bề mặt để làm việc này, nhưng đó có lẽ là trường hợp.

Một cách tiếp cận khác là chỉ sử dụng các đỉnh để tạo lưới từ đám mây điểm , nhưng điều này không được đảm bảo để khớp với lưới hiện tại của bạn. Giải pháp đơn giản nhất có lẽ là cố gắng tránh hoàn toàn vấn đề, tức là đảm bảo nguồn của các mắt lưới tạo ra các mắt lưới được kết nối được xác định rõ.

ví dụ về các cạnh để kết nối


Cảm ơn bạn đã trả lời của bạn, đây thực sự là cách tiếp cận mà tôi đã làm việc trong một thời gian, tôi gần như đã hoàn thành lập trình, hiện đang có vấn đề với khuôn mặt sai hướng nên các lỗ hổng không thành công.
Niels
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.