Exemplo n.º 1
0
    bool make_statistic::run(viennamesh::algorithm_handle &)
    {
        info(1) << "make_statistic started:" << std::endl;

        mesh_handle input_mesh = get_required_input<mesh_handle>("mesh");

        /*original mesh for comparison statistics (hausdorff distance, curvature difference...)*/
        mesh_handle original_mesh = get_input<mesh_handle>("original_mesh");

        /*All provided cell quality metric types are implemented as header files, which are located in statistics/metrics.
         * Note that most metrics are only implemented for triangles*/
        data_handle<viennamesh_string> metric_type = get_required_input<viennamesh_string>("metric_type");

        /*Decision threshold for triangle qualitity classification
         * E.g., radius_ratio < 1.5
         * Whether '<' or '>' is used for comparison is deduced from metric_ordering_tag*/
        data_handle<viennagrid_numeric> good_element_threshold = get_input<viennagrid_numeric>("good_element_threshold");

        /* comprehensive mesh quality metric is defined as
             alpha * (1 - good_elements_counted/count) + beta * min_dist_rms + gamma * mean_curvature + delta * volume_deviation;
        */
        data_handle<viennagrid_numeric> alpha = get_input<viennagrid_numeric>("alpha");
        data_handle<viennagrid_numeric> beta = get_input<viennagrid_numeric>("beta");
        data_handle<viennagrid_numeric> gamma = get_input<viennagrid_numeric>("gamma");
        data_handle<viennagrid_numeric> delta = get_input<viennagrid_numeric>("delta");

#if HIST
        data_handle<viennagrid_numeric> histogram_bins = get_input<viennagrid_numeric>("histogram_bin");
        data_handle<viennagrid_numeric> histogram_min = get_input<viennagrid_numeric>("histogram_min");
        data_handle<viennagrid_numeric> histogram_max = get_input<viennagrid_numeric>("histogram_max");
        data_handle<int> histogram_bin_count = get_input<int>("histogram_bin_count");
#endif


        typedef viennagrid::mesh                                  MeshType;
        typedef viennagrid::result_of::element<MeshType>::type    ElementType; //=Triangle or Tetrahedron

        typedef viennamesh::statistic<viennagrid_numeric>         StatisticType;
        StatisticType statistic;

#if HIST
        typedef StatisticType::histogram_type                     HistogramType;


        if (histogram_bins.valid())
        {
            std::vector<viennagrid_numeric> bins;
            for (int i = 0; i != histogram_bins.size(); ++i)
                bins.push_back( histogram_bins(i) );

            statistic.set_histogram( StatisticType::histogram_type::make(bins.begin(), bins.end()) );
        }
        else if (histogram_min.valid() && histogram_max.valid() && histogram_bin_count.valid())
        {
            statistic.set_histogram( StatisticType::histogram_type::make_uniform(histogram_min(), histogram_max(), histogram_bin_count()) );
        }
        else
        {
            //If histograms are about to be added again, returing false here will prevent the basic statistics features from working!
            error(1) << "No histogram configuration provided" << std::endl;
            return false;
        }
#endif





        //Good element threshold input was set, call statistics with the appropriate metric
        if(good_element_threshold.valid())
        {
            viennamesh::LoggingStack stack( std::string("High quality cell counter with metric type \"") + metric_type() + "\"" );

            if (metric_type() == "aspect_ratio")
                statistic.cell_quality_count<viennamesh::aspect_ratio_tag>( input_mesh(), viennamesh::aspect_ratio<ElementType>, good_element_threshold());
            else if (metric_type() == "min_angle")
                statistic.cell_quality_count<viennamesh::min_angle_tag>( input_mesh(), viennamesh::min_angle<ElementType>, good_element_threshold());
            else if (metric_type() == "max_angle")
                statistic.cell_quality_count<viennamesh::max_angle_tag>( input_mesh(), viennamesh::max_angle<ElementType>, good_element_threshold());
            else if (metric_type() == "min_dihedral_angle")
                statistic.cell_quality_count<viennamesh::min_dihedral_angle_tag>( input_mesh(), viennamesh::min_dihedral_angle<ElementType>, good_element_threshold());
            else if (metric_type() == "radius_edge_ratio")
                statistic.cell_quality_count<viennamesh::radius_edge_ratio_tag>( input_mesh(), viennamesh::radius_edge_ratio<ElementType>, good_element_threshold());
            else if (metric_type() == "radius_ratio")
                statistic.cell_quality_count<viennamesh::radius_ratio_tag>( input_mesh(), viennamesh::radius_ratio<ElementType>, good_element_threshold());
            else if (metric_type() == "perimeter_inradius_ratio")
                statistic.cell_quality_count<viennamesh::perimeter_inradius_ratio_tag>( input_mesh(), viennamesh::perimeter_inradius_ratio<ElementType>, good_element_threshold());
            else if (metric_type() == "edge_ratio")
                statistic.cell_quality_count<viennamesh::edge_ratio_tag>( input_mesh(), viennamesh::edge_ratio<ElementType>, good_element_threshold());
            else if (metric_type() == "circum_perimeter_ratio")
                statistic.cell_quality_count<viennamesh::circum_perimeter_ratio_tag>( input_mesh(), viennamesh::circum_perimeter_ratio<ElementType>, good_element_threshold());
            else if (metric_type() == "stretch")
                statistic.cell_quality_count<viennamesh::stretch_tag>( input_mesh(), viennamesh::stretch<ElementType>, good_element_threshold());
            else if (metric_type() == "skewness")
                statistic.cell_quality_count<viennamesh::skewness_tag>( input_mesh(), viennamesh::skewness<ElementType>, good_element_threshold());
            else
            {
                error(1) << "Metric type \"" << metric_type() << "\" is not supported for cell quality classifaction" << std::endl;
                return false;
            }
        }
        else //no triangle classifiction takes place
        {
            viennamesh::LoggingStack stack( std::string("Cell statistics with metric type \"") + metric_type() + "\"" );

            if (metric_type() == "aspect_ratio")
                statistic.cell_stats( input_mesh(), viennamesh::aspect_ratio<ElementType> );
            else if (metric_type() == "min_angle")
                statistic.cell_stats( input_mesh(), viennamesh::min_angle<ElementType> );
            else if (metric_type() == "max_angle")
                statistic.cell_stats( input_mesh(), viennamesh::max_angle<ElementType> );
            else if (metric_type() == "min_dihedral_angle")
                statistic.cell_stats( input_mesh(), viennamesh::min_dihedral_angle<ElementType> );
            else if (metric_type() == "radius_edge_ratio")
                statistic.cell_stats( input_mesh(), viennamesh::radius_edge_ratio<ElementType> );
            else if (metric_type() == "radius_ratio")
                statistic.cell_stats( input_mesh(), viennamesh::radius_ratio<ElementType> );
            else if (metric_type() == "perimeter_inradius_ratio")
                statistic.cell_stats( input_mesh(), viennamesh::perimeter_inradius_ratio<ElementType> );
            else if (metric_type() == "edge_ratio")
                statistic.cell_stats( input_mesh(), viennamesh::edge_ratio<ElementType> );
            else if (metric_type() == "circum_perimeter_ratio")
                statistic.cell_stats( input_mesh(), viennamesh::circum_perimeter_ratio<ElementType> );
            else if (metric_type() == "stretch")
                statistic.cell_stats( input_mesh(), viennamesh::stretch<ElementType> );
            else if (metric_type() == "skewness")
                statistic.cell_stats( input_mesh(), viennamesh::skewness<ElementType> );
            else
            {
                error(1) << "Metric type \"" << metric_type() << "\" is not supported" << std::endl;
                return false;
            }
        }

        if(original_mesh.valid())//a second mesh is set, calculate mesh comparison measures
        {
            viennamesh::LoggingStack stack( std::string("Calculation of Mesh Comparison Measures") );

            statistic.mesh_comparison_quality(input_mesh(), original_mesh());



            ConstTriangleRange tr_orig(original_mesh());
            ConstTriangleRange tr(input_mesh());

            StatisticType statistic_orig;
            statistic_orig.cell_stats( original_mesh(), viennamesh::aspect_ratio<ElementType> );


            //use median of orig mesh for input mesh triangle shape characterization
            statistic.cell_quality_count<viennamesh::aspect_ratio_tag>( input_mesh(), viennamesh::aspect_ratio<ElementType>, statistic_orig.median());

            if(alpha.valid() && beta.valid() && gamma.valid() && delta.valid() )
            {
                statistic.set_mesh_quality_weights(alpha(), beta(), gamma(), delta());
                info(5) << "values for comprehensive mesh quality metric: alpha = " << alpha()
                        << ", beta = " << beta() << ", gamma = " << gamma() << ", delta = "<< delta() <<  std::endl;

            }
            else
            {
                info(5) << "default values for comprehensive mesh quality metric used: alpha = 0.25, beta = 20, gamma = 1.0, delta = 1.3" << std::endl;
            }

            set_output("minimum_distance_rms", statistic.min_dist_rms());
            set_output("mean_curvature_difference", statistic.mean_curvature());
            set_output("area_deviation", statistic.volume_deviation());
            set_output("triangle_shape", statistic.good_elements()/statistic.count());
            set_output("mesh_quality_metric", statistic.mesh_quality_metric());
        }


        info(5) << statistic << "\n";

#if HIST
        statistic.normalize();
        std::vector<viennagrid_numeric> bins;
        for (HistogramType::const_iterator bit = statistic.histogram().begin(); bit != statistic.histogram().end(); ++bit)
            bins.push_back( (*bit).second );
        bins.push_back( statistic.histogram().overflow_bin() );

        data_handle<viennagrid_numeric> output_bins = make_data<viennagrid_numeric>();
        output_bins.set( bins );
        set_output( "bins", output_bins );
#endif

        set_output( "min", statistic.min() );
        set_output( "max", statistic.max() );
        set_output( "mean", statistic.mean() );
        set_output( "median", statistic.median());

        return true;
    }
  bool make_statistic::generic_run()
  {
    typedef viennagrid::segmented_mesh<MeshT, SegmentationT> SegmentedMeshType;
    typename viennamesh::result_of::const_parameter_handle<SegmentedMeshType>::type imp = input_mesh.get<SegmentedMeshType>();
    if (imp)
    {
      typedef viennamesh::statistic<double> StatisticType;
      typedef typename viennagrid::result_of::cell<MeshT>::type CellType;
      output_parameter_proxy<StatisticType> osp(output_statistic);

      if (histogram_bins.valid())
      {
        osp().set_histogram( StatisticType::histogram_type::make(histogram_bins().begin(), histogram_bins().end()) );
      }
      else if (histogram_min.valid() && histogram_max.valid() && histogram_bin_count.valid())
      {
        osp().set_histogram( StatisticType::histogram_type::make_uniform(histogram_min(), histogram_max(), histogram_bin_count()) );
      }
      else
      {
        error(1) << "No histogram configuration provided" << std::endl;
        return false;
      }

      try
      {
        if (metric_type() == "aspect_ratio")
          osp()( imp().mesh, viennamesh::aspect_ratio<CellType> );
        else if (metric_type() == "condition_number")
          osp()( imp().mesh, viennamesh::condition_number<CellType> );
        else if (metric_type() == "min_angle")
          osp()( imp().mesh, viennamesh::min_angle<CellType> );
        else if (metric_type() == "max_angle")
          osp()( imp().mesh, viennamesh::max_angle<CellType> );
        else if (metric_type() == "min_dihedral_angle")
          osp()( imp().mesh, viennamesh::min_dihedral_angle<CellType> );
        else if (metric_type() == "radius_edge_ratio")
          osp()( imp().mesh, viennamesh::radius_edge_ratio<CellType> );
        else
        {
          error(1) << "Metric type \"" << metric_type() << "\" is not supported" << std::endl;
          return false;
        }
      }
      catch ( metric_not_implemented_or_supported_exception const & ex )
      {
        error(1) << "Metric type \"" << metric_type() << "\" is not supported" << std::endl;
        error(1) << ex.what() << std::endl;
      }

      info(5) << osp() << std::endl;

      return true;
    }

    return false;
  }