// 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; std::vector m_centroids; std::vector m_areas; 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); std::vector ().swap (m_centroids); std::vector ().swap (m_areas); } std::size_t run (FT epsilon, FT tolerance_coplanarity) { compute_centroids_and_areas (); // 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 < m_planes.size (); ++ i) { std::vector < bool > table_parallel_tmp; for (std::size_t j = 0; j < m_planes.size(); ++ j) { Vector v1 = m_planes[i]->plane_normal (); Vector v2 = m_planes[i]->plane_normal (); if (i != j && std::fabs (v1 * v2) > 1. - epsilon) 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 < m_planes.size (); ++ i) is_available.push_back (true); for (std::size_t i = 0; i < m_planes.size(); ++ i) { if(is_available[i]) { is_available[i]=false; //initialization containers std::vector < int > 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 = m_planes[i]->plane_normal (); double cumulated_area = m_areas[i]; do { propagation=false; for (std::size_t k=0;kplane_normal (); if( table_parallel[plane_index][it] && is_available[it] && std::fabs(normal_it*cluster_normal)>1.-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)m_areas[it]*normal_it; FT norm=1./sqrt(cluster_normal.squared_length()); cluster_normal=norm*cluster_normal; cumulated_area+=m_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; iprojection (m_centroids[index_prim]); if( m_planes[index_prim]->plane_normal () * vec_reg < 0) vec_reg=-vec_reg; Plane plane_reg(pt_reg,vec_reg); if( std::fabs(m_planes[index_prim]->plane_normal () * plane_reg.orthogonal_vector ()) > 1. - epsilon) { m_planes[index_prim]->update (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 = m_planes[index_prim]->projection(m_centroids[index_prim]); Plane plan_reg(pt_reg,vec_reg); for (std::size_t k=j+1; kprojection(m_centroids[index_prim_next]); Point pt_proj=plan_reg.projection(pt_reg_next); double distance=distance_Point(pt_reg_next,pt_proj); if(distance > list_primitive_reg_index_extracted_planes; std::vector < Plane > list_primitive_reg; for (std::size_t i=0;iprojection(m_centroids[index_prim]); pt_bary=barycenter(pt_bary, area,pt_reg,m_areas[index_prim]); area+=m_areas[index_prim]; } Vector vec_reg = m_planes[list_coplanar_prim[i][j][0]]->plane_normal (); Plane plane_reg(pt_bary,vec_reg); bool is_reg_used=false; std::vector< int > list_primitive_reg_index_extracted_planes_tmp1; for (std::size_t k=0; kplane_normal () * plane_reg.orthogonal_vector()) > 1. - epsilon) { if(m_planes[index_prim]->plane_normal () * plane_reg.orthogonal_vector()<0) m_planes[index_prim]->update (plane_reg.opposite()); else m_planes[index_prim]->update (plane_reg); is_reg_used=true; list_primitive_reg_index_extracted_planes_tmp1.push_back(index_prim); } else{ list_primitive_reg.push_back(static_cast (*(m_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<