Commit 65566188 authored by Pavel Vainerman's avatar Pavel Vainerman

(Calibration): перешёл на использование vector вместо list, переписал функцию…

(Calibration): перешёл на использование vector вместо list, переписал функцию поиска (сделал поиск методом половинного деления).
parent d4980d69
...@@ -275,6 +275,12 @@ ...@@ -275,6 +275,12 @@
<!-- <xi:include href="testIDnon-exist.xml"/> --> <!-- <xi:include href="testIDnon-exist.xml"/> -->
<Calibrations name="Calibrations"> <Calibrations name="Calibrations">
<diagram name="testcal"> <diagram name="testcal">
<point x="-1000" y="-300"/>
<point x="-900" y="-250"/>
<point x="-800" y="-200"/>
<point x="-700" y="-150"/>
<point x="-600" y="-100"/>
<point x="-500" y="-80"/>
<point x="-200" y="-60"/> <point x="-200" y="-60"/>
<point x="-100" y="-60"/> <point x="-100" y="-60"/>
<point x="-50" y="-20"/> <point x="-50" y="-20"/>
...@@ -282,6 +288,14 @@ ...@@ -282,6 +288,14 @@
<point x="50" y="20"/> <point x="50" y="20"/>
<point x="100" y="60"/> <point x="100" y="60"/>
<point x="200" y="60"/> <point x="200" y="60"/>
<point x="300" y="80"/>
<point x="400" y="100"/>
<point x="500" y="150"/>
<point x="600" y="200"/>
<point x="700" y="250"/>
<point x="800" y="300"/>
<point x="900" y="400"/>
<point x="1000" y="600"/>
</diagram> </diagram>
</Calibrations> </Calibrations>
</UNISETPLC> </UNISETPLC>
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
#include <cmath> #include <cmath>
#include <string> #include <string>
#include <list> #include <vector>
#include <ostream> #include <ostream>
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
/*! /*!
...@@ -55,8 +55,11 @@ class Calibration ...@@ -55,8 +55,11 @@ class Calibration
Calibration( xmlNode* node ); Calibration( xmlNode* node );
~Calibration(); ~Calibration();
/*! Тип для хранения значения */
typedef float TypeOfValue;
/*! выход за границы диапазона */ /*! выход за границы диапазона */
static const int outOfRange=-1; static const TypeOfValue outOfRange;
/*! /*!
Получение калиброванного значения Получение калиброванного значения
...@@ -103,10 +106,6 @@ class Calibration ...@@ -103,10 +106,6 @@ class Calibration
*/ */
void build( const std::string& name, const std::string& confile, xmlNode* node=0 ); void build( const std::string& name, const std::string& confile, xmlNode* node=0 );
/*! Тип для хранения текущего значения */
typedef float TypeOfValue;
/*! преобразование типа для хранения /*! преобразование типа для хранения
в тип для аналоговых датчиков в тип для аналоговых датчиков
*/ */
...@@ -121,6 +120,8 @@ class Calibration ...@@ -121,6 +120,8 @@ class Calibration
/*! точка характеристики */ /*! точка характеристики */
struct Point struct Point
{ {
Point():x(outOfRange),y(outOfRange){}
Point( TypeOfValue _x, TypeOfValue _y ): Point( TypeOfValue _x, TypeOfValue _y ):
x(_x),y(_y){} x(_x),y(_y){}
...@@ -137,6 +138,7 @@ class Calibration ...@@ -137,6 +138,7 @@ class Calibration
class Part class Part
{ {
public: public:
Part();
Part( const Point& pleft, const Point& pright ); Part( const Point& pleft, const Point& pright );
~Part(){}; ~Part(){};
...@@ -175,15 +177,15 @@ class Calibration ...@@ -175,15 +177,15 @@ class Calibration
TypeOfValue k; /*!< коэффициент наклона */ TypeOfValue k; /*!< коэффициент наклона */
}; };
protected:
// список надо отсортировать по x! // список надо отсортировать по x!
typedef std::list<Part> PartsList; typedef std::vector<Part> PartsVec;
protected:
long minRaw, maxRaw, minVal, maxVal, rightVal, leftVal, rightRaw, leftRaw; long minRaw, maxRaw, minVal, maxVal, rightVal, leftVal, rightRaw, leftRaw;
private: private:
PartsList plist; PartsVec pvec;
std::string myname; std::string myname;
}; };
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
......
#include <sstream> #include <sstream>
#include <iostream> #include <iostream>
#include <limits>
#include <algorithm> #include <algorithm>
#include "UniXML.h" #include "UniXML.h"
#include "Exceptions.h" #include "Exceptions.h"
...@@ -8,6 +9,13 @@ ...@@ -8,6 +9,13 @@
using namespace std; using namespace std;
using namespace UniSetTypes; using namespace UniSetTypes;
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
const Calibration::TypeOfValue Calibration::outOfRange = std::numeric_limits<Calibration::TypeOfValue>::max();
// ----------------------------------------------------------------------------
Calibration::Part::Part():
k(0)
{
}
Calibration::Part::Part( const Point& pleft, const Point& pright ): Calibration::Part::Part( const Point& pleft, const Point& pright ):
p_left(pleft), p_left(pleft),
...@@ -96,6 +104,7 @@ Calibration::TypeOfValue Calibration::Part::calcX( const TypeOfValue& y ) const ...@@ -96,6 +104,7 @@ Calibration::TypeOfValue Calibration::Part::calcX( const TypeOfValue& y ) const
Calibration::Calibration(): Calibration::Calibration():
minRaw(0),maxRaw(0),minVal(0),maxVal(0),rightVal(0),leftVal(0),rightRaw(0),leftRaw(0), minRaw(0),maxRaw(0),minVal(0),maxVal(0),rightVal(0),leftVal(0),rightRaw(0),leftRaw(0),
pvec(50),
myname("") myname("")
{ {
} }
...@@ -104,6 +113,7 @@ myname("") ...@@ -104,6 +113,7 @@ myname("")
Calibration::Calibration( const string& name, const string& confile ): Calibration::Calibration( const string& name, const string& confile ):
minRaw(0),maxRaw(0),minVal(0),maxVal(0),rightVal(0),leftVal(0),rightRaw(0),leftRaw(0), minRaw(0),maxRaw(0),minVal(0),maxVal(0),rightVal(0),leftVal(0),rightRaw(0),leftRaw(0),
pvec(50),
myname(name) myname(name)
{ {
build(name,confile,0); build(name,confile,0);
...@@ -111,7 +121,7 @@ myname(name) ...@@ -111,7 +121,7 @@ myname(name)
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
Calibration::Calibration( xmlNode* node ): Calibration::Calibration( xmlNode* node ):
minRaw(0),maxRaw(0),minVal(0),maxVal(0),rightVal(0),leftVal(0),rightRaw(0),leftRaw(0) minRaw(0),maxRaw(0),minVal(0),maxVal(0),rightVal(0),leftVal(0),rightRaw(0),leftRaw(0),pvec(100)
{ {
UniXML_iterator it(node); UniXML_iterator it(node);
myname = it.getProp("name"); myname = it.getProp("name");
...@@ -143,7 +153,7 @@ void Calibration::build( const string& name, const string& confile, xmlNode* roo ...@@ -143,7 +153,7 @@ void Calibration::build( const string& name, const string& confile, xmlNode* roo
} }
UniXML_iterator it(root); UniXML_iterator it(root);
if( !it.goChildren() ) if( !it.goChildren() )
{ {
ostringstream err; ostringstream err;
...@@ -154,24 +164,22 @@ void Calibration::build( const string& name, const string& confile, xmlNode* roo ...@@ -154,24 +164,22 @@ void Calibration::build( const string& name, const string& confile, xmlNode* roo
cerr << err.str() << endl; cerr << err.str() << endl;
throw Exception(err.str()); throw Exception(err.str());
} }
bool prev = false; bool prev = false;
Point prev_point(0,0); Point prev_point(0,0);
unsigned int i=0;
for(;it;it.goNext()) for(;it;it.goNext())
{ {
Point p(prev_point); Point p(prev_point);
p.x = atof(it.getProp("x").c_str()); p.x = atof(it.getProp("x").c_str());
p.y = atof(it.getProp("y").c_str()); p.y = atof(it.getProp("y").c_str());
if( p.x==0 || p.y==0 ) if( p.x==0 || p.y==0 )
{ {
cerr << myname << "(Calibration::build): (warn) x=" cerr << myname << "(Calibration::build): (warn) x="
<< p.x << " y=" << p.y << endl; << p.x << " y=" << p.y << endl;
} }
// cout << myname << "(Calibration::build):"
// << "\tadd x=" << p.x << " y=" << p.y << endl;
if( p.x > maxRaw ) if( p.x > maxRaw )
maxRaw = p.x; maxRaw = p.x;
else if( p.x < minRaw ) else if( p.x < minRaw )
...@@ -184,26 +192,25 @@ void Calibration::build( const string& name, const string& confile, xmlNode* roo ...@@ -184,26 +192,25 @@ void Calibration::build( const string& name, const string& confile, xmlNode* roo
if( prev ) if( prev )
{ {
// cout << myname << "(Calibration::build):"
// << "\tadd x=" << p.x << " y=" << p.y
// << " prev.x=" << prev_point.x
// << " prev.y=" << prev_point.y
// << endl;
Part pt(prev_point,p); Part pt(prev_point,p);
plist.push_back(pt); pvec[i++] = pt;
if( i >= pvec.size() )
pvec.resize(pvec.size()+20);
} }
else else
prev = true; prev = true;
prev_point = p; prev_point = p;
} }
plist.sort(); pvec.resize(i); // приводим размер к фактическому..
PartsList::iterator beg = plist.begin(); std::sort(pvec.begin(),pvec.end());
PartsList::iterator end = plist.end();
PartsVec::iterator beg = pvec.begin();
if( plist.size() > 0 ) PartsVec::iterator end = pvec.end();
if( pvec.size() > 0 )
{ {
leftRaw = beg->left_x(); leftRaw = beg->left_x();
leftVal = beg->left_y(); leftVal = beg->left_y();
...@@ -219,6 +226,27 @@ void Calibration::build( const string& name, const string& confile, xmlNode* roo ...@@ -219,6 +226,27 @@ void Calibration::build( const string& name, const string& confile, xmlNode* roo
} }
} }
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// рекурсивная функция поиска методом "половинного деления"
static Calibration::PartsVec::iterator find_range( long raw, Calibration::PartsVec::iterator beg,
Calibration::PartsVec::iterator end )
{
if( beg->checkX(raw) )
return beg;
if( end->checkX(raw) )
return end;
Calibration::PartsVec::iterator it = beg + std::distance(beg,end)/2;
if( raw < it->left_x() )
return find_range(raw,beg,it);
if( raw > it->right_x() )
return find_range(raw,it,end);
return it;
}
// ----------------------------------------------------------------------------
long Calibration::getValue( long raw, bool crop_raw ) long Calibration::getValue( long raw, bool crop_raw )
{ {
// если x левее первого отрезка то берём первую точку... // если x левее первого отрезка то берём первую точку...
...@@ -229,19 +257,21 @@ long Calibration::getValue( long raw, bool crop_raw ) ...@@ -229,19 +257,21 @@ long Calibration::getValue( long raw, bool crop_raw )
if( raw > rightRaw ) if( raw > rightRaw )
return (crop_raw ? rightVal : outOfRange); return (crop_raw ? rightVal : outOfRange);
for( PartsList::iterator it=plist.begin(); it!=plist.end(); ++it ) PartsVec::iterator fit = find_range(raw, pvec.begin(), pvec.end());
{
TypeOfValue q = it->getY(raw); if( fit == pvec.end() )
if( q != outOfRange ) return outOfRange;
return tRound(q);
} TypeOfValue q = fit->getY(raw);
if( q != outOfRange )
return tRound(q);
return outOfRange; return outOfRange;
} }
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
long Calibration::getRawValue( long cal, bool range ) long Calibration::getRawValue( long cal, bool range )
{ {
for( PartsList::iterator it=plist.begin(); it!=plist.end(); ++it ) for( PartsVec::iterator it=pvec.begin(); it!=pvec.end(); ++it )
{ {
TypeOfValue q = it->getX(cal); TypeOfValue q = it->getX(cal);
if( q != outOfRange ) if( q != outOfRange )
...@@ -256,14 +286,14 @@ long Calibration::getRawValue( long cal, bool range ) ...@@ -256,14 +286,14 @@ long Calibration::getRawValue( long cal, bool range )
if( cal > rightVal ) if( cal > rightVal )
return rightRaw; return rightRaw;
} }
return outOfRange; return outOfRange;
} }
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
std::ostream& operator<<( std::ostream& os, Calibration& c ) std::ostream& operator<<( std::ostream& os, Calibration& c )
{ {
os << "*******************" << endl; os << "*******************" << endl;
for( Calibration::PartsList::iterator it=c.plist.begin(); it!=c.plist.end(); ++it ) for( Calibration::PartsVec::iterator it=c.pvec.begin(); it!=c.pvec.end(); ++it )
{ {
os << "[" << it->leftPoint().x << " : " << it->rightPoint().x << " ] --> [" os << "[" << it->leftPoint().x << " : " << it->rightPoint().x << " ] --> ["
<< it->leftPoint().y << " : " << it->rightPoint().y << " ]" << it->leftPoint().y << " : " << it->rightPoint().y << " ]"
...@@ -276,14 +306,14 @@ std::ostream& operator<<( std::ostream& os, Calibration& c ) ...@@ -276,14 +306,14 @@ std::ostream& operator<<( std::ostream& os, Calibration& c )
std::ostream& operator<<( std::ostream& os, Calibration* c ) std::ostream& operator<<( std::ostream& os, Calibration* c )
{ {
os << "*******************" << endl; os << "*******************" << endl;
for( Calibration::PartsList::iterator it=c->plist.begin(); it!=c->plist.end(); ++it ) for( Calibration::PartsVec::iterator it=c->pvec.begin(); it!=c->pvec.end(); ++it )
{ {
os << "[" << it->leftPoint().x << " : " << it->rightPoint().x << " ] --> [" os << "[" << it->leftPoint().x << " : " << it->rightPoint().x << " ] --> ["
<< it->leftPoint().y << " : " << it->rightPoint().y << " ]" << it->leftPoint().y << " : " << it->rightPoint().y << " ]"
<< endl; << endl;
} }
os << "*******************" << endl; os << "*******************" << endl;
return os; return os;
} }
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
...@@ -19,6 +19,12 @@ int main( int argc, const char** argv ) ...@@ -19,6 +19,12 @@ int main( int argc, const char** argv )
cout << "diagram: " << cal << endl; cout << "diagram: " << cal << endl;
cout << "-1500 --> " << cal->getValue(-1500) << endl; cout << "-1500 --> " << cal->getValue(-1500) << endl;
cout << "-933 --> " << cal->getValue(-933) << endl;
cout << "-844 --> " << cal->getValue(-844) << endl;
cout << "-540 --> " << cal->getValue(-540) << endl;
cout << "-320 --> " << cal->getValue(-320) << endl;
cout << "-200 --> " << cal->getValue(-200) << endl;
cout << "-100 --> " << cal->getValue(-100) << endl;
cout << "-200 --> " << cal->getValue(-200) << endl; cout << "-200 --> " << cal->getValue(-200) << endl;
cout << "-100 --> " << cal->getValue(-100) << endl; cout << "-100 --> " << cal->getValue(-100) << endl;
cout << " -75 --> " << cal->getValue(-75) << endl; cout << " -75 --> " << cal->getValue(-75) << endl;
...@@ -30,6 +36,10 @@ int main( int argc, const char** argv ) ...@@ -30,6 +36,10 @@ int main( int argc, const char** argv )
cout << " 75 --> " << cal->getValue(75) << endl; cout << " 75 --> " << cal->getValue(75) << endl;
cout << " 100 --> " << cal->getValue(100) << endl; cout << " 100 --> " << cal->getValue(100) << endl;
cout << " 200 --> " << cal->getValue(200) << endl; cout << " 200 --> " << cal->getValue(200) << endl;
cout << " 310 --> " << cal->getValue(310) << endl;
cout << " 415 --> " << cal->getValue(415) << endl;
cout << " 556 --> " << cal->getValue(556) << endl;
cout << " 873 --> " << cal->getValue(873) << endl;
cout << " 1500 --> " << cal->getValue(1500) << endl; cout << " 1500 --> " << cal->getValue(1500) << endl;
cout << endl << " RAW VALUE.." << endl; cout << endl << " RAW VALUE.." << endl;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment