将多面体转换为nef(违反访问)时,与CGAL崩溃

Crash with CGAL when converting a polyhedron to a nef (access violation)

本文关键字:崩溃 CGAL 访问 转换 多面体 nef      更新时间:2023-10-16

以下是我用来计算两个polyhedra与 cgal的相交的代码。我知道这很大,但我竭尽所能最小化。

此代码适用于一个示例,但是对于下面的示例,它崩溃了。汇编运行正常,但是当我运行可执行文件时,它会崩溃。当我从Haskell运行它时,我会收到错误消息"读取XXX时生成的代码中的访问违规" (其中XXX是地址(。

该程序首先构建两个Polyhedra P1P2。在此步骤中没有问题。然后,当程序到达这一行时,就会发生问题:

  Nef_polyhedron nef1(P1);

我很感谢任何帮助以弄清楚发生的事情。

#include <vector>
#include <fstream>
#include <CGAL/Exact_predicates_exact_constructions_kernel.h>
#include <CGAL/Polyhedron_incremental_builder_3.h>
#include <CGAL/Polyhedron_3.h>
#include <CGAL/IO/Polyhedron_iostream.h>
#include <CGAL/Nef_polyhedron_3.h>
#include <CGAL/Surface_mesh.h>
#include <CGAL/boost/graph/convert_nef_polyhedron_to_polygon_mesh.h>
typedef CGAL::Exact_predicates_exact_constructions_kernel Kernel;
typedef CGAL::Polyhedron_3<Kernel>                        Polyhedron;
typedef Polyhedron::HalfedgeDS                            HalfedgeDS;
typedef CGAL::Surface_mesh<Kernel::Point_3>               Surface_mesh;
typedef CGAL::Nef_polyhedron_3<Kernel, CGAL::SNC_indexed_items> Nef_polyhedron;

// helper functions to convert arrays to vectors
std::vector<int> iarray2vector(int* array, size_t n){
  std::vector<int> out;
  for(size_t i=0; i<n; i++){
      out.push_back(array[i]);
  }
  return out;
}
std::vector<double> darray2vector(double* array, size_t n){
  std::vector<double> out;
  for(size_t i=0; i<n; i++){
      out.push_back(array[i]);
  }
  return out;
}

// A modifier creating a polyhedron with the incremental builder.
class polyhedron_builder : public CGAL::Modifier_base<HalfedgeDS> {
public:
  std::vector<double> &coords;
  std::vector<int>    &faces;
  std::vector<int>    &facesizes;
  polyhedron_builder(
    std::vector<double> &_coords,
    std::vector<int> &_faces,
    std::vector<int> &_facesizes
  ) : coords(_coords), faces(_faces), facesizes(_facesizes) {}
  void operator()( HalfedgeDS& hds) {
    typedef typename HalfedgeDS::Vertex   Vertex;
    typedef typename Vertex::Point        Point;
    /* create a cgal incremental builder */
    CGAL::Polyhedron_incremental_builder_3<HalfedgeDS> B( hds, true);
    B.begin_surface( coords.size()/3, faces.size()); 
      /* add the polyhedron vertices */
      for(int i=0; i<(int)coords.size(); i+=3){
        B.add_vertex( Point( coords[i+0], coords[i+1], coords[i+2] ) );
      }
      /* add the polyhedron faces */
      int i=0;
      for(int k=0; k<(int)facesizes.size(); k++){
        int fs = facesizes[k];
        B.begin_facet();
        for(int j=0; j<fs; j++){
          B.add_vertex_to_facet( faces[i+j] );
        }
        B.end_facet();
        i += fs;
      }
    /* finish up the surface */
    B.end_surface();
  }
};

Polyhedron buildPolyhedron(
  double* vertices,
  size_t nvertices,
  int* faces,
  int* facesizes,
  size_t nfaces)
{
  /* calculate length of `faces`*/
  size_t l = 0;
  for(size_t i=0; i < nfaces; i++){
    l += facesizes[i];
  }
  /* make vectors from arrays */
  std::vector<double> vs = darray2vector(vertices, 3*nvertices);
  std::vector<int> fs = iarray2vector(faces, l);
  std::vector<int> fzs = iarray2vector(facesizes, nfaces);
  /* build the polyhedron */
  Polyhedron P;
  polyhedron_builder builder(vs, fs, fzs);
  P.delegate( builder );
  /**/
  return P;
}
void intersectPolyhedra(Polyhedron P1, Polyhedron P2){
  /* convert polyhedra to nefs */
  printf("make nef1n");
  Nef_polyhedron nef1(P1);
  printf("make nef2n");
  Nef_polyhedron nef2(P2);
  /* compute the intersection */
  printf("make nefs intersectionn");
  Nef_polyhedron nef = nef1*nef2;
  /* surface mesh */
  Surface_mesh smesh;
  CGAL::convert_nef_polyhedron_to_polygon_mesh(nef, smesh);
  /* write OFF file */
  std::ofstream outfile;
  outfile.open("intersection.off");
  outfile << smesh;
  outfile.close();
}
void intersectionTwoPolyhedra(
  double* vertices1,
  size_t nvertices1,
  int* faces1,
  int* facesizes1,
  size_t nfaces1,
  double* vertices2,
  size_t nvertices2,
  int* faces2,
  int* facesizes2,
  size_t nfaces2)
{
  printf("build P1n");
  Polyhedron P1 = buildPolyhedron(vertices1, nvertices1, faces1, facesizes1, nfaces1);
  printf("P1 is closed: %un", P1.is_closed());
  std::cout << P1;
  printf("build P2n");
  Polyhedron P2 = buildPolyhedron(vertices2, nvertices2, faces2, facesizes2, nfaces2);
  printf("P2 is closed: %un", P2.is_closed());
  std::cout << P2;
  printf("run intersectionn");
  intersectPolyhedra(P1, P2);
}

int main(){
    double x = (1 + sqrt(5))/2;
    double y = x - 1;
    double vertices[60] = { -1, 1, 1,
                            0, y, x,
                            y, x, 0,
                            -y, x, 0,
                            0, y, -x,
                            0, -y, x,
                            1, -1, 1,
                            x, 0, y,
                            1, 1, 1,
                            1, 1, -1,
                            x, 0, -y,
                            y, -x, 0,
                            1, -1, -1,
                            -1, -1, 1,
                            -x, 0, y,
                            -1, 1, -1,
                            -x, 0, -y,
                            -1, -1, -1,
                            -y, -x, 0,
                            0, -y, -x };
    int faces1[24] = { 3,1,7,9,
                       1,3,16,13,
                       9,19,16,3,
                       16,19,11,13,
                       1,13,11,7,
                       9,7,11,19 };
    int faces2[24] = { 2,4,16,0,
                       2,7,12,4,
                       2,0,5,7,
                       4,12,18,16,
                       0,16,18,5,
                       7,5,18,12 };
    int facesizes[6] = { 4, 4, 4, 4, 4, 4};
    intersectionTwoPolyhedra(
        vertices,
        20,
        faces1,
        facesizes,
        6,
        vertices,
        20,
        faces2,
        facesizes,
        6
    );
    return 0;
}

均调用P1.is_valid()P2.is_valid()返回false。因此,您的输入Polyhedra似乎无效。

我建议您尝试使用更用户友好的polygon_soup_to_polygon_mesh()功能来创建您的Polyhedra。

您也可能需要直接使用Surface_mesh和Polygon网格处理软件包中可用的布尔操作。请参阅此处。