From: <rha...@us...> - 2011-09-26 14:24:15
|
Revision: 384 http://mevislabmodules.svn.sourceforge.net/mevislabmodules/?rev=384&view=rev Author: rhameeteman Date: 2011-09-26 14:24:04 +0000 (Mon, 26 Sep 2011) Log Message: ----------- KH. * Added the posibility to calculate the distances between the COSs (with the same index) of two input Lists * Added a mode field specifying how to find the matching CSO, default is still the old behavior show the distance between the first 2 CSO of input0 and only the minimal distance. Modified Paths: -------------- trunk/Community/General/Modules/ML/MLCSOCommunityModules/MLCSOCommunityModules.def trunk/Community/General/Sources/ML/MLCSOCommunityModules/CSODistance/CSODistance.cpp trunk/Community/General/Sources/ML/MLCSOCommunityModules/CSODistance/CSODistance.h Modified: trunk/Community/General/Modules/ML/MLCSOCommunityModules/MLCSOCommunityModules.def =================================================================== --- trunk/Community/General/Modules/ML/MLCSOCommunityModules/MLCSOCommunityModules.def 2011-09-26 13:41:31 UTC (rev 383) +++ trunk/Community/General/Modules/ML/MLCSOCommunityModules/MLCSOCommunityModules.def 2011-09-26 14:24:04 UTC (rev 384) @@ -13,7 +13,7 @@ documentation = "$(LOCAL)/CSODistance/CSODistance.html" Window { - Category { + Category Totals { Field minimumDistance { edit = NO minLength = 10 } Separator { direction = Horizontal } Field minimumDistancePoint1 { minLength = 10 } @@ -27,12 +27,25 @@ Separator { direction = Horizontal } + RadioButtonGroup mode {} + Horizontal { + alignX = Left + Label {title = "Curve statistic:" } + ButtonBar curveStatistic { show = One } + } Horizontal { alignX = Right CheckBox = autoApply Button = apply } } + Category Distances { + expandY = Yes + ListView distances { + expandY = Yes + columnSeparator = "," + } + } } }// MLModule CSODistance Modified: trunk/Community/General/Sources/ML/MLCSOCommunityModules/CSODistance/CSODistance.cpp =================================================================== --- trunk/Community/General/Sources/ML/MLCSOCommunityModules/CSODistance/CSODistance.cpp 2011-09-26 13:41:31 UTC (rev 383) +++ trunk/Community/General/Sources/ML/MLCSOCommunityModules/CSODistance/CSODistance.cpp 2011-09-26 14:24:04 UTC (rev 384) @@ -15,23 +15,42 @@ handleNotificationOff(); - _csoList = NULL; + _csoList0 = NULL; + _csoList1 = NULL; + _tableHeader = "Id1,Id2,min,max,mean,stdDev"; FieldContainer* fieldC = getFieldContainer(); ML_CHECK(fieldC); - (_inputCSOFld = fieldC->addBase("inCSOList"))->setBaseValue(NULL); + (_input0CSOFld = fieldC->addBase("inCSOList"))->setBaseValue(NULL); + (_input1CSOFld = fieldC->addBase("inCSOList1"))->setBaseValue(NULL); ////////////////////////////////////////////////////////////////////////// + char* distanceModes[LASTMODE]; + distanceModes[ FIRST2 ] = "First 2 CSOs"; + distanceModes[ INPLANE ] = "Match in plane CSOs"; + distanceModes[ TWOINPUTS ] = "Match index of two CSOLists"; + _modeFld = fieldC->addEnum("mode",distanceModes,LASTMODE); + _modeFld->setEnumValue( FIRST2 ); + + ////////////////////////////////////////////////////////////////////////// + (_minimumDistanceFld = fieldC->addFloat("minimumDistance"))->setFloatValue(0); (_minimumDistancePoint1Fld = fieldC->addVec3f("minimumDistancePoint1"))->setVec3fValue(vec3(0.0,0.0,0.0)); (_minimumDistancePoint2Fld = fieldC->addVec3f("minimumDistancePoint2"))->setVec3fValue(vec3(0.0,0.0,0.0)); + _distancesFld = addString("distances",_tableHeader ); ////////////////////////////////////////////////////////////////////////// + _tolleranceFld = addDouble("tollerance", 0.0001 ); + + ////////////////////////////////////////////////////////////////////////// + _applyFld = fieldC->addNotify("apply"); (_autoApplyFld = fieldC->addBool("autoApply"))->setBoolValue(true); + _statusFld = fieldC->addString("status"); + _statusFld->setStringValue("Ready"); ////////////////////////////////////////////////////////////////////////// @@ -42,12 +61,21 @@ (_listenToSelectionChangedNotificationsFld = fieldC->addBool("listenToSelectionChangedNotifications")) ->setBoolValue(false); + char* statisticsNames[LASTSTATISTIC]; + statisticsNames[ MIN ] = "Minimum"; + statisticsNames[ MAX ] = "Maximum"; + statisticsNames[ MEAN ] = "Mean"; + statisticsNames[ STDEV ] = "StDev"; + _curveStatistic = addEnum("curveStatistic",statisticsNames,LASTSTATISTIC ); + _isInNotificationCB = false; ML_CHECK_NEW(_outputXMarkerList,XMarkerList()); (_outputXMarkerListFld = getFieldContainer()->addBase("outputXMarkerList"))->setBaseValue(NULL); + _outputCurveList = new CurveList; + (_outputCurveListFld = getFieldContainer()->addBase("outputCurveList"))->setBaseValue( _outputCurveList ); handleNotificationOn(); } @@ -58,11 +86,19 @@ { ML_TRACE_IN("CSODistance::~CSODistance()"); - if (_csoList != NULL){ - _csoList->removeNotificationObserver(_csoListNotificationCB, this); + if (_csoList0 != NULL){ + _csoList0->removeNotificationObserver(_csoListNotificationCB, this); } ML_DELETE(_outputXMarkerList); + + // Delete all created CurveData objects + while ( !_outputCurveList->getCurveList().empty() ) { + ML_DELETE( _outputCurveList->getCurveList().back() ); + _outputCurveList->getCurveList().pop_back(); + } + ML_DELETE( _outputCurveList ); + } ////////////////////////////////////////////////////////////////////////// @@ -84,26 +120,46 @@ { ML_TRACE_IN("void CSODistance::handleNotification(Field* field)"); - if (field == _inputCSOFld){ + if (field == _input0CSOFld){ - if (!_isInNotificationCB) { CSOList::removeNotificationObserverFromAllCSOLists(_csoListNotificationCB, this);} + if (!_isInNotificationCB && _csoList0 ) { _csoList0->removeNotificationObserver(_csoListNotificationCB, this);} - if (BASE_IS_A((static_cast<Base*>(_inputCSOFld->getBaseValue())), CSOList)){ + if (BASE_IS_A((static_cast<Base*>(_input0CSOFld->getBaseValue())), CSOList)){ - _csoList = static_cast<CSOList*>(_inputCSOFld->getBaseValue()); + _csoList0 = static_cast<CSOList*>(_input0CSOFld->getBaseValue()); - if (_csoList != NULL){ + if (_csoList0 != NULL){ - if (!_isInNotificationCB) { _csoList->addNotificationObserver(_csoListNotificationCB, this); } + if (!_isInNotificationCB) { _csoList0->addNotificationObserver(_csoListNotificationCB, this); } } } else { - _csoList = NULL; + _csoList0 = NULL; } if (_autoApplyFld->getBoolValue()) { _process(); } } else - if (field == _applyFld) { + if (field == _input1CSOFld){ + + if (!_isInNotificationCB && _csoList1 ) { _csoList1->removeNotificationObserver(_csoListNotificationCB, this);} + + if (BASE_IS_A((static_cast<Base*>(_input1CSOFld->getBaseValue())), CSOList)){ + + _csoList1 = static_cast<CSOList*>(_input1CSOFld->getBaseValue()); + + if (_csoList1 != NULL){ + + if (!_isInNotificationCB) { _csoList1->addNotificationObserver(_csoListNotificationCB, this); } + } + } else { + + _csoList1 = NULL; + } + + if (_autoApplyFld->getBoolValue()) { _process(); } + } else + if ( field == _applyFld || ( _autoApplyFld->getBoolValue() && + ( field == _tolleranceFld || field == _curveStatistic )) ){ _process(); } @@ -119,56 +175,248 @@ _outputXMarkerList->clearList(); - if (_csoList != NULL) { + // Delete all created CurveData objects + while ( !_outputCurveList->getCurveList().empty() ) { + ML_DELETE( _outputCurveList->getCurveList().back() ); + _outputCurveList->getCurveList().pop_back(); + } - if ((_csoList->numCSO() >= 2) && (_csoList->getCSOAt(0)->getIsFinished()) && (_csoList->getCSOAt(1)->getIsFinished())) { - MinimalDistancePointClouds* pointSetsMinDist = NULL; - ML_CHECK_NEW(pointSetsMinDist, MinimalDistancePointClouds); + if (_csoList0 != NULL) { - std::vector<vec3>pointSet1; - std::vector<vec3>pointSet2; - - _csoList->getCSOAt(0)->fillPathPointCoordinatesFlattened(pointSet1); - _csoList->getCSOAt(1)->fillPathPointCoordinatesFlattened(pointSet2); + int nCSOs = _csoList0->numCSO(); - pointSetsMinDist->setPointSets(pointSet1, pointSet2); - pointSetsMinDist->setNumEntries(200); + double minDistance = 0.0; + double maxDistance = 0.0; + double avgDistance = 0.0; + double stdDevDistance = 0.0; - vec3 nPoint1, nPoint2; - pointSetsMinDist->computeDistance(nPoint1,nPoint2); + std::stringstream distances; + distances << _tableHeader << std::endl; - _minimumDistancePoint1Fld->setVec3fValue(nPoint1); - _minimumDistancePoint2Fld->setVec3fValue(nPoint2); - double distance = sqrt((nPoint1[0]-nPoint2[0])*(nPoint1[0]-nPoint2[0]) + - (nPoint1[1]-nPoint2[1])*(nPoint1[1]-nPoint2[1]) + - (nPoint1[2]-nPoint2[2])*(nPoint1[2]-nPoint2[2])); + switch ( _modeFld->getEnumValue() ){ + case FIRST2 : + { + if ((nCSOs >= 2) && (_csoList0->getCSOAt(0)->getIsFinished()) && (_csoList0->getCSOAt(1)->getIsFinished())) { + std::vector<vec3>pointSet1; + std::vector<vec3>pointSet2; + + _csoList0->getCSOAt(0)->fillPathPointCoordinatesFlattened(pointSet1); + _csoList0->getCSOAt(1)->fillPathPointCoordinatesFlattened(pointSet2); - _minimumDistanceFld->setFloatValue(distance); + Vector3 minPoint1,minPoint2,maxPoint1,maxPoint2; - _outputXMarkerList->appendItem(XMarker(vec6(nPoint1[0],nPoint1[1],nPoint1[2],0.5f,0.0f,0.0f), - vec3(nPoint2[0]-nPoint1[0],nPoint2[1]-nPoint1[1],0.0f), - 0,"")); - - ML_DELETE(pointSetsMinDist); + MinimalDistancePointClouds* pointSetsMinDist = NULL; + ML_CHECK_NEW(pointSetsMinDist, MinimalDistancePointClouds); + + pointSetsMinDist->setPointSets(pointSet1, pointSet2); + pointSetsMinDist->setNumEntries(200); + pointSetsMinDist->computeDistance(minPoint1,minPoint2); - } else { - _minimumDistancePoint1Fld->setVec3fValue(vec3(0.0,0.0,0.0)); - _minimumDistancePoint2Fld->setVec3fValue(vec3(0.0,0.0,0.0)); - _minimumDistanceFld->setFloatValue(0.0f); + minDistance = sqrt((minPoint1[0]-minPoint2[0])*(minPoint1[0]-minPoint2[0]) + + (minPoint1[1]-minPoint2[1])*(minPoint1[1]-minPoint2[1]) + + (minPoint1[2]-minPoint2[2])*(minPoint1[2]-minPoint2[2])); + + + + _minimumDistanceFld->setFloatValue( static_cast<float>(minDistance)); + + _outputXMarkerList->appendItem(XMarker( vec6(minPoint1[0],minPoint1[1],minPoint1[2],0.5f,0.0f,0.0f), + vec3(minPoint2[0]-minPoint1[0],minPoint2[1]-minPoint1[1],minPoint2[2]-minPoint1[2]), + 0,"")); + distances << _csoList0->getCSOAt(0)->getId() << "," + << _csoList0->getCSOAt(1)->getId() << "," + << minDistance << "," + << maxDistance << "," + << avgDistance << "," + << stdDevDistance + << std::endl; + } else { + _minimumDistancePoint1Fld->setVec3fValue(vec3(0.0,0.0,0.0)); + _minimumDistancePoint2Fld->setVec3fValue(vec3(0.0,0.0,0.0)); + _minimumDistanceFld->setFloatValue(0.0f); + _distancesFld->setStringValue( _tableHeader ); + } + break; + } + case INPLANE: + { + CurveData *outputCurve = new CurveData; + double *yValues = new double[ nCSOs ]; + + double minDist = ML_DOUBLE_MAX; + vec3 point1; + vec3 point2; + for ( int iCSO = 0; iCSO<nCSOs; ++iCSO ){ + CSO* currentCSO = _csoList0->getCSOAt( iCSO ); + CSO* matchingCSO = _findMatchingCSO(iCSO); + if (!matchingCSO) {continue;} + + std::vector<vec3>pointSet1; + std::vector<vec3>pointSet2; + currentCSO->fillPathPointCoordinatesFlattened(pointSet1); + matchingCSO->fillPathPointCoordinatesFlattened(pointSet2); + + Vector3 minPoint1,minPoint2,maxPoint1,maxPoint2; + + _getDistances( pointSet1, pointSet2, + minDistance,maxDistance,avgDistance,stdDevDistance, + minPoint1,minPoint2,maxPoint1,maxPoint2); + + distances << currentCSO->getId() << "," + << matchingCSO->getId() << "," + << minDistance << "," + << maxDistance << "," + << avgDistance << "," + << stdDevDistance + << std::endl; + + if ( minDistance < minDist ){ + minDist = minDistance; + point1 = minPoint1; + point2 = minPoint2; + } + + _outputXMarkerList->appendItem(XMarker( vec6(minPoint1[0],minPoint1[1],minPoint1[2],0.5f,0.0f,0.0f), + vec3(minPoint2[0]-minPoint1[0],minPoint2[1]-minPoint1[1],minPoint2[2]-minPoint1[2]), + currentCSO->getId(),"")); + + switch ( _curveStatistic->getEnumValue() ){ + case MIN: + yValues[ iCSO ] = minDistance; + break; + case MAX: + yValues[ iCSO ] = maxDistance; + break; + case MEAN: + yValues[ iCSO ] = avgDistance; + break; + case STDEV: + yValues[ iCSO ] = stdDevDistance; + break; + default: + break; + } + } // iCSO + outputCurve->setY( nCSOs, yValues); + delete[] yValues; + _outputCurveList->getCurveList().push_back( outputCurve ); + _distancesFld->setStringValue( distances.str() ); + _minimumDistancePoint1Fld->setVec3fValue(point1); + _minimumDistancePoint2Fld->setVec3fValue(point2); + _minimumDistanceFld->setFloatValue( static_cast<float>(minDistance) ); + break; + } + default: + break; } + } else { _minimumDistancePoint1Fld->setVec3fValue(vec3(0.0,0.0,0.0)); _minimumDistancePoint2Fld->setVec3fValue(vec3(0.0,0.0,0.0)); _minimumDistanceFld->setFloatValue(0.0f); + _distancesFld->setStringValue( _tableHeader ); } _outputXMarkerListFld->setBaseValue(_outputXMarkerList); + _outputCurveListFld->touch(); } ////////////////////////////////////////////////////////////////////////// +void CSODistance::_getDistances( std::vector<Vector3> &set1, + std::vector<Vector3> &set2, + double &minDistance, + double &maxDistance, + double &averageDistance, + double &stdDevDistance, + Vector3 &minPoint1, + Vector3 &minPoint2, + Vector3 &maxPoint1, + Vector3 &maxPoint2) +{ + + + minDistance = ML_DOUBLE_MAX; + maxDistance = 0.0; + double sumDist = 0.0; + double sqrDist = 0.0; + for(int i = 0; i < int(set1.size()); i++) + { + Vector3 pos1 = set1[i]; + Vector3 pos2; + double currentDistance = ML_DOUBLE_MAX; + for(int j = 0; j < int( set2.size() ); j++) + { + Vector3 pos = set2[j]; + double dist = (pos1 - pos).length(); + if ( dist < currentDistance ){ + currentDistance = dist; + pos2 = pos; + } + } + + if ( minDistance > currentDistance ){ + minDistance = currentDistance; + minPoint1 = pos1; + minPoint2 = pos2; + } + if (maxDistance < currentDistance ){ + maxDistance = currentDistance; + maxPoint1 = pos1; + maxPoint2 = pos2; + } + sumDist += currentDistance; + sqrDist += currentDistance*currentDistance; + } + double nPoints = ( set1.size() ? static_cast<double>(set1.size()) : 1.0); + averageDistance = sumDist/nPoints; + stdDevDistance = sqrDist/nPoints - averageDistance*averageDistance; +} + +////////////////////////////////////////////////////////////////////////// + +CSO* CSODistance::_findMatchingCSO(int findCSO) +{ + CSO* matchingCSO = NULL; + + if ( _modeFld->getEnumValue() == TWOINPUTS && _csoList0 != NULL && _csoList1 != NULL) { + if (findCSO < static_cast<int>( _csoList1->numCSO()) ){ + matchingCSO = _csoList1->getCSOAt( findCSO ); + } + } else { + + const int nCSOs = _csoList0->numCSO(); + const CSO* currentCSO = _csoList0->getCSOAt( findCSO ); + const double tollerance = _tolleranceFld->getDoubleValue(); + vec3 currentNormal = currentCSO->getPlaneNormal(); + currentNormal.normalize(); + const vec3 currentPoint = currentCSO->getFirstSeedPoint()->worldPosition; + + double minError = ML_DOUBLE_MAX; + for ( int iCSO = 0; iCSO<nCSOs; ++iCSO ){ + CSO* cso = _csoList0->getCSOAt( iCSO ); + if ( cso == currentCSO ) { continue; } + vec3 normal = cso->getPlaneNormal(); + normal.normalize(); + const vec3 matchingPoint = cso->getFirstSeedPoint()->worldPosition; + const double angleError = 1- abs( currentNormal.dot( normal )); + const double distanceError = abs(currentNormal.dot( matchingPoint - currentPoint )); + const double currentError = angleError + distanceError; + if ( currentError < minError && angleError < tollerance && distanceError < 10*tollerance ) { + minError = currentError; + matchingCSO = cso; + } + } + } + + return matchingCSO; +} + + +////////////////////////////////////////////////////////////////////////// + void CSODistance::_csoListNotificationCB(void* userData, int notificationFlag) { ML_TRACE_IN("void CSODistance::_csoListNotificationCB()"); Modified: trunk/Community/General/Sources/ML/MLCSOCommunityModules/CSODistance/CSODistance.h =================================================================== --- trunk/Community/General/Sources/ML/MLCSOCommunityModules/CSODistance/CSODistance.h 2011-09-26 13:41:31 UTC (rev 383) +++ trunk/Community/General/Sources/ML/MLCSOCommunityModules/CSODistance/CSODistance.h 2011-09-26 14:24:04 UTC (rev 384) @@ -8,6 +8,7 @@ #include "../MinimalDistancePointClouds/MinimalDistancePointClouds.h" #include <mlXMarkerList.h> +#include <mlDiagramData.h> ML_START_NAMESPACE @@ -23,6 +24,8 @@ //! Standard constructor. CSODistance(); + enum {FIRST2=0, INPLANE, TWOINPUTS, LASTMODE}; + protected: //! Standard destructor. @@ -39,8 +42,14 @@ /* FIELDS */ //! CSO input field. - BaseField* _inputCSOFld; + BaseField* _input0CSOFld; + //! CSO input field. + BaseField* _input1CSOFld; + + //! Mode + EnumField* _modeFld; + //! Shall the module update on every event? BoolField* _listenToRepaintNotificationsFld; //! Shall the module listen to finishing events? @@ -48,33 +57,55 @@ //! Shall the module listen to selection change notifications? BoolField* _listenToSelectionChangedNotificationsFld; + //! Only calculate distances for CSOs in the same plane. + DoubleField* _tolleranceFld; + //! Field for displaying the minimum distance. FloatField* _minimumDistanceFld; //! Field for displaying the position of the first point Vec3fField* _minimumDistancePoint1Fld; //! Field for displaying the position of the second point Vec3fField* _minimumDistancePoint2Fld; + //! Field for holding the distances per cso + StringField* _distancesFld; //! Apply field NotifyField* _applyFld; //! Auto apply field BoolField* _autoApplyFld; + //! Status field + StringField* _statusFld; + //! XMarkerList output field BaseField *_outputXMarkerListFld; + //! CurveList output field; + BaseField* _outputCurveListFld; + + //! Output statistic + EnumField* _curveStatistic; + + enum STATISTICS {MIN,MAX,MEAN,STDEV,LASTSTATISTIC}; /* MEMBER VARIABLES */ //! A pointer to the input CSOList. - CSOList* _csoList; + CSOList* _csoList0; + //! A pointer to the input CSOList. + CSOList* _csoList1; + //! Locking variable... bool _isInNotificationCB; //! Output XMarkerList XMarkerList *_outputXMarkerList; + //! output CurveList + CurveList* _outputCurveList; + std::string _tableHeader; + /* METHODS */ //! Reads out information and displays them. @@ -83,6 +114,19 @@ //! Can be notified from anywhere in the network. static void _csoListNotificationCB(void* userData, int notificationFlag); + CSO* _findMatchingCSO(int csoIndex); + + void _getDistances( std::vector<Vector3> &set1, + std::vector<Vector3> &set2, + double &minDistance, + double &maxDistance, + double &averageDistance, + double &stdDevDistance, + Vector3 &minPoint1, + Vector3 &minPoint2, + Vector3 &maxPoint1, + Vector3 &maxPoint2); + ML_BASEOP_CLASS_HEADER(CSODistance); }; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |