35 #include "QualityAssessor.hpp"
36 #include "PatchData.hpp"
37 #include "MsqMeshEntity.hpp"
38 #include "MsqVertex.hpp"
39 #include "MsqDebug.hpp"
40 #include "MeshSet.hpp"
42 #ifdef MSQ_USE_OLD_STD_HEADERS
51 #ifdef MSQ_USE_OLD_IO_HEADERS
52 # include <iostream.h>
64 QualityAssessor::QualityAssessor(
string name) :
65 qualityAssessorName(name),
68 stoppingMetric( assessList.end() ),
69 stoppingFunction( NO_FUNCTION )
127 return "Histogram of metric values: ";
143 return count ? sum/count : 0;
148 return count ?
sqrt(sqrSum/count) : 0;
153 double sqr = sqrSum/count - sum*sum/((double)count*count);
154 return sqr < 0 ? 0 :
sqrt(sqr);
171 msq_std::list<Assessor>::iterator iter;
174 iter->funcFlags |= func;
181 list<Assessor>::iterator iter;
185 if (iter->qualMetric == qm )
250 if (min_val >= max_val || intervals < 1) {
255 list<Assessor>::iterator assessor =
find_or_add( qm );
257 assessor->histMin = min_val;
258 assessor->histMax = max_val;
259 assessor->histogram.resize( intervals + 2 );
288 list<Assessor>::iterator elem_end =
assessList.end();
289 bool need_second_pass_for_elements =
false;
290 bool need_second_pass_for_vertices =
false;
291 list<Assessor>::iterator iter;
297 if (iter->funcFlags&HISTOGRAM && !iter->haveHistRange)
298 need_second_pass_for_elements =
true;
303 if (iter->funcFlags&HISTOGRAM && !iter->haveHistRange)
304 need_second_pass_for_vertices =
true;
307 list<Assessor> histogramList;
312 bool first_pass =
false;
314 first_pass = !first_pass;
317 PatchData local_patch;
319 bool more_mesh =
true;
322 more_mesh=ms.get_next_patch(*pd,
this, err);
MSQ_ERRZERO(err);
333 for (
unsigned i = 0;
i < pd->num_elements(); ++
i)
335 for (iter =
assessList.begin(); iter != elem_end; ++iter)
341 bool valid = iter->get_metric()->evaluate_element( *pd,
342 &pd->element_by_index(
i),
346 iter->add_value(value);
348 iter->add_invalid_value();
352 else if (iter->funcFlags&HISTOGRAM && !iter->haveHistRange)
355 iter->get_metric()->evaluate_element( *pd,
356 &pd->element_by_index(
i),
360 iter->add_hist_value(value);
367 more_mesh = ms.get_next_patch(*pd,
this, err);
MSQ_ERRZERO(err);
374 for (iter =
assessList.begin(); iter != elem_end; ++iter)
375 if (iter->funcFlags&HISTOGRAM && !iter->haveHistRange)
377 iter->calculate_histogram_range();
383 }
while (first_pass && need_second_pass_for_elements);
390 bool first_pass =
false;
392 first_pass = !first_pass;
396 PatchData local_patch;
398 bool more_mesh =
true;
401 more_mesh=ms.get_next_patch(*pd,
this, err);
MSQ_ERRZERO(err);
412 for (
unsigned i = 0;
i < pd->num_vertices(); ++
i)
414 for (iter = elem_end; iter !=
assessList.end(); ++iter)
420 bool valid = iter->get_metric()->evaluate_vertex( *pd,
421 &pd->vertex_by_index(
i),
425 iter->add_value(value);
427 iter->add_invalid_value();
431 else if (iter->funcFlags&HISTOGRAM && !iter->haveHistRange)
434 iter->get_metric()->evaluate_vertex( *pd,
435 &pd->vertex_by_index(
i),
439 iter->add_hist_value(value);
445 more_mesh = ms.get_next_patch(*pd,
this, err);
MSQ_ERRZERO(err);
452 for (iter = elem_end; iter !=
assessList.end(); ++iter)
453 if (iter->funcFlags&HISTOGRAM && !iter->haveHistRange)
455 iter->calculate_histogram_range();
461 }
while (first_pass && need_second_pass_for_vertices);
485 MSQ_SETERR(err)(
"Invalid stopping function for QualityAssessor",
494 msq_std::list<Assessor>::const_iterator iter;
496 if (iter->get_invalid_element_count())
503 msq_std::list<Assessor>::iterator iter;
509 : qualMetric(metric),
511 haveHistRange(false),
520 msq_std::list<Assessor>::const_iterator iter;
522 if (iter->get_metric() == metric)
529 double& upper_bound_out,
530 msq_std::vector<int>& counts_out,
531 MsqError& err )
const
540 lower_bound_out = histMin;
541 upper_bound_out = histMax;
544 lower_bound_out = minimum;
545 upper_bound_out = maximum;
548 counts_out = histogram;
559 memset( &histogram[0], 0,
sizeof(
int)*histogram.size() );
565 sqrSum += metric_value*metric_value;
566 if (metric_value > maximum)
567 maximum = metric_value;
568 if (metric_value < minimum)
569 minimum = metric_value;
574 if (funcFlags & QualityAssessor::HISTOGRAM && haveHistRange)
575 add_hist_value( metric_value );
588 double step = (histMax - histMin) / (histogram.size()-2);
593 if (metric_value < histMin)
595 else if (metric_value > histMax)
596 ++histogram[histogram.size()-1];
603 if (step > DBL_EPSILON)
604 cell = 1+(unsigned)((metric_value - histMin) / step);
611 if (cell + 1 == histogram.size())
620 double step = (maximum - minimum) / (histogram.size() - 2);
621 double size =
pow( 10, ceil(
log10(step)) );
622 histMin = size * floor( minimum / size );
623 histMax = size * ceil( maximum / size );
628 const int NAMEW = 19;
632 stream << msq_stdio::endl
635 <<
" Summary **************"
640 msq_std::list<Assessor>::const_iterator iter;
642 int invalid_count = 0;
645 flags |= (iter->funcFlags & ~HISTOGRAM);
647 if (iter->get_invalid_element_count())
651 stream <<
" " << iter->get_invalid_element_count()
652 <<
" OF " << iter->get_count()
653 <<
" VALUES ARE INVALID FOR "
654 << iter->get_metric()->get_name()
655 << msq_stdio::endl << msq_stdio::endl;
659 if (0 == invalid_count) {
660 stream <<
" No invalid values for any metric."
661 << msq_stdio::endl << msq_stdio::endl;
668 stream << msq_stdio::setw(NAMEW) <<
"metric";
670 stream << msq_stdio::setw(NUMW) <<
"minimum";
672 stream << msq_stdio::setw(NUMW) <<
"average";
674 stream << msq_stdio::setw(NUMW) <<
"rms";
676 stream << msq_stdio::setw(NUMW) <<
"maximum";
678 stream << msq_stdio::setw(NUMW) <<
"std.dev.";
679 stream << msq_stdio::endl;
685 if (!(iter->funcFlags & ~HISTOGRAM))
689 stream << msq_stdio::setw(NAMEW) << iter->get_metric()->get_name();
694 if (iter->funcFlags & MINIMUM)
695 stream << msq_stdio::setw(NUMW) << iter->get_minimum();
697 stream << msq_stdio::setw(NUMW) <<
" ";
701 if (iter->funcFlags & AVERAGE)
702 stream << msq_stdio::setw(NUMW) << iter->get_average();
704 stream << msq_stdio::setw(NUMW) <<
" ";
708 if (iter->funcFlags & RMS)
709 stream << msq_stdio::setw(NUMW) << iter->get_rms();
711 stream << msq_stdio::setw(NUMW) <<
" ";
715 if (iter->funcFlags & MAXIMUM)
716 stream << msq_stdio::setw(NUMW) << iter->get_maximum();
718 stream << msq_stdio::setw(NUMW) <<
" ";
722 if (iter->funcFlags & STDDEV)
723 stream << msq_stdio::setw(NUMW) << iter->get_stddev();
725 stream << msq_stdio::setw(NUMW) <<
" ";
727 stream << msq_stdio::endl;
732 if (iter->funcFlags & HISTOGRAM)
733 iter->print_histogram( stream );
746 const char GRAPH_CHAR =
'=';
747 const int FLOATW = 12;
748 const int GRAPHW = 50;
762 double step = (max -
min) / (histogram.size()-2);
766 int max_interval = 1;
767 for (i = 0; i < histogram.size(); ++
i)
768 if (histogram[i] > max_interval)
769 max_interval = histogram[
i];
771 if (0 == max_interval)
777 for (
int temp = max_interval; temp > 0; temp /= 10)
781 char graph_chars[GRAPHW+1];
782 memset( graph_chars, GRAPH_CHAR,
sizeof(graph_chars) );
787 bool log_plot =
false;
788 double stddev = get_stddev();
789 if (stddev > 0 && stddev < 2.0*step)
791 int new_interval = (int)(
log10((
double)(1+max_interval)));
792 if (new_interval > 0) {
794 max_interval = new_interval;
800 stream << msq_stdio::endl <<
" " << get_metric()->get_name() <<
" histogram:";
802 stream <<
" (log10 plot)";
803 stream << msq_stdio::endl;
807 for (i = 0; i < histogram.size(); ++
i)
813 if (0 == histogram[i])
815 stream << setw(FLOATW) <<
"under min";
819 else if (i+1 == histogram.size())
821 if (0 == histogram[i])
823 stream << setw(FLOATW) <<
"over max";
829 stream <<
" " << setw(FLOATW) << min + (i-1)*step;
833 stream <<
": " << setw(num_width) << histogram[
i] <<
": ";
840 num_graph = GRAPHW * (int)
log10((
double)(1+histogram[
i])) / max_interval;
842 num_graph = GRAPHW * histogram[
i] / max_interval;
845 graph_chars[num_graph] =
'\0';
846 stream << graph_chars << msq_stdio::endl;
847 graph_chars[num_graph] = GRAPH_CHAR;
850 stream << msq_stdio::endl;
#define MSQ_ERRZERO(err)
Return zero/NULL on error.
void reset_data()
Reset calculated data.
virtual void set_patch_type(PatchData::PatchType patch_type, MsqError &err, int param1=0, int param2=0)
Sets the Patch Type.
msq_stdio::ostream & outputStream
Stream to which to write summary of metric data.
static msq_std::string get_QAFunction_name(enum QualityAssessor::QAFunction)
const int DEFAULT_HISTOGRAM_INTERVALS
Vector_n max(const Array_n_const &v1, const Array_n_const &v2)
~QualityAssessor()
Destructor.
void print_histogram(msq_stdio::ostream &) const
Print the histogram.
void print_summary(msq_stdio::ostream &stream) const
Print accumulated summary data to specified stream.
double get_stddev() const
Assessor(QualityMetric *metric)
virtual double loop_over_mesh(MeshSet &ms, MsqError &err)
Does one sweep over the mesh and assess the quality with the metrics previously added.
invalid function argument passed
void add_quality_assessment(QualityMetric *qm, int function_flags, MsqError &err)
Adds a quality metric and a wrapper function (min, max, ...).
#define MSQ_SETERR(err)
Macro to set error - use err.clear() to clear.
msq_std::list< Assessor >::iterator find_or_add(QualityMetric *qm)
Find an Assessor corresponding to the passed QualityMetric, or create it if is not found in the list...
CImg< _cimg_Tfloat > log10(const CImg< T > &instance)
PatchData::PatchType get_patch_type()
Returns the Patch Type.
msq_std::string qualityAssessorName
Name.
msq_std::list< Assessor >::iterator stoppingMetric
Metric in assessList to use as return value for loop_over_mesh.
Vector_n min(const Array_n_const &v1, const Array_n_const &v2)
PatchData * get_global_patch()
Returns the Global Patch.
void get_histogram(double &lower_bound_out, double &upper_bound_out, msq_std::vector< int > &counts_out, MsqError &err) const
Get historgram of data, if calculated.
void no_culling_method()
Sets off all culling methods.
object is in an invalid state
msq_std::list< Assessor > assessList
List of quality metrics and corresponding data.
T sqr(const T val)
Return the square of a number.
void add_histogram_assessment(QualityMetric *qm, double min, double max, int intervals, MsqError &err)
Add a quality metric for which the histogram is to be calculated, and set histogram parameters...
void add_hist_value(double metric_value)
Add a value to the hisogram data.
QAFunction stoppingFunction
Value to use as return value for loop_over_mesh.
void set_stopping_assessment(QualityMetric *qm, QAFunction func, MsqError &err)
void add_value(double metric_value)
Add a value to the running counts.
bool printSummary
Disable printing.
double pow(double value, const Exponent &exp)
QualityAssessor(msq_std::string name="QualityAssessor")
Constructor - output to std::cout.
void reset_data()
Reset all calculated data.
double get_average() const
void calculate_histogram_range()
If range of histogram has not yet been determined, calculate it from the min/max values.
const Assessor * get_results(QualityMetric *metric) const
Request summary data for a specific QualityMetric This method allows the application to request the s...
bool invalid_elements() const
True if any metric evaluated to an invalid value for any element.
void add_invalid_value()
Note invalid result.