diff --git a/Property_map/include/CGAL/Properties.h b/Property_map/include/CGAL/Properties.h index 94e7dd729d1..bbcb00959bb 100644 --- a/Property_map/include/CGAL/Properties.h +++ b/Property_map/include/CGAL/Properties.h @@ -273,6 +273,15 @@ public: return dynamic_cast&>(*m_property_arrays.at(name)); } + template + std::optional>> get_property_if_exists(const std::string& name) { + auto it = m_property_arrays.find(name); + if (it == m_property_arrays.end()) return {}; + auto [_, array] = *it; + if (typeid(*array) != typeid(Property_array)) return {}; + return dynamic_cast&>(*m_property_arrays.at(name)); + } + /*! * Removes a property array from the container * diff --git a/Surface_mesh/include/CGAL/Surface_mesh/IO/OFF.h b/Surface_mesh/include/CGAL/Surface_mesh/IO/OFF.h index 583a25e3eb3..f746b55a2ce 100644 --- a/Surface_mesh/include/CGAL/Surface_mesh/IO/OFF.h +++ b/Surface_mesh/include/CGAL/Surface_mesh/IO/OFF.h @@ -110,7 +110,7 @@ bool read_OFF_with_or_without_fcolors(std::istream& is, bool is_fcm_requested = !(is_default_parameter::value); if (is_fcm_requested || scanner.has_colors()) { - auto [fcm, created] = sm.template property_map("f:color"); + auto [fcm, created] = sm.template add_property_map("f:color"); return CGAL::IO::internal::read_OFF_BGL(is, sm, np.face_color_map(fcm)); } else { return CGAL::IO::internal::read_OFF_BGL(is, sm, np); @@ -136,7 +136,7 @@ bool read_OFF_with_or_without_vtextures(std::istream& is, bool is_vtm_requested = !(is_default_parameter::value); if (is_vtm_requested || scanner.has_textures()) { - auto [vtm, created] = sm.template property_map("v:texcoord"); + auto [vtm, created] = sm.template add_property_map("v:texcoord"); return read_OFF_with_or_without_fcolors(is, sm, scanner, np.vertex_texture_map(vtm)); } else { return read_OFF_with_or_without_fcolors(is, sm, scanner, np); @@ -161,7 +161,7 @@ bool read_OFF_with_or_without_vcolors(std::istream& is, bool is_vcm_requested = !(is_default_parameter::value); if (is_vcm_requested || scanner.has_colors()) { - auto [vcm, created] = sm.template property_map("v:color"); + auto [vcm, created] = sm.template add_property_map("v:color"); return read_OFF_with_or_without_vtextures(is, sm, scanner, np.vertex_color_map(vcm)); } else { return read_OFF_with_or_without_vtextures(is, sm, scanner, np); @@ -187,7 +187,7 @@ bool read_OFF_with_or_without_vnormals(std::istream& is, bool is_vnm_requested = !(is_default_parameter::value); if (is_vnm_requested || scanner.has_normals()) { - auto [vnm, created] = sm.template property_map("v:normal"); + auto [vnm, created] = sm.template add_property_map("v:normal"); return read_OFF_with_or_without_vcolors(is, sm, scanner, np.vertex_normal_map(vnm)); } else { return read_OFF_with_or_without_vcolors(is, sm, scanner, np); @@ -338,10 +338,10 @@ bool write_OFF_with_or_without_fcolors(std::ostream& os, const bool has_fcolors = !(is_default_parameter::value); - auto [fcolors, has_internal_fcolors] = sm.template property_map("f:color"); + auto fcolors = sm.template property_map("f:color"); - if(!has_fcolors && has_internal_fcolors && fcolors.size() > 0) - return write_OFF_BGL(os, sm, np.face_color_map(fcolors)); + if(!has_fcolors && fcolors && fcolors->size() > 0) + return write_OFF_BGL(os, sm, np.face_color_map(fcolors.value())); else return write_OFF_BGL(os, sm, np); } @@ -361,10 +361,10 @@ bool write_OFF_with_or_without_vtextures(std::ostream& os, const bool has_vtextures = !(is_default_parameter::value); - auto [vtextures, has_internal_vtextures] = sm.template property_map("v:texcoord"); + auto vtextures = sm.template property_map("v:texcoord"); - if(!has_vtextures && has_internal_vtextures && vtextures.size() > 0) - return write_OFF_with_or_without_fcolors(os, sm, np.vertex_texture_map(vtextures)); + if(!has_vtextures && vtextures && vtextures->size() > 0) + return write_OFF_with_or_without_fcolors(os, sm, np.vertex_texture_map(vtextures.value())); else return write_OFF_with_or_without_fcolors(os, sm, np); } @@ -382,10 +382,10 @@ bool write_OFF_with_or_without_vcolors(std::ostream& os, const bool has_vcolors = !(is_default_parameter::value); - auto [vcolors, has_internal_vcolors] = sm.template property_map("v:color"); + auto vcolors = sm.template property_map("v:color"); - if(!has_vcolors && has_internal_vcolors && vcolors.size() > 0) - return write_OFF_with_or_without_vtextures(os, sm, np.vertex_color_map(vcolors)); + if(!has_vcolors && vcolors && vcolors->size() > 0) + return write_OFF_with_or_without_vtextures(os, sm, np.vertex_color_map(vcolors.value())); else return write_OFF_with_or_without_vtextures(os, sm, np); } @@ -405,10 +405,10 @@ bool write_OFF_with_or_without_vnormals(std::ostream& os, const bool has_vnormals = !(is_default_parameter::value); - auto [vnormals, has_internal_vnormals] = sm.template property_map("v:normal"); + auto vnormals = sm.template property_map("v:normal"); - if(!has_vnormals && has_internal_vnormals && vnormals.size() > 0) - return write_OFF_with_or_without_vcolors(os, sm, np.vertex_normal_map(vnormals)); + if(!has_vnormals && vnormals && vnormals->size() > 0) + return write_OFF_with_or_without_vcolors(os, sm, np.vertex_normal_map(vnormals.value())); else return write_OFF_with_or_without_vcolors(os, sm, np); } diff --git a/Surface_mesh/include/CGAL/Surface_mesh/IO/PLY.h b/Surface_mesh/include/CGAL/Surface_mesh/IO/PLY.h index 74830af23ad..4f1f50dde98 100644 --- a/Surface_mesh/include/CGAL/Surface_mesh/IO/PLY.h +++ b/Surface_mesh/include/CGAL/Surface_mesh/IO/PLY.h @@ -458,12 +458,10 @@ bool fill_simplex_specific_header(std::ostream& os, return true; } - bool okay = false; if(prop == "v:normal") { - Vector_map pmap; - boost::tie(pmap, okay) = sm.template property_map(prop); - if(okay) + auto pmap = sm.template property_map(prop); + if(pmap) { if(std::is_same::value) { @@ -477,23 +475,22 @@ bool fill_simplex_specific_header(std::ostream& os, << "property double ny" << std::endl << "property double nz" << std::endl; } - printers.push_back(new Property_printer(pmap)); + printers.push_back(new Property_printer(pmap.value())); return true; } } if(prop == "v:color") { - Vcolor_map pmap; - boost::tie(pmap, okay) = sm.template property_map(prop); - if(okay) + auto pmap = sm.template property_map(prop); + if(pmap) { os << "property uchar red" << std::endl << "property uchar green" << std::endl << "property uchar blue" << std::endl << "property uchar alpha" << std::endl; - printers.push_back(new Property_printer(pmap)); + printers.push_back(new Property_printer(pmap.value())); return true; } } @@ -515,19 +512,17 @@ bool fill_simplex_specific_header(std::ostream& os, if(prop == "f:connectivity" || prop == "f:removed") return true; - bool okay = false; if(prop == "f:color") { - Fcolor_map pmap; - boost::tie(pmap, okay) = sm.template property_map(prop); - if(okay) + auto pmap = sm.template property_map(prop); + if(pmap) { os << "property uchar red" << std::endl << "property uchar green" << std::endl << "property uchar blue" << std::endl << "property uchar alpha" << std::endl; - printers.push_back(new Property_printer(pmap)); + printers.push_back(new Property_printer(pmap.value())); return true; } } @@ -652,44 +647,40 @@ void fill_header(std::ostream& os, const Surface_mesh& sm, typedef typename SMesh::Vertex_index VIndex; using VCM = typename internal_np::Lookup_named_param_def< - internal_np::vertex_color_map_t, - CGAL_NP_CLASS, - typename Surface_mesh::template Property_map >::type; - // typedef typename internal_np::Lookup_named_param_def< - // internal_np::vertex_color_map_t, CGAL_NP_CLASS, - // Constant_property_map >::type VCM; + internal_np::vertex_color_map_t, CGAL_NP_CLASS, + typename Surface_mesh::template Property_map + >::type; + using FCM = typename internal_np::Lookup_named_param_def< + internal_np::face_color_map_t, CGAL_NP_CLASS, + typename Surface_mesh::template Property_map + >::type; using parameters::choose_parameter; using parameters::is_default_parameter; using parameters::get_parameter; - VCM vcm = choose_parameter(get_parameter(np, internal_np::vertex_color_map)); - bool has_vcolor = !is_default_parameter::value; - - using FCM = typename internal_np::Lookup_named_param_def< - internal_np::face_color_map_t, - CGAL_NP_CLASS, - typename Surface_mesh::template Property_map >::type; - FCM fcm = choose_parameter(get_parameter(np, internal_np::face_color_map)); - bool has_fcolor = !is_default_parameter::value; + constexpr bool has_vcolor = !is_default_parameter::value; + constexpr bool has_fcolor = !is_default_parameter::value; std::vector prop = sm.template properties(); - if (std::is_same::value && has_fcolor) { + if constexpr (std::is_same::value && has_fcolor) { os << "property uchar red" << std::endl << "property uchar green" << std::endl << "property uchar blue" << std::endl << "property uchar alpha" << std::endl; + FCM fcm = get_parameter(np, internal_np::face_color_map); add_color_map()(printers, fcm); } - if (std::is_same::value && has_vcolor) + if constexpr (std::is_same::value && has_vcolor) { os << "property uchar red" << std::endl << "property uchar green" << std::endl << "property uchar blue" << std::endl << "property uchar alpha" << std::endl; + VCM vcm = get_parameter(np, internal_np::vertex_color_map); add_color_map()(printers, vcm); } @@ -708,94 +699,93 @@ void fill_header(std::ostream& os, const Surface_mesh& sm, // Cut the "v:" prefix std::string name = get_property_raw_name(prop[i], Simplex()); - bool okay = false; { - auto [pmap, okay] = sm.template property_map(prop[i]); - if(okay) + auto pmap = sm.template property_map(prop[i]); + if(pmap) { os << "property char " << name << std::endl; - printers.push_back(new internal::Char_property_printer(pmap)); + printers.push_back(new internal::Char_property_printer(pmap.value())); continue; } } { - auto [pmap, okay] = sm.template property_map(prop[i]); - if(okay) + auto pmap = sm.template property_map(prop[i]); + if(pmap) { os << "property uchar " << name << std::endl; - printers.push_back(new internal::Char_property_printer(pmap)); + printers.push_back(new internal::Char_property_printer(pmap.value())); continue; } } { - auto [pmap, okay] = sm.template property_map(prop[i]); - if(okay) + auto pmap = sm.template property_map(prop[i]); + if(pmap) { os << "property short " << name << std::endl; - printers.push_back(new internal::Simple_property_printer(pmap)); + printers.push_back(new internal::Simple_property_printer(pmap.value())); continue; } } { - auto [pmap, okay] = sm.template property_map(prop[i]); - if(okay) + auto pmap = sm.template property_map(prop[i]); + if(pmap) { os << "property ushort " << name << std::endl; - printers.push_back(new internal::Simple_property_printer(pmap)); + printers.push_back(new internal::Simple_property_printer(pmap.value())); continue; } } { - auto [pmap, okay] = sm.template property_map(prop[i]); - if(okay) + auto pmap = sm.template property_map(prop[i]); + if(pmap) { os << "property int " << name << std::endl; - printers.push_back(new internal::Simple_property_printer(pmap)); + printers.push_back(new internal::Simple_property_printer(pmap.value())); continue; } } { - auto [pmap, okay] = sm.template property_map(prop[i]); - if(okay) + auto pmap = sm.template property_map(prop[i]); + if(pmap) { os << "property uint " << name << std::endl; - printers.push_back(new internal::Simple_property_printer(pmap)); + printers.push_back(new internal::Simple_property_printer(pmap.value())); continue; } } { - auto [pmap, okay] = sm.template property_map(prop[i]); - if(okay) + auto pmap = sm.template property_map(prop[i]); + if(pmap) { os << "property int " << name << std::endl; - printers.push_back(new internal::Simple_property_printer(pmap)); + printers.push_back(new internal::Simple_property_printer(pmap.value())); continue; } } { - auto [pmap, okay] = sm.template property_map(prop[i]); - if(okay) + auto pmap = sm.template property_map(prop[i]); + if(pmap) { os << "property uint " << name << std::endl; - printers.push_back(new internal::Simple_property_printer(pmap)); + printers.push_back(new internal::Simple_property_printer(pmap.value())); continue; } } { - auto [pmap, okay] = sm.template property_map(prop[i]); - if(okay) + auto pmap = sm.template property_map(prop[i]); + if(pmap) { os << "property float " << name << std::endl; - printers.push_back(new internal::Simple_property_printer(pmap)); + printers.push_back(new internal::Simple_property_printer(pmap.value())); continue; } } { - auto [pmap, okay] = sm.template property_map(prop[i]); - if(okay) + auto pmap = sm.template property_map(prop[i]); + if(pmap) { os << "property double " << name << std::endl; - printers.push_back(new internal::Simple_property_printer(pmap)); + printers.push_back(new internal::Simple_property_printer(pmap.value())); continue; } } diff --git a/Surface_mesh/include/CGAL/Surface_mesh/Surface_mesh.h b/Surface_mesh/include/CGAL/Surface_mesh/Surface_mesh.h index d9ea94793f7..5cea7e1a744 100644 --- a/Surface_mesh/include/CGAL/Surface_mesh/Surface_mesh.h +++ b/Surface_mesh/include/CGAL/Surface_mesh/Surface_mesh.h @@ -1881,13 +1881,21 @@ public: } /// returns a property map named `name` with key type `I` and value type `T`, - /// and a Boolean that is `true` if the property was created. + /// if such a property map exists template - std::pair, bool> + std::optional> + property_map(const std::string& name) { + auto maybe_property_map = get_property_container().template get_property_if_exists(name); + if (!maybe_property_map) return {}; + else return {{maybe_property_map.value()}}; + } + + template + std::optional> property_map(const std::string& name) const { - auto [array, created] = - const_cast*>(this)->get_property_container().template get_or_add_property(name); - return {{array.get()}, created}; + auto maybe_property_map = const_cast*>(this)->get_property_container().template get_property_if_exists(name); + if (!maybe_property_map) return {}; + else return {{maybe_property_map.value()}}; } diff --git a/Surface_mesh/test/Surface_mesh/sm_open_colored_off.cpp b/Surface_mesh/test/Surface_mesh/sm_open_colored_off.cpp index 0c998763420..ce25271e189 100644 --- a/Surface_mesh/test/Surface_mesh/sm_open_colored_off.cpp +++ b/Surface_mesh/test/Surface_mesh/sm_open_colored_off.cpp @@ -33,8 +33,8 @@ void OpenOFF(int i) assert(in && !surface_mesh.is_empty()); - auto [fcolors, created_fcolors] = surface_mesh.property_map("f:color"); - auto [vcolors, created_vcolors] = surface_mesh.property_map("v:color"); + auto [fcolors, created_fcolors] = surface_mesh.add_property_map("f:color"); + auto [vcolors, created_vcolors] = surface_mesh.add_property_map("v:color"); // Both color maps should have already existed, because they were loaded from the file assert(!created_fcolors); diff --git a/Surface_mesh/test/Surface_mesh/sm_ply_io.cpp b/Surface_mesh/test/Surface_mesh/sm_ply_io.cpp index f2889f912bd..c3524a2076b 100644 --- a/Surface_mesh/test/Surface_mesh/sm_ply_io.cpp +++ b/Surface_mesh/test/Surface_mesh/sm_ply_io.cpp @@ -15,6 +15,7 @@ typedef boost::graph_traits::face_descriptor face_descriptor; int main() { std::ifstream in(CGAL::data_file_path("meshes/colored_tetra.ply")); + assert(in.is_open()); SMesh mesh; CGAL::IO::read_PLY(in, mesh); @@ -37,6 +38,7 @@ int main() // Append second mesh std::ifstream in2("tetra.ply"); + assert(in2.is_open()); CGAL::IO::read_PLY(in2, mesh); std::ofstream out("out.ply"); diff --git a/Surface_mesh/test/Surface_mesh/sm_remove.cpp b/Surface_mesh/test/Surface_mesh/sm_remove.cpp index 48e1301433f..6744fbf77b2 100644 --- a/Surface_mesh/test/Surface_mesh/sm_remove.cpp +++ b/Surface_mesh/test/Surface_mesh/sm_remove.cpp @@ -47,10 +47,10 @@ int main() // make sure all is OK when clearing the mesh - auto vconn = m.property_map("v:connectivity").first; - auto hconn = m.property_map("h:connectivity").first; - auto fconn = m.property_map("f:connectivity").first; - auto vpoint = m.property_map("v:point").first; + auto vconn = m.add_property_map("v:connectivity").first; + auto hconn = m.add_property_map("h:connectivity").first; + auto fconn = m.add_property_map("f:connectivity").first; + auto vpoint = m.add_property_map("v:point").first; // first call to squat the first available position m.add_property_map("vprop_dummy"); @@ -71,10 +71,10 @@ int main() auto l_fprop = m.add_property_map("fprop").first; auto l_eprop = m.add_property_map("eprop").first; - auto l_vconn = m.property_map("v:connectivity").first; - auto l_hconn = m.property_map("h:connectivity").first; - auto l_fconn = m.property_map("f:connectivity").first; - auto l_vpoint = m.property_map("v:point").first; + auto l_vconn = m.add_property_map("v:connectivity").first; + auto l_hconn = m.add_property_map("h:connectivity").first; + auto l_fconn = m.add_property_map("f:connectivity").first; + auto l_vpoint = m.add_property_map("v:point").first; assert( vconn == l_vconn ); assert( hconn == l_hconn ); @@ -89,10 +89,10 @@ int main() { m.clear(); - auto l_vconn = m.property_map("v:connectivity").first; - auto l_hconn = m.property_map("h:connectivity").first; - auto l_fconn = m.property_map("f:connectivity").first; - auto l_vpoint = m.property_map("v:point").first; + auto l_vconn = m.add_property_map("v:connectivity").first; + auto l_hconn = m.add_property_map("h:connectivity").first; + auto l_fconn = m.add_property_map("f:connectivity").first; + auto l_vpoint = m.add_property_map("v:point").first; assert( vconn == l_vconn ); assert( hconn == l_hconn );