CGAL/cgal

TDS_3 with indices: how to deal with cached circumcenters? (Delaunay_triangulation_cell_base_with_circumcenter_3 and others)

Opened this issue · 0 comments

@afabri :

For the cell with cached circumcenter we use std::optional<Point> instead of a pointer to a 3D point and it should probably be a std::unique_ptr.

@lrineau's proposal is the following:

If the TDS can add property maps, a cell property map of Point_3 is conditionally added. At first, it is the null property map (with nullptr). If the member function t.add_circumcenter_property_map(), then the property map is created, the member function dual(Cell_handle) uses it.

See commit 4b62935:

  • I have created a mixing class (base class with CRTP):
    template <typename Derived_triangulation, typename Geom_traits, typename Tds>
    class Cache_cell_circumcenter_with_property_maps
    {
    public:
    void add_circumcenter_property_map() {
    if constexpr(Tds::has_property_maps) {
    using Point = typename Geom_traits::Point_3;
    this->circumcenter_pmap = static_cast<Derived_triangulation*>(this)
    ->tds()
    .template add_property_map<Cell_index, std::optional<Point>>()
    .first;
    }
    }
    protected:
    static auto get_property_point_map_type() {
    if constexpr(Tds::has_property_maps) {
    using Point = typename Geom_traits::Point_3;
    using Concurrency_tag = typename Tds::Concurrency_tag;
    return Property_map<typename Tds::Cell_index, std::optional<Point>, Concurrency_tag>{};
    } else {
    return Null_tag{};
    }
    }
    using Circumcenter_property_map = decltype(get_property_point_map_type());
    CGAL_NO_UNIQUE_ADDRESS Circumcenter_property_map circumcenter_pmap;
    };
    } /// namespace CGAL
  • Delaunay_3 and Regular_3 use that mixing:
    template <class Gt, class Tds_>
    using Delaunay_triangulation_3_tds = typename Default::Get<
    Tds_,
    Triangulation_data_structure_3<Triangulation_vertex_base_3<Gt>, Delaunay_triangulation_cell_base_3<Gt>>>::type;
    // There is a specialization Delaunay_triangulation_3<Gt, Tds, Fast_location>
    // defined in <CGAL/Triangulation_3/internal/Delaunay_triangulation_hierarchy_3.h>.
    // Here is the specialization Delaunay_triangulation_3<Gt, Tds>, with three
    // arguments, that is if Location_policy being the default value 'Default'.
    template <class Gt, class Tds_, class Lock_data_structure_>
    class Delaunay_triangulation_3<Gt, Tds_, Default, Lock_data_structure_>
    : public Triangulation_3<
    Gt,
    Delaunay_triangulation_3_tds<Gt, Tds_>,
    Lock_data_structure_>
    , public Cache_cell_circumcenter_with_property_maps<
    Delaunay_triangulation_3<Gt, Tds_, Default, Lock_data_structure_>,
    Gt,
    Delaunay_triangulation_3_tds<Gt, Tds_>>
    {
    typedef Delaunay_triangulation_3_tds<Gt, Tds_> Tds;
  • the dual(Cell_handle) member function use that property map is it is created:
    template < class Gt, class Tds, class Lds >
    typename Delaunay_triangulation_3<Gt,Tds,Default,Lds>::Point
    Delaunay_triangulation_3<Gt,Tds,Default,Lds>::
    dual(Cell_handle c) const
    {
    CGAL_precondition(dimension()==3);
    CGAL_precondition(! is_infinite(c));
    if constexpr (Tds::has_property_maps) {
    if(this->circumcenter_pmap) {
    auto& opt_point = this->circumcenter_pmap[c->index()];
    if(opt_point.has_value())
    return *opt_point;
    else {
    opt_point = construct_circumcenter(point(c, 0), point(c, 1),
    point(c, 2), point(c, 3));
    return *opt_point;
    }
    }
    return construct_circumcenter(point(c, 0), point(c, 1),
    point(c, 2), point(c, 3));
    } else {
    return c->circumcenter(geom_traits());
    }
    }

TODO:

  • i forgot to change the dual(Cell_handle) member function of Rt_3.