2 ज्यामितीय जोड़ने वाला सीजीएएल


11

वर्तमान में मैं मेष के विभिन्न हिस्सों में शामिल होने की कोशिश करता हूं, जो जुड़े नहीं हैं। उदाहरण से मुझे यह (blobby_3cc.off) मिला।

के साथ keep_large_connected_componentsऔर keep_largest_connected_componentsमैं सभी छोटे घटकों को हटा दें। जो इन 3 को नीचे रखता है।

मुझे उनके साथ जुड़ने और लापता भागों को भरने के लिए दस्तावेज़ में कोई रास्ता नहीं मिल सकता है। एक समाधान 1 त्रिकोण बनाना है और छिद्रों को भरना है (तब से यह 1 वस्तु है, जिसमें भारी छेद हैं)। लेकिन मुझे इनसे जुड़ने का कोई तरीका नहीं मिल रहा है।

किसी के पास इसके लिए कोई हल है?

मैं C ++ के लिए CGAL का उपयोग कर रहा हूं।

यहां छवि विवरण दर्ज करें

जवाबों:


3

जब मैंने सीजीएएल के साथ शुरुआत की, मैं लगभग तुरंत इस समस्या में भाग गया। बहुभुज जाल प्रलेखन पर सावधानीपूर्वक पढ़ने के बाद मैं एक समाधान खोजने में सक्षम था । मूल रूप से, कोरफाइनमेंट के संशोधित संस्करण के माध्यम से , आप दो अलग-अलग ज्यामितीयों को एक साथ आसानी से जाल कर सकते हैं, कोई फर्क नहीं पड़ता कि उनकी पॉली काउंट या आकृति (हालांकि, पॉलीगन्स का अंतर जितना अधिक होगा, उतना कम प्रभावी होगा)।

आपको पहले क्या करना है, सुनिश्चित करें कि ज्यामिति स्वयं-प्रतिच्छेद नहीं करती है। दूसरे, यह सुनिश्चित करें कि CGAL::Polygon_mesh_processing::clip()दो ज्यामितीयों पर सक्रिय है (मैं उपयोग करने का सुझाव देता हूं close_volumes=false)। अगला, दो नए मेषों के मिलन की गणना करें:

#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;
}

सटीक निर्माणों के साथ कर्नेल से एक बिंदु के साथ एक जाल का उपयोग करने के बजाय, सटीक बिंदु जाल कोने की एक संपत्ति है जिसे हम बाद के संचालन में पुन: उपयोग कर सकते हैं। उस संपत्ति के साथ, हम फ़्लोटिंग पॉइंट निर्देशांक वाले बिंदुओं के साथ एक जाल को जोड़ सकते हैं लेकिन सटीक निर्माणों द्वारा प्रदान की गई मजबूती से लाभान्वित होते हैं:

#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;
}


आपके जवाब के लिए धन्यवाद। मैं अपने कोड को समझने की कोशिश, लेकिन कुछ कार्यों मुझे समझ में नहीं हैं corefine_and_compute_union, corefine_and_compute_intersection। मुझे डॉक्स में कोई स्पष्ट समझ नहीं है। क्या आप थोड़ा समझा सकते हैं?
नील्स

अनिवार्य रूप से, corefine_and_compute_unionउस जाल के खंडों की गणना करता है जो ओवरलैप करते हैं, और उन्हें हटाने और बहुभुज भरने के साथ प्रतिस्थापित करने की आवश्यकता होती है। corefine_and_compute_intersectionएक ही चीज़ के करीब है, लेकिन एक चिकनी जाल भरने के बजाय कटौती को भरने के लिए मौजूदा जाल का उपयोग करता है। पहले फ़ंक्शन को आमतौर पर काम करने के लिए एक सटीक इनपुट की आवश्यकता होती है, लेकिन दूसरा एक पैरामीटर के रूप में खुद को पारित करने की अनुमति देता है।
डेथ वाल्ट्ज

मुझे इस सप्ताह के अंत में इसकी जांच करनी है और परिणाम देखना है इसलिए मुझे पता है कि यह कैसे काम करता है। मैं इस जवाब को सही जवाब के रूप में स्वीकार करूंगा क्योंकि बाउंटी के रन आउट होने से पहले।
नील्स

ठीक है, अगर यह काम नहीं करता है, तो मुझे बताएं
डेथ वाल्ट्ज

0

मेष मूल रूप से कैसे दिखता है? क्या छोटे पुर्जों को हटाने के बजाय अलग-अलग घटकों को मर्ज करना संभव होगा? अधिक जानकारी के लिए CGAL कॉम्बिनेटरिकल रिपेयरिंग देखें ।

विभिन्न घटकों को जोड़ना एक कठिन समस्या है। मेरा मानना ​​है कि नियमित रूप से छेद भरने वाले एल्गोरिदम केवल उन छेदों पर काम करते हैं जो बंधे होते हैं, यानी एक खुला किनारा होता है जो छेद के चारों ओर जाता है और शुरू में समाप्त होता है।

मेरी सिफारिश होगी कि खुले किनारों-सूचियों को खोजने के लिए जाल का विश्लेषण किया जाए, जिसे जोड़ने की जरूरत है, यानी लाल, हरी, नीली और बैंगनी रेखाएं। एक-दूसरे के साथ जोड़ी बनाने का एक तरीका खोजें, अर्थात रेग-ग्रीन और ब्लू-बैंगनी। उदाहरण में यह युग्मन के लिए किनारों के औसत का उपयोग करने के लिए पर्याप्त होना चाहिए।

फिर आपको किनारों के बीच अंतर को त्रिकोणित करने के लिए कुछ विधि की आवश्यकता होगी। जैसा कि आप उल्लेख करते हैं, भागों को जोड़ने के लिए एक त्रिकोण (या दो) बनाने के लिए पर्याप्त होना चाहिए, और बाकी को भरने के लिए CGAL :: Polygon_mesh_processing :: triangulate_refine_and_fair_hole जैसी किसी चीज़ का उपयोग करना चाहिए।

ऐसा करने के लिए आप प्रत्येक सूची के दो किनारों को खोजने की कोशिश कर सकते हैं जो एक दूसरे के करीब हैं। यानी बिंदु दूरी का योग जितना संभव हो उतना छोटा है। तो एक किनारे को एक सूची से चुनें और दूसरे में निकटतम किनारे का पता लगाएं। जब आपके पास दो किनारे हों, तो त्रिकोण की एक जोड़ी जोड़ें और बाकी को भरने के लिए CGAL का उपयोग करें। अलग-अलग हिस्सों में काम करने के लिए समान सतह अभिविन्यास होना चाहिए, लेकिन संभवतः ऐसा ही है।

एक अन्य दृष्टिकोण सिर्फ एक बिंदु बादल से एक जाल बनाने के लिए कोने का उपयोग करना होगा , लेकिन यह आपके वर्तमान जाल से मेल खाने की गारंटी नहीं है। सबसे आसान समाधान संभवतः समस्या से पूरी तरह से बचने की कोशिश करना है, अर्थात सुनिश्चित करें कि मेषों का स्रोत अच्छी तरह से परिभाषित मेषों का उत्पादन करता है।

कनेक्ट करने के लिए किनारों का उदाहरण


आपके उत्तर के लिए धन्यवाद, यह वास्तव में दृष्टिकोण है कि मैं थोड़ी देर के लिए काम कर रहा हूं, मैंने लगभग प्रोग्रामिंग समाप्त कर दी है, वर्तमान में गलत दिशा में चेहरे के साथ समस्या हो रही है ताकि भरण छेद विफल हो जाए।
नील्स
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.