/*========================================================================= Program: Visualization Toolkit Module: vtkSmoothErrorMetric.cxx Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ #include "vtkSmoothErrorMetric.h" #include "vtkObjectFactory.h" #include "vtkGenericAttribute.h" #include "vtkGenericAttributeCollection.h" #include "vtkGenericAdaptorCell.h" #include "vtkGenericDataSet.h" #include "vtkMath.h" #include vtkStandardNewMacro(vtkSmoothErrorMetric); //----------------------------------------------------------------------------- vtkSmoothErrorMetric::vtkSmoothErrorMetric() { this->AngleTolerance = 90.1; // in degrees this->CosTolerance = cos( vtkMath::RadiansFromDegrees( this->AngleTolerance ) ); } //----------------------------------------------------------------------------- vtkSmoothErrorMetric::~vtkSmoothErrorMetric() { } //----------------------------------------------------------------------------- double vtkSmoothErrorMetric::GetAngleTolerance() { return this->AngleTolerance; } //----------------------------------------------------------------------------- void vtkSmoothErrorMetric::SetAngleTolerance(double value) { // assert("pre: positive_value" && value>90 && value<180); if(this->AngleTolerance!=value) { // Clamp the value if(value<=90) { vtkWarningMacro(<< "value " << value << " out of range ]90,180[, clamped to 90.1" ); this->AngleTolerance=90.1; } else { if(value>=180) { vtkWarningMacro(<< "value " << value << " out of range ]90,180[, clamped to 179.9" ); this->AngleTolerance=179.9; } else { this->AngleTolerance=value; } } this->CosTolerance = cos( vtkMath::RadiansFromDegrees( this->AngleTolerance ) ); this->Modified(); } } //----------------------------------------------------------------------------- int vtkSmoothErrorMetric::RequiresEdgeSubdivision(double *leftPoint, double *midPoint, double *rightPoint, double vtkNotUsed(alpha) ) { assert( "pre: leftPoint_exists" && leftPoint != nullptr ); assert( "pre: midPoint_exists" && midPoint != nullptr ); assert( "pre: rightPoint_exists" && rightPoint != nullptr ); // assert( "pre: clamped_alpha" && alpha>0 && alpha < 1. ); // or else true if( this->GenericCell->IsGeometryLinear() ) { //don't need to do anything: return 0; } double a[3]; double b[3]; a[0] = leftPoint[0] - midPoint[0]; a[1] = leftPoint[1] - midPoint[1]; a[2] = leftPoint[2] - midPoint[2]; b[0] = rightPoint[0] - midPoint[0]; b[1] = rightPoint[1] - midPoint[1]; b[2] = rightPoint[2] - midPoint[2]; double dota = vtkMath::Dot( a, a ); double dotb = vtkMath::Dot( b, b ); double cosa; if( dota == 0 || dotb == 0 ) { cosa = -1.; } else { cosa = vtkMath::Dot( a, b ) / sqrt( dota * dotb ); } int result = ( cosa > this->CosTolerance ); return result; } //----------------------------------------------------------------------------- // Description: // Return the error at the mid-point. The type of error depends on the state // of the concrete error metric. For instance, it can return an absolute // or relative error metric. // See RequiresEdgeSubdivision() for a description of the arguments. // \post positive_result: result>=0 double vtkSmoothErrorMetric::GetError(double *leftPoint, double *midPoint, double *rightPoint, double vtkNotUsed(alpha) ) { assert( "pre: leftPoint_exists" && leftPoint != nullptr ); assert( "pre: midPoint_exists" && midPoint != nullptr ); assert( "pre: rightPoint_exists" && rightPoint != nullptr ); // assert( "pre: clamped_alpha" && alpha > 0. && alpha < 1. ); if( this->GenericCell->IsGeometryLinear() ) { //don't need to do anything: return 0.; } double a[3]; double b[3]; a[0] = leftPoint[0] - midPoint[0]; a[1] = leftPoint[1] - midPoint[1]; a[2] = leftPoint[2] - midPoint[2]; b[0] = rightPoint[0] - midPoint[0]; b[1] = rightPoint[1] - midPoint[1]; b[2] = rightPoint[2] - midPoint[2]; double dota = vtkMath::Dot(a,a); double dotb = vtkMath::Dot(b,b); double cosa; if( dota == 0. || dotb==0. ) { cosa = -1.; } else { cosa = vtkMath::Dot( a, b ) / sqrt( dota * dotb ); } if( cosa > 1.) { cosa = 1.; } else if( cosa < -1. ) { cosa = -1.; } double result = 180. - vtkMath::RadiansFromDegrees( acos( cosa ) ); assert( "post: positive_result" && result >= 0. ); return result; } //----------------------------------------------------------------------------- void vtkSmoothErrorMetric::PrintSelf(ostream& os, vtkIndent indent) { this->Superclass::PrintSelf(os,indent); os << indent << "AngleTolerance: " << this->AngleTolerance << endl; os << indent << "CosTolerance: " << this->CosTolerance << endl; }