// Copyright (c) 2015 INRIA Sophia-Antipolis (France). // All rights reserved. // // This file is part of CGAL (www.cgal.org). // You can redistribute it and/or modify it under the terms of the GNU // General Public License as published by the Free Software Foundation, // either version 3 of the License, or (at your option) any later version. // // Licensees holding a valid commercial license may use this file in // accordance with the commercial license agreement provided with the software. // // This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE // WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. // // $URL$ // $Id$ // // // Author(s) : // /** * \ingroup PkgPointSetShapeDetection3 * \file CGAL/Plane_regularization.h * */ #ifndef CGAL_PLANE_REGULARIZATION_H #define CGAL_PLANE_REGULARIZATION_H #include #include #include namespace CGAL { template class Plane_regularization { public: typedef Plane_regularization Self; typedef typename Traits::FT FT; typedef typename Traits::Point_3 Point; typedef typename Traits::Vector_3 Vector; typedef typename Traits::Plane_3 Plane; typedef typename Traits::Point_map Point_map; typedef typename Traits::Normal_map Normal_map; typedef typename Traits::Input_range Input_range; typedef typename Input_range::iterator Input_iterator; typedef Shape_detection_3::Shape_base Shape; typedef Shape_detection_3::Plane Plane_shape; private: Traits m_traits; Input_iterator m_input_begin; Input_iterator m_input_end; Point_map m_point_pmap; Normal_map m_normal_pmap; std::vector > m_planes; public: Plane_regularization (Traits t = Traits ()) : m_traits (t) { } Plane_regularization (Input_range& input_range, const Shape_detection_3::Efficient_RANSAC& shape_detection) : m_traits (shape_detection.traits()) { m_input_begin = input_range.begin (); m_input_end = input_range.end (); BOOST_FOREACH (boost::shared_ptr shape, shape_detection.shapes()) { boost::shared_ptr pshape = boost::dynamic_pointer_cast(shape); // Ignore all shapes other than plane if (pshape == boost::shared_ptr()) continue; m_planes.push_back (pshape); } } virtual ~Plane_regularization () { clear (); } void clear () { std::vector > ().swap (m_planes); } void run (FT epsilon, FT tolerance_coplanarity) { // WRAPPER BEGIN std::vector extracted_planes; std::vector > plane_point_index; std::vector primitive_index (m_input_end - m_input_begin, -1); std::vector label_plane (m_input_end - m_input_begin, -1); std::vector list_centroid; std::vector list_areas; for (std::size_t i = 0; i < m_planes.size (); ++ i) { extracted_planes.push_back (static_cast (*(m_planes[i]))); plane_point_index.push_back (std::vector()); std::copy (m_planes[i]->indices_of_assigned_points().begin (), m_planes[i]->indices_of_assigned_points().begin (), std::back_inserter (plane_point_index.back ())); std::vector < Point > listp; for (std::size_t j = 0; j < plane_point_index.back ().size (); ++ j) { primitive_index[j] = i; int yy = plane_point_index.back()[j]; label_plane[yy] = i; Point pt = get (m_point_pmap, *(m_input_begin + yy)); listp.push_back(pt); } list_centroid.push_back (CGAL::centroid (listp.begin (), listp.end ())); list_areas.push_back ((double)(plane_point_index.back().size()) / 100.); } // WRAPPER END // find pairs of epsilon-parallel primitives and store them in table_parallel std::vector < std::vector < bool > > table_parallel; for( std::size_t i=0;i table_parallel_tmp; for( std::size_t j=0;j1.-epsilon && i!=j) table_parallel_tmp.push_back(true); else table_parallel_tmp.push_back(false); } table_parallel.push_back(table_parallel_tmp); } // clustering the parallel primitives and store them in list_parallel_planes // & compute the normal, size and cos angle to the vertical of each cluster, and store that in list_cluster_normales, list_cluster_angle and list_cluster_area std::vector < std::vector < int > > list_parallel_planes; std::vector < Vector > list_cluster_normales; std::vector < double > list_cluster_cosangle_vertical; std::vector < double > list_cluster_area; std::vector < bool > is_available; for( std::size_t i=0;i index_container_parallel; index_container_parallel.push_back(i); std::vector < int > index_container_former_ring_parallel; index_container_former_ring_parallel.push_back(i); std::list < int > index_container_current_ring_parallel; //propagation over the pairs of epsilon-parallel primitives bool propagation=true; Vector cluster_normal=extracted_planes[i].orthogonal_vector(); double cumulated_area=list_areas[i]; do { propagation=false; for (std::size_t k=0;k1.-epsilon ) { propagation=true; index_container_current_ring_parallel.push_back(it); is_available[it]=false; if(cluster_normal*normal_it <0) normal_it=-normal_it; cluster_normal=(FT)cumulated_area*cluster_normal+(FT)list_areas[it]*normal_it; FT norm=1./sqrt(cluster_normal.squared_length()); cluster_normal=norm*cluster_normal; cumulated_area+=list_areas[it]; } } } //update containers index_container_former_ring_parallel.clear(); for (std::list < int >::iterator it = index_container_current_ring_parallel.begin(); it != index_container_current_ring_parallel.end(); ++it) { index_container_former_ring_parallel.push_back(*it); index_container_parallel.push_back(*it); } index_container_current_ring_parallel.clear(); } while(propagation); list_parallel_planes.push_back(index_container_parallel); list_cluster_normales.push_back(cluster_normal); list_cluster_area.push_back(cumulated_area); Vector v_vertical(0.,0.,1.); list_cluster_cosangle_vertical.push_back(std::fabs(v_vertical*cluster_normal)); } } is_available.clear(); //discovery orthogonal relationship between clusters std::vector < std::vector < bool > > group_planes_orthogonal; for( std::size_t i=0;i gp_tmp; for( std::size_t j=0;j cosangle_centroids; std::vector < int > list_cluster_index; for( std::size_t i=0;i1.-epsilon) cosangle_centroids[i]=1; } for (std::size_t i=0; i "; for (std::size_t j=0; j "; for (std::size_t j=0;j "< "< > subgraph_clusters; std::vector < int > subgraph_clusters_max_area_index; std::vector < bool > is_free; for (std::size_t i=0; i index_container; index_container.push_back(i); std::vector < int > index_container_former_ring; index_container_former_ring.push_back(i); std::list < int > index_container_current_ring; //propagation bool propagation=true; do { propagation=false; //neighbors for (std::size_t k=0;k::iterator it = index_container_current_ring.begin(); it != index_container_current_ring.end(); ++it) { index_container_former_ring.push_back(*it); index_container.push_back(*it); } index_container_current_ring.clear(); } while(propagation); subgraph_clusters.push_back(index_container); subgraph_clusters_max_area_index.push_back(index_max_area); } } is_free.clear(); //create subgraphs of mutually orthogonal clusters in which the largest cluster is excluded and store in subgraph_clusters_prop std::vector < std::vector < int > > subgraph_clusters_prop; for (std::size_t i=0;i subgraph_clusters_prop_temp; for (std::size_t j=0;j cluster_is_available; for( std::size_t i=0;i index_container; index_container.push_back(index_current); std::vector < int > index_container_former_ring; index_container_former_ring.push_back(index_current); std::list < int > index_container_current_ring; //propagation bool propagation=true; do { propagation=false; //neighbors for (std::size_t k=0;k::iterator it = index_container_current_ring.begin(); it != index_container_current_ring.end(); ++it) { index_container_former_ring.push_back(*it); index_container.push_back(*it); } index_container_current_ring.clear(); }while(propagation); } //recompute optimal plane for each primitive after normal regularization for (std::size_t i=0; i 1. - epsilon) extracted_planes[index_prim]=plane_reg; } } //detecting co-planarity and store in list_coplanar_prim std::vector< std::vector< std::vector < int > > > list_coplanar_prim; for (std::size_t i=0; i > list_coplanar_prim_tmp; Vector vec_reg=list_cluster_normales[i]; std::vector < int > list_cop_index; for( std::size_t ip=0;ip list_coplanar_prim_tmp_tmp; list_cop_index[j]=cop_index; list_coplanar_prim_tmp_tmp.push_back(index_prim); Point pt_reg=extracted_planes[index_prim].projection(list_centroid[index_prim]); Plane plan_reg(pt_reg,vec_reg); for (std::size_t k=j+1; k > list_primitive_reg_index_extracted_planes; std::vector < Plane > list_primitive_reg; for (std::size_t i=0;i list_primitive_reg_index_extracted_planes_tmp1; for (std::size_t k=0; k 1. - epsilon) { if(extracted_planes[index_prim].orthogonal_vector()*plane_reg.orthogonal_vector()<0) extracted_planes[index_prim]=plane_reg.opposite(); else extracted_planes[index_prim]=plane_reg; is_reg_used=true; list_primitive_reg_index_extracted_planes_tmp1.push_back(index_prim); } else{ list_primitive_reg.push_back(extracted_planes[index_prim]); std::vector< int > list_primitive_reg_index_extracted_planes_tmp; list_primitive_reg_index_extracted_planes_tmp.push_back(index_prim); list_primitive_reg_index_extracted_planes.push_back(list_primitive_reg_index_extracted_planes_tmp); } } if(is_reg_used) { list_primitive_reg.push_back(plane_reg); list_primitive_reg_index_extracted_planes.push_back(list_primitive_reg_index_extracted_planes_tmp1); } } } std::cout<