CGAL:带信息点的 3D 凸包

CGAL: 3D Convex Hull with Points with info

我正在尝试使用 CGAL's 3D Convex Hull generation function with a Point_with_info. This is similar to this question 但用于 3D 而不是 2D。我正在尝试遵循使用转发仿函数的相同策略,但我遇到了很多错误,我希望转发仿函数能够处理这些错误。以下是我尝试使用的完整代码:

#include <vector>
#include <utility>
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Convex_hull_traits_3.h>
#include <CGAL/convex_hull_3.h>
#include <CGAL/Surface_mesh.h>

typedef CGAL::Exact_predicates_inexact_constructions_kernel K;
typedef K::Point_3 Point_3;
typedef std::pair<Point_3, unsigned> Point_with_info;
typedef CGAL::Surface_mesh<Point_with_info> Surface_mesh;

template <class F>
struct Forward_functor
    : public F
{
    template <class Point_3>
    bool operator()(const Point_3 &p, const Point_3 &q) const
    {
        return static_cast<const F *>(this)->operator()(p.first, q.first);
    }

    template <class Point_3>
    bool operator()(const Point_3 &p, const Point_3 &q, const Point_3 &r) const
    {
        return static_cast<const F *>(this)->operator()(p.first, q.first, r.first);
    }

    template <class Point_3>
    bool operator()(const Point_3 &p, const Point_3 &q, const Point_3 &r, const Point_3 &s) const
    {
        return static_cast<const F *>(this)->operator()(p.first, q.first, r.first, s.first);
    }
};

struct CH_traits_for_point_with_info
{
    typedef Point_with_info Point_3;
    typedef CGAL::Convex_hull_traits_3<K> Base;
    typedef Base::Plane_3 Plane_3;

    typedef Forward_functor<Base::Segment_3> Segment_3;
    typedef Forward_functor<Base::Triangle_3> Triangle_3;
    typedef Forward_functor<Base::Vector_3> Vector_3;

    typedef Base::Polygon_mesh Polyhedron_3;

    typedef Forward_functor<Base::Construct_segment_3> Construct_segment_3;
    typedef Forward_functor<Base::Construct_ray_3> Construct_ray_3;

    class Construct_plane_3
    {
    public:
        Plane_3 operator()(const Point_3 &p, const Point_3 &q, const Point_3 &r) const
        {
            return Base::Plane_3(p.first, q.first, r.first);
        }
    };

    typedef Forward_functor<Base::Construct_triangle_3> Construct_triangle_3;
    typedef Forward_functor<Base::Construct_centroid_3> Construct_centroid_3;
    typedef Forward_functor<Base::Construct_orthogonal_vector_3> Construct_orthogonal_vector_3;

    typedef Forward_functor<Base::Equal_3> Equal_3;
    typedef Forward_functor<Base::Orientation_3> Orientation_3;
    typedef Forward_functor<Base::Collinear_3> Collinear_3;
    typedef Forward_functor<Base::Coplanar_3> Coplanar_3;
    typedef Forward_functor<Base::Less_distance_to_point_3> Less_distance_to_point_3;

    typedef Forward_functor<Base::Has_on_positive_side_3> Has_on_positive_side_3;

    typedef Forward_functor<Base::Less_signed_distance_to_plane_3> Less_signed_distance_to_plane_3;

    // required for degenerate case of all points coplanar
    typedef Forward_functor<Base::Traits_xy_3> Traits_xy_3;
    typedef Forward_functor<Base::Traits_yz_3> Traits_yz_3;
    typedef Forward_functor<Base::Traits_xz_3> Traits_xz_3;
    Traits_xy_3 construct_traits_xy_3_object() const
    {
        return Traits_xy_3();
    }
    Traits_yz_3 construct_traits_yz_3_object() const
    {
        return Traits_yz_3();
    }
    Traits_xz_3 construct_traits_xz_3_object() const
    {
        return Traits_xz_3();
    }

    typedef Forward_functor<Base::Construct_vector_3> Construct_vector_3;
    // for postcondition checking
    typedef Forward_functor<Base::Ray_3> Ray_3;

    typedef Forward_functor<Base::Has_on_3> Has_on_3;
    typedef Forward_functor<Base::Oriented_side_3> Oriented_side_3;
    typedef Forward_functor<Base::Do_intersect_3> Do_intersect_3;

    Construct_segment_3
    construct_segment_3_object() const
    {
        return Construct_segment_3();
    }

    Construct_ray_3
    construct_ray_3_object() const
    {
        return Construct_ray_3();
    }

    Construct_plane_3
    construct_plane_3_object() const
    {
        return Construct_plane_3();
    }

    Construct_triangle_3
    construct_triangle_3_object() const
    {
        return Construct_triangle_3();
    }

    Construct_centroid_3
    construct_centroid_3_object() const
    {
        return Construct_centroid_3();
    }

    Construct_orthogonal_vector_3
    construct_orthogonal_vector_3_object() const
    {
        return Construct_orthogonal_vector_3();
    }

    Collinear_3
    collinear_3_object() const
    {
        return Collinear_3();
    }

    Coplanar_3
    coplanar_3_object() const
    {
        return Coplanar_3();
    }

    Has_on_3
    has_on_3_object() const
    {
        return Has_on_3();
    }

    Less_distance_to_point_3
    less_distance_to_point_3_object() const
    {
        return Less_distance_to_point_3();
    }

    Has_on_positive_side_3
    has_on_positive_side_3_object() const
    {
        return Has_on_positive_side_3();
    }

    Oriented_side_3
    oriented_side_3_object() const
    {
        return Oriented_side_3();
    }

    Equal_3
    equal_3_object() const
    {
        return Equal_3();
    }

    Do_intersect_3
    do_intersect_3_object() const
    {
        return Do_intersect_3();
    }

    Less_signed_distance_to_plane_3
    less_signed_distance_to_plane_3_object() const
    {
        return Less_signed_distance_to_plane_3();
    }

    Orientation_3
    orientation_3_object() const
    {
        return Orientation_3();
    }

    Construct_vector_3
    construct_vector_3_object() const
    {
        return Construct_vector_3();
    }
};

int main(int argc, char *argv[])
{
    // Insert the projected points in a CGAL vertex_with_info vector
    std::vector<std::pair<Point_3, unsigned>> verts;
    verts.push_back(std::make_pair(Point_3(1.0, 0.0, 0.0), 0));
    verts.push_back(std::make_pair(Point_3(0.0, 1.0, 0.0), 1));
    verts.push_back(std::make_pair(Point_3(-1.0, 0., 0.0), 2));
    verts.push_back(std::make_pair(Point_3(0.0, -1., 0.0), 3));
    verts.push_back(std::make_pair(Point_3(0.0, 0.0, 1.0), 4));
    verts.push_back(std::make_pair(Point_3(0.0, 0.0, -1.), 5));

    Surface_mesh sm;
    CGAL::convex_hull_3(verts.begin(), verts.end(), sm, CH_traits_for_point_with_info());
    std::cout << "The convex hull contains " << num_vertices(sm) << " vertices" << std::endl;
    return 0;
}

C++ 中的模板编程通常会出现大量错误,因此我不会发布它们。请帮忙。

更新:根据@AndreasFabri 的评论,我的解决方案太复杂了。您可以根据已在 CGAL https://gist.github.com/afabri/a32f0d1ac5af1a99491d62786a0d5559 中实现的内容找到更短的解决方案。我正在复制以下相同的代码:

#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Surface_mesh.h>
#include <CGAL/convex_hull_3.h>
#include <CGAL/Extreme_points_traits_adapter_3.h>
#include <vector>
#include <fstream>

typedef CGAL::Exact_predicates_inexact_constructions_kernel  K;

typedef K::Point_3                                Point_3;
typedef std::pair<Point_3,int>                    Point;

typedef CGAL::First_of_pair_property_map<Point>   Pmap;
typedef CGAL::Extreme_points_traits_adapter_3<Pmap,CGAL::Convex_hull_traits_3<K> > CHT;

typedef CGAL::Surface_mesh<Point>                 Surface_mesh;


int main(int argc, char* argv[])
{
  std::ifstream in( (argc>1)? argv[1] : "data/cube.xyz");
  std::vector<Point> points;
  Point_3 p;
  int i = 0;
  while(in >> p){
    points.push_back(std::make_pair(p,i++));
  }

  Surface_mesh sm;
  CGAL::convex_hull_3(points.begin(), points.end(), sm,
                      CHT(Pmap()));

  std::cout << "The convex hull contains " << num_vertices(sm) << " vertices" << std::endl;
  return 0;
}

忽略下面的答案:

我能够通过更正以下内容来编译它:

  1. Forward_functors 仅适用于返回 bool 的函子。对于所有其他人,我必须构建一个 class/struct 以手动从 std::pair 传递 Point_3
  2. 我不得不为 2D-Convex Hull 写一个 Traits class。简单地传递给 Projection_xy 等是行不通的。
  3. 我已经从我编写的 classes 中删除了所有模板参数,因为我不打算将它们用于许多不同的内核。我只使用 CGAL::Epick.
  4. 我不得不痛苦地阅读并理解模板代码中的每一个错误。但最后它似乎起作用了。
#include <vector>
#include <utility>
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/convex_hull_3.h>
#include <CGAL/Surface_mesh.h>
#include <CGAL/Convex_hull_traits_3.h>
#include <CGAL/convex_hull_traits_2.h>

typedef CGAL::Exact_predicates_inexact_constructions_kernel K;
typedef std::pair<K::Point_3, unsigned> Point_with_info;
typedef CGAL::Surface_mesh<Point_with_info> Surface_mesh;

template <class F>
struct Forward_functor
    : public F
{
    template <class Point_3>
    bool operator()(const Point_3 &p, const Point_3 &q) const
    {
        return static_cast<const F *>(this)->operator()(p.first, q.first);
    }

    template <class Point_3>
    bool operator()(const Point_3 &p, const Point_3 &q, const Point_3 &r) const
    {
        return static_cast<const F *>(this)->operator()(p.first, q.first, r.first);
    }

    template <class Point_3>
    bool operator()(const Point_3 &p, const Point_3 &q, const Point_3 &r, const Point_3 &s) const
    {
        return static_cast<const F *>(this)->operator()(p.first, q.first, r.first, s.first);
    }
};

template <class F>
struct Forward_functor_xy
    : public F
{
    template <class Point_3>
    bool operator()(const Point_3 &p, const Point_3 &q) const
    {
        K::Point_2 a(p.first.x(), p.first.y());
        K::Point_2 b(q.first.x(), q.first.y());
        return static_cast<const F *>(this)->operator()(a, b);
    }

    template <class Point_3>
    bool operator()(const Point_3 &p, const Point_3 &q, const Point_3 &r) const
    {
        K::Point_2 a(p.first.x(), p.first.y());
        K::Point_2 b(q.first.x(), q.first.y());
        K::Point_2 c(r.first.x(), r.first.y());
        return static_cast<const F *>(this)->operator()(a, b, c);
    }

    template <class Point_3>
    bool operator()(const Point_3 &p, const Point_3 &q, const Point_3 &r, const Point_3 &s) const
    {
        K::Point_2 a(p.first.x(), p.first.y());
        K::Point_2 b(q.first.x(), q.first.y());
        K::Point_2 c(r.first.x(), r.first.y());
        K::Point_2 d(s.first.x(), s.first.y());
        return static_cast<const F *>(this)->operator()(a, b, c, d);
    }
};

template <class F>
struct Forward_functor_yz
    : public F
{
    template <class Point_3>
    bool operator()(const Point_3 &p, const Point_3 &q) const
    {
        K::Point_2 a(p.first.y(), p.first.z());
        K::Point_2 b(q.first.y(), q.first.z());
        return static_cast<const F *>(this)->operator()(a, b);
    }

    template <class Point_3>
    bool operator()(const Point_3 &p, const Point_3 &q, const Point_3 &r) const
    {
        K::Point_2 a(p.first.y(), p.first.z());
        K::Point_2 b(q.first.y(), q.first.z());
        K::Point_2 c(r.first.y(), r.first.z());
        return static_cast<const F *>(this)->operator()(a, b, c);
    }

    template <class Point_3>
    bool operator()(const Point_3 &p, const Point_3 &q, const Point_3 &r, const Point_3 &s) const
    {
        K::Point_2 a(p.first.y(), p.first.z());
        K::Point_2 b(q.first.y(), q.first.z());
        K::Point_2 c(r.first.y(), r.first.z());
        K::Point_2 d(s.first.y(), s.first.z());
        return static_cast<const F *>(this)->operator()(a, b, c, d);
    }
};

template <class F>
struct Forward_functor_xz
    : public F
{
    template <class Point_3>
    bool operator()(const Point_3 &p, const Point_3 &q) const
    {
        K::Point_2 a(p.first.x(), p.first.z());
        K::Point_2 b(q.first.x(), q.first.z());
        return static_cast<const F *>(this)->operator()(a, b);
    }

    template <class Point_3>
    bool operator()(const Point_3 &p, const Point_3 &q, const Point_3 &r) const
    {
        K::Point_2 a(p.first.x(), p.first.z());
        K::Point_2 b(q.first.x(), q.first.z());
        K::Point_2 c(r.first.x(), r.first.z());
        return static_cast<const F *>(this)->operator()(a, b, c);
    }

    template <class Point_3>
    bool operator()(const Point_3 &p, const Point_3 &q, const Point_3 &r, const Point_3 &s) const
    {
        K::Point_2 a(p.first.x(), p.first.z());
        K::Point_2 b(q.first.x(), q.first.z());
        K::Point_2 c(r.first.x(), r.first.z());
        K::Point_2 d(s.first.x(), s.first.z());
        return static_cast<const F *>(this)->operator()(a, b, c, d);
    }
};

class Point_with_info_triple
{
protected:
    typedef K::FT FT;
    typedef K::Vector_3 Vector_3;
    typedef Point_with_info Point_3;

    Point_3 p_, q_, r_;

public:
    Point_with_info_triple() {}

    Point_with_info_triple(const Point_3 &p, const Point_3 &q, const Point_3 &r)
        : p_(p), q_(q), r_(r)
    {
    }

    const K::Point_3 &p() const { return p_.first; }
    const K::Point_3 &q() const { return q_.first; }
    const K::Point_3 &r() const { return r_.first; }
};

class Point_with_info_triple_has_on_positive_side_3
{
public:
    typedef Point_with_info Point_3;
    typedef Point_with_info_triple Plane_3;
    bool
    operator()(const Plane_3 &pl, const Point_3 &p) const
    {
        typename K::Orientation_3 o;
        return (o(pl.p(), pl.q(), pl.r(), p.first) == CGAL::POSITIVE);
    }

    typedef bool result_type;
};

class Point_with_info_triple_construct_orthogonal_vector_3
{
public:
    typedef K::Vector_3 Vector_3;
    typedef Point_with_info_triple Plane_3;

    Vector_3 operator()(const Plane_3 &plane) const
    {
        K::Construct_orthogonal_vector_3 construct_orthogonal_vector_3;
        return construct_orthogonal_vector_3(plane.p(), plane.q(), plane.r());
    }
};

class Point_with_info_triple_oriented_side_3
{
public:
    typedef Point_with_info Point_3;
    typedef Point_with_info_triple Plane_3;
    typedef CGAL::Oriented_side result_type;

    result_type
    operator()(const Plane_3 &pl, const Point_3 &p) const
    {
        K::Orientation_3 o;
        CGAL::Orientation ori = o(pl.p(), pl.q(), pl.r(), p.first);
        if (ori > 0)
            return CGAL::ON_POSITIVE_SIDE;
        if (ori < 0)
            return CGAL::ON_NEGATIVE_SIDE;
        return CGAL::ON_ORIENTED_BOUNDARY;
    }
};

class Point_with_info_triple_less_signed_distance_to_plane_3
{
public:
    typedef Point_with_info Point_3;
    typedef Point_with_info_triple Plane_3;

    typedef bool result_type;

    bool
    operator()(const Plane_3 &h, const Point_3 &p, const Point_3 &q) const
    {
        const K::Point_3 &hp = h.p();
        const K::Point_3 &hq = h.q();
        const K::Point_3 &hr = h.r();
        K::Less_signed_distance_to_plane_3 less_signed_distance_to_plane_3;
        return less_signed_distance_to_plane_3(hp, hq, hr, p.first, q.first);
    }
};

class CH_traits_for_point_with_info
{
public:
    typedef K::Segment_3 Segment_3;
    typedef K::Triangle_3 Triangle_3;
    typedef K::Vector_3 Vector_3;
    typedef CGAL::Convex_hull_traits_3<K, Surface_mesh> Base;
    typedef Point_with_info Point_3;
    typedef Point_with_info_triple Plane_3;
    typedef Surface_mesh Polyhedron_3;

    typedef Base::Construct_segment_3 Construct_segment_3;
    typedef Base::Construct_ray_3 Construct_ray_3;
    typedef Base::Construct_triangle_3 Construct_triangle_3;
    typedef Base::Construct_centroid_3 Construct_centroid_3;

    class Construct_plane_3
    {
    public:
        Plane_3 operator()(const Point_3 &p, const Point_3 &q, const Point_3 &r) const
        {
            return Plane_3(p, q, r);
        }
    };

    typedef Point_with_info_triple_construct_orthogonal_vector_3 Construct_orthogonal_vector_3;

    typedef Forward_functor<K::Equal_3> Equal_3;
    typedef Forward_functor<K::Orientation_3> Orientation_3;
    typedef Forward_functor<K::Collinear_3> Collinear_3;
    typedef Forward_functor<K::Coplanar_3> Coplanar_3;
    typedef Forward_functor<K::Less_distance_to_point_3> Less_distance_to_point_3;

    typedef Point_with_info_triple_has_on_positive_side_3 Has_on_positive_side_3;
    typedef Point_with_info_triple_less_signed_distance_to_plane_3
        Less_signed_distance_to_plane_3;

    // required for degenerate case of all points coplanar
    class Traits_xy_3
    {
    public:
        typedef Point_with_info Point_2;
        typedef CGAL::convex_hull_traits_2<K> Base;
        typedef Forward_functor_xy<Base::Less_xy_2> Less_xy_2;
        typedef Forward_functor_xy<Base::Less_yx_2> Less_yx_2;
        typedef Forward_functor_xy<Base::Left_turn_2> Left_turn_2;
        typedef Forward_functor_xy<Base::Equal_2> Equal_2;
        struct Orientation_2
        {
            CGAL::Orientation
            operator()(const Point_2 &p, const Point_2 &q, const Point_2 &r) const
            {
                K::Point_2 a(p.first.x(), p.first.y());
                K::Point_2 b(q.first.x(), q.first.y());
                K::Point_2 c(r.first.x(), r.first.y());
                return Base::Orientation_2()(a, b, c);
            }
        };

        Less_xy_2 less_xy_2_object() const
        {
            return Less_xy_2();
        }
        Less_yx_2 less_yx_2_object() const
        {
            return Less_yx_2();
        }
        Left_turn_2 left_turn_2_object() const
        {
            return Left_turn_2();
        }
        Equal_2 equal_2_object() const
        {
            return Equal_2();
        }
        Orientation_2 orientation_2_object() const
        {
            return Orientation_2();
        }
    };

    class Traits_yz_3
    {
    public:
        typedef Point_with_info Point_2;
        typedef CGAL::convex_hull_traits_2<K> Base;
        typedef Forward_functor_yz<Base::Less_xy_2> Less_xy_2;
        typedef Forward_functor_yz<Base::Less_yx_2> Less_yx_2;
        typedef Forward_functor_yz<Base::Left_turn_2> Left_turn_2;
        typedef Forward_functor_yz<Base::Equal_2> Equal_2;
        struct Orientation_2
        {
            CGAL::Orientation
            operator()(const Point_2 &p, const Point_2 &q, const Point_2 &r) const
            {
                K::Point_2 a(p.first.y(), p.first.z());
                K::Point_2 b(q.first.y(), q.first.z());
                K::Point_2 c(r.first.y(), r.first.z());
                return Base::Orientation_2()(a, b, c);
            }
        };

        Less_xy_2 less_xy_2_object() const
        {
            return Less_xy_2();
        }
        Less_yx_2 less_yx_2_object() const
        {
            return Less_yx_2();
        }
        Left_turn_2 left_turn_2_object() const
        {
            return Left_turn_2();
        }
        Equal_2 equal_2_object() const
        {
            return Equal_2();
        }
        Orientation_2 orientation_2_object() const
        {
            return Orientation_2();
        }
    };

    class Traits_xz_3
    {
    public:
        typedef Point_with_info Point_2;
        typedef CGAL::convex_hull_traits_2<K> Base;
        typedef Forward_functor_xz<Base::Less_xy_2> Less_xy_2;
        typedef Forward_functor_xz<Base::Less_yx_2> Less_yx_2;
        typedef Forward_functor_xz<Base::Left_turn_2> Left_turn_2;
        typedef Forward_functor_xz<Base::Equal_2> Equal_2;
        struct Orientation_2
        {
            CGAL::Orientation
            operator()(const Point_2 &p, const Point_2 &q, const Point_2 &r) const
            {
                K::Point_2 a(p.first.x(), p.first.z());
                K::Point_2 b(q.first.x(), q.first.z());
                K::Point_2 c(r.first.x(), r.first.z());
                return Base::Orientation_2()(a, b, c);
            }
        };

        Less_xy_2 less_xy_2_object() const
        {
            return Less_xy_2();
        }
        Less_yx_2 less_yx_2_object() const
        {
            return Less_yx_2();
        }
        Left_turn_2 left_turn_2_object() const
        {
            return Left_turn_2();
        }
        Equal_2 equal_2_object() const
        {
            return Equal_2();
        }
        Orientation_2 orientation_2_object() const 
        {
            return Orientation_2();
        }
    };

    Traits_xy_3 construct_traits_xy_3_object() const
    {
        return Traits_xy_3();
    }
    Traits_yz_3 construct_traits_yz_3_object() const
    {
        return Traits_yz_3();
    }
    Traits_xz_3 construct_traits_xz_3_object() const
    {
        return Traits_xz_3();
    }

    typedef Base::Construct_vector_3 Construct_vector_3;

    // for postcondition checking
    typedef K::Ray_3 Ray_3;
    typedef Forward_functor<K::Has_on_3> Has_on_3;
    typedef Point_with_info_triple_oriented_side_3 Oriented_side_3;
    typedef Forward_functor<K::Do_intersect_3> Do_intersect_3;

    Construct_segment_3
    construct_segment_3_object() const
    {
        return Construct_segment_3();
    }

    Construct_ray_3
    construct_ray_3_object() const
    {
        return Construct_ray_3();
    }

    Construct_plane_3
    construct_plane_3_object() const
    {
        return Construct_plane_3();
    }

    Construct_triangle_3
    construct_triangle_3_object() const
    {
        return Construct_triangle_3();
    }

    Construct_centroid_3
    construct_centroid_3_object() const
    {
        return Construct_centroid_3();
    }

    Construct_orthogonal_vector_3
    construct_orthogonal_vector_3_object() const
    {
        return Construct_orthogonal_vector_3();
    }

    Collinear_3
    collinear_3_object() const
    {
        return Collinear_3();
    }

    Coplanar_3
    coplanar_3_object() const
    {
        return Coplanar_3();
    }

    Has_on_3
    has_on_3_object() const
    {
        return Has_on_3();
    }

    Less_distance_to_point_3
    less_distance_to_point_3_object() const
    {
        return Less_distance_to_point_3();
    }

    Has_on_positive_side_3
    has_on_positive_side_3_object() const
    {
        return Has_on_positive_side_3();
    }

    Oriented_side_3
    oriented_side_3_object() const
    {
        return Oriented_side_3();
    }

    Equal_3
    equal_3_object() const
    {
        return Equal_3();
    }

    Do_intersect_3
    do_intersect_3_object() const
    {
        return Do_intersect_3();
    }

    Less_signed_distance_to_plane_3
    less_signed_distance_to_plane_3_object() const
    {
        return Less_signed_distance_to_plane_3();
    }

    Orientation_3
    orientation_3_object() const
    {
        return Orientation_3();
    }

    Construct_vector_3
    construct_vector_3_object() const
    {
        return Construct_vector_3();
    }
};

int main(int argc, char *argv[])
{
    // Insert the projected points in a CGAL vertex_with_info vector
    std::vector<std::pair<K::Point_3, unsigned>> verts;
    verts.push_back(std::make_pair(K::Point_3(1.0, 0.0, 0.0), 0));
    verts.push_back(std::make_pair(K::Point_3(0.0, 1.0, 0.0), 1));
    verts.push_back(std::make_pair(K::Point_3(-1.0, 0., 0.0), 2));
    verts.push_back(std::make_pair(K::Point_3(0.0, -1., 0.0), 3));
    verts.push_back(std::make_pair(K::Point_3(0.0, 0.0, 1.0), 4));
    verts.push_back(std::make_pair(K::Point_3(0.0, 0.0, -1.), 5));

    Surface_mesh sm;
    CGAL::convex_hull_3(verts.begin(), verts.end(), sm, CH_traits_for_point_with_info());
    std::cout << "The convex hull contains " << num_vertices(sm) << " vertices" << std::endl;
    return 0;
}