#ifndef QEX_GRAPHICS_TOLLERANCE_H#define QEX_GRAPHICS_TOLLERANCE_H#include "config.h"class WIN_EXPORT QexGraphicsTollerance{private: double absolute_distance; double relative_distance;public: QexGraphicsTollerance (); QexGraphicsTollerance & setAbsoluteDistance ( double distance ); double absoluteDistance () const; QexGraphicsTollerance & setRelativeDistance ( double distance ); double relativeDistance () const; bool operator == ( const QexGraphicsTollerance & other ) const; bool operator != ( const QexGraphicsTollerance & other ) const;};#endif
#ifndef QEX_GRAPHICS_CURVE_FILTER_H#define QEX_GRAPHICS_CURVE_FILTER_H#include "QexGraphicsTollerance.h"typedef QVector< int > glIndexArray;typedef QVector< QexPoint3Df > glPointArray;class WIN_EXPORT QexGraphicsCurveFilter{private: QexGraphicsTollerance filter_tollerance;public: QexGraphicsCurveFilter ( const QexGraphicsTollerance & tollerance ); void setTollerance ( const QexGraphicsTollerance & tollerance ); const QexGraphicsTollerance & tollerance () const; glIndexArray filter ( const glPointArray & points ) const; glIndexArray filter ( const glPointArray & points, glIndexArray indices ) const; glIndexArray filter ( int point_count, const QexPoint3Df * points ) const; glIndexArray filter ( const QexPoint3Df * points, int index_count, const int * indices = 0 ) const; GLfloat length ( const QexPoint3Df * points, int index_count, const int * indices ) const;};#endif // QEX_GRAPHICS_CURVE_FILTER_H
#include "QexGraphicsCurveFilter.h"QexGraphicsCurveFilter::QexGraphicsCurveFilter ( const QexGraphicsTollerance & tollerance ) : filter_tollerance( tollerance ){};void QexGraphicsCurveFilter::setTollerance ( const QexGraphicsTollerance & tollerance ){ filter_tollerance = tollerance;};const QexGraphicsTollerance & QexGraphicsCurveFilter::tollerance () const{ return filter_tollerance;};glIndexArray QexGraphicsCurveFilter::filter ( const glPointArray & points ) const{ return filter( points.count(), points.constData() );};glIndexArray QexGraphicsCurveFilter::filter ( const glPointArray & points, glIndexArray indices ) const{ return filter( points.constData(), indices.count(), indices.constData() );};glIndexArray QexGraphicsCurveFilter::filter ( int point_count, const QexPoint3Df * points ) const{ return filter( points, point_count, 0 );};#define CF_INDEX( i ) ( indices ? indices[ ( i ) ] : ( i ) )GLfloat QexGraphicsCurveFilter::length ( const QexPoint3Df * points, int index_count, const int * indices ) const{ GLfloat result( 0 ); for ( int i = 1; i < index_count; ++i ) { result += QexVector3Df::abs( QexVector3Df( points[ CF_INDEX( i ) ], points[ CF_INDEX( i - 1 ) ] ) ); } return result;}glIndexArray QexGraphicsCurveFilter::filter ( const QexPoint3Df * points, int index_count, const int * indices ) const{ if ( !index_count ) return glIndexArray(); GLfloat ref_abs_dist= qMax< GLfloat >( tollerance().absoluteDistance(), 0 ); GLfloat ref_rel_dist = qMax< GLfloat >( tollerance().relativeDistance(), 0 ); if ( ref_rel_dist ) ref_rel_dist *= length( points, index_count, indices ); GLfloat ref_distance = ref_abs_dist && ref_rel_dist ? qMin( ref_abs_dist, ref_rel_dist ) : qMax( ref_abs_dist, ref_rel_dist ); glIndexArray ret; int index_first = CF_INDEX( 0 ); ret.append( index_first ); // всегда добавляется первый int index; for ( int i = 1; i < index_count; ++i ) { index = CF_INDEX( i ); if ( ref_distance ) { index_first = CF_INDEX( i - 1 ); QexVector3Df vector( points[ index_first ], points[ index ] ); // проверяем index_next int index_next; for ( int j = i + 1; j < index_count; ++j ) { index_next = CF_INDEX( j ); GLfloat diviation = QexVector3Df::abs( QexVector3Df( points[ index ], points[ index_next ] ) ); if ( diviation < ref_distance ) continue; QexVector3Df vector_next( points[ index_first ], points[ index_next ] ); diviation = QexVector3Df::abs( vector ) * sin( QexVector3Df::angle( vector, vector_next ) ); if ( diviation >= ref_distance ) { i = j - 1; ret.append( index ); break; } } } else { ret.append( index ); } } // добавляется последний, если еще не добавлен index = CF_INDEX( index_count - 1 ); if ( ret.last() != index || ret.count() == 1 ) ret.append( index ); return ret;};#undef CF_INDEX
diviation = QexVector3Df::abs( vector ) * sin( QexVector3Df::angle( vector, vector_next ) );
C++ (Qt)diviation = fabs(QexVector3Df::cross( vector, vector_next )) / QexVector3Df::abs( vector_next );