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 )
75 QualityAssessor::QualityAssessor(ostream& stream,
string name) :
76 qualityAssessorName(name),
77 outputStream( stream ),
79 stoppingMetric( assessList.end() ),
80 stoppingFunction( NO_FUNCTION )
86 QualityAssessor::QualityAssessor( QualityMetric*
metric,
90 qualityAssessorName(name),
93 stoppingMetric( assessList.end() ),
94 stoppingFunction( (QAFunction)0 )
97 add_quality_assessment( metric,
function, err );
98 set_stopping_assessment( metric,
function, err );
101 QualityAssessor::QualityAssessor( QualityMetric*
metric,
106 qualityAssessorName(name),
107 outputStream( stream ),
108 printSummary( true ),
109 stoppingMetric( assessList.end() ),
110 stoppingFunction( (QAFunction)0 )
113 add_quality_assessment( metric,
function, err );
114 set_stopping_assessment( metric,
function, err );
117 QualityAssessor::~QualityAssessor()
120 string QualityAssessor::get_QAFunction_name(
127 return "Histogram of metric values: ";
141 double QualityAssessor::Assessor::get_average()
const
143 return count ? sum/count : 0;
146 double QualityAssessor::Assessor::get_rms()
const
148 return count ?
sqrt(sqrSum/count) : 0;
151 double QualityAssessor::Assessor::get_stddev()
const
153 double sqr = sqrSum/count - sum*sum/((double)count*count);
154 return sqr < 0 ? 0 :
sqrt(sqr);
171 msq_std::list<Assessor>::iterator iter;
173 iter = find_or_add( qm );
174 iter->funcFlags |= func;
179 list<QualityAssessor::Assessor>::iterator QualityAssessor::find_or_add(
QualityMetric* qm )
181 list<Assessor>::iterator iter;
184 for (iter = assessList.begin(); iter != assessList.end(); ++iter)
185 if (iter->qualMetric == qm )
189 if (iter == assessList.end())
193 assessList.push_back(
Assessor(qm) );
194 iter = --assessList.end();
198 assessList.push_front(
Assessor(qm) );
199 iter = assessList.begin();
221 MSQ_SETERR(err)(
"HISTOGRAM DOES NOT GIVE A VALID RETURN VALUE", MsqError::INVALID_ARG);
224 else if (func == NO_FUNCTION) {
225 MSQ_SETERR(err)(
"No function specified for stopping assessment", MsqError::INVALID_ARG);
229 stoppingMetric = find_or_add( qm );
230 stoppingFunction = func;
250 if (min_val >= max_val || intervals < 1) {
251 MSQ_SETERR(err)(
"Invalid histogram range.", MsqError::INVALID_ARG );
255 list<Assessor>::iterator assessor = find_or_add( qm );
256 assessor->funcFlags |= QualityAssessor::HISTOGRAM;
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;
292 for (iter = assessList.begin(); iter != assessList.end(); ++iter)
294 if (iter->get_metric()->get_metric_type() == QualityMetric::VERTEX_BASED)
297 if (iter->funcFlags&HISTOGRAM && !iter->haveHistRange)
298 need_second_pass_for_elements =
true;
301 for ( ; iter != assessList.end(); ++iter)
303 if (iter->funcFlags&HISTOGRAM && !iter->haveHistRange)
304 need_second_pass_for_vertices =
true;
307 list<Assessor> histogramList;
310 if (assessList.begin() != elem_end)
312 bool first_pass =
false;
314 first_pass = !first_pass;
319 bool more_mesh =
true;
320 if (get_global_patch() == 0) {
325 pd = get_global_patch();
335 for (iter = assessList.begin(); iter != elem_end; ++iter)
341 bool valid = iter->get_metric()->evaluate_element( *pd,
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,
360 iter->add_hist_value(value);
366 if (get_patch_type() != PatchData::GLOBAL_PATCH)
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);
388 if (assessList.end() != elem_end)
390 bool first_pass =
false;
392 first_pass = !first_pass;
398 bool more_mesh =
true;
399 if (get_global_patch() == 0) {
404 pd = get_global_patch();
414 for (iter = elem_end; iter != assessList.end(); ++iter)
420 bool valid = iter->get_metric()->evaluate_vertex( *pd,
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,
439 iter->add_hist_value(value);
444 if (get_patch_type() != PatchData::GLOBAL_PATCH)
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);
467 print_summary( this->outputStream );
470 if (!stoppingFunction)
474 if (stoppingFunction & STDDEV)
475 return stoppingMetric->get_stddev();
476 else if (stoppingFunction & AVERAGE)
477 return stoppingMetric->get_average();
478 else if (stoppingFunction &
MAXIMUM)
479 return stoppingMetric->get_maximum();
480 else if (stoppingFunction & MINIMUM)
481 return stoppingMetric->get_minimum();
482 else if (stoppingFunction & RMS)
483 return stoppingMetric->get_rms();
485 MSQ_SETERR(err)(
"Invalid stopping function for QualityAssessor",
486 MsqError::INVALID_STATE);
491 bool QualityAssessor::invalid_elements( )
const
494 msq_std::list<Assessor>::const_iterator iter;
495 for (iter = assessList.begin(); iter != assessList.end(); ++iter)
496 if (iter->get_invalid_element_count())
501 void QualityAssessor::reset_data()
503 msq_std::list<Assessor>::iterator iter;
504 for (iter = assessList.begin(); iter != assessList.end(); ++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,
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;
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;
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;
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;
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.
MetricType get_metric_type()
MsqVertex & vertex_by_index(size_t index)
Returns the start of the vertex->element array.
Used to hold the error state and return it to the application.
Base class for concrete quality metrics.
const int DEFAULT_HISTOGRAM_INTERVALS
Vector_n max(const Array_n_const &v1, const Array_n_const &v2)
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.
Per-metric QualityAssessor data.
size_t num_elements() const
number of elements in the Patch.
#define MSQ_SETERR(err)
Macro to set error - use err.clear() to clear.
CImg< _cimg_Tfloat > log10(const CImg< T > &instance)
msq_std::string qualityAssessorName
Name.
size_t num_vertices() const
number of vertices in the patch.
MsqMeshEntity & element_by_index(size_t index)
Vector_n min(const Array_n_const &v1, const Array_n_const &v2)
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.
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_hist_value(double metric_value)
Add a value to the hisogram data.
void add_value(double metric_value)
Add a value to the running counts.
double pow(double value, const Exponent &exp)
void reset_data()
Reset all calculated data.
The MeshSet class stores one or more Mesquite::Mesh pointers and manages access to the mesh informati...
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 get_next_patch(PatchData &pd, PatchDataUser *pd_user, MsqError &err)
Gets the next PatchData.
void add_invalid_value()
Note invalid result.