【问题标题】:Crash with CGAL when converting a polyhedron to a nef (access violation)将多面体转换为 nef 时出现 CGAL 崩溃(访问冲突)
【发布时间】:2018-02-16 13:52:08
【问题描述】:

下面是我用来计算两个多面体与cgal 的交集的代码。我知道它很大,但我尽了最大努力将其最小化。

此代码适用于一个示例,但对于下面包含的示例,它会崩溃。编译运行良好,但是当我运行可执行文件时它崩溃了。当我从 Haskell 运行它时,我收到错误消息 “读取 xxx 时生成代码中的访问冲突”(其中 xxx 是地址)。

程序首先构建两个多面体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 nef1\n");
  Nef_polyhedron nef1(P1);
  printf("make nef2\n");
  Nef_polyhedron nef2(P2);
  /* compute the intersection */
  printf("make nefs intersection\n");
  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 P1\n");
  Polyhedron P1 = buildPolyhedron(vertices1, nvertices1, faces1, facesizes1, nfaces1);
  printf("P1 is closed: %u\n", P1.is_closed());
  std::cout << P1;
  printf("build P2\n");
  Polyhedron P2 = buildPolyhedron(vertices2, nvertices2, faces2, facesizes2, nfaces2);
  printf("P2 is closed: %u\n", P2.is_closed());
  std::cout << P2;
  printf("run intersection\n");
  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;
}

【问题讨论】:

    标签: c++ computational-geometry cgal


    【解决方案1】:

    调用P1.is_valid()P2.is_valid() 都返回false。因此,您的输入多面体似乎无效。

    我建议你尝试使用对用户更友好的polygon_soup_to_polygon_mesh() 函数来创建你的多面体。

    您可能还想直接使用Surface_mesh 和多边形网格处理包中可用的布尔运算。见here

    【讨论】:

    • 奇怪,我已经在 OpenGL 中绘制了这些立方体,它们很好。我想知道“无效”是什么意思。谢谢,我会调查的,我会回来的。感谢您的建议。
    • sloriot,我知道问题所在:多面体无效,因为有未使用的顶点。
    • sloriot,关于您的最后一个建议,您的意思是可以直接将多面体转换为表面网格,而无需经过 nef?嗯,也许我应该去 cgal-discuss 去问这些基本的问题。
    • 您确实不需要 nef 将多面体复制到表面网格中,只需使用 copy_face_graph()
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-13
    • 2014-12-25
    相关资源
    最近更新 更多