diff --git a/examples/osgtransferfunction/osgtransferfunction.cpp b/examples/osgtransferfunction/osgtransferfunction.cpp index f8c08781d..7c59b7cb5 100644 --- a/examples/osgtransferfunction/osgtransferfunction.cpp +++ b/examples/osgtransferfunction/osgtransferfunction.cpp @@ -18,6 +18,8 @@ #include #include +#include +#include #include #include @@ -29,6 +31,308 @@ #include +class Histogram +{ +public: + Histogram() {} + + void analyse(const osg::Image* image, double interval=0.0); + + void insertZeroBoundaryValues(float xMin=FLT_MAX, float xMax=-FLT_MAX); + + osg::Node* createGraphicalRepresentation(); + + typedef std::map ValueMap; + + ValueMap& getValueMap() { return _valueMap; } + +protected: + + ValueMap _valueMap; +}; + +struct PopulateHistogram +{ + + PopulateHistogram(Histogram::ValueMap& valueMap): + _histogram(valueMap) {} + + float cast(char v) { return v; } + float cast(unsigned char v) { return v; } + float cast(short v) { return v; } + float cast(unsigned short v) { return v; } + float cast(int v) { return v; } + float cast(unsigned int v) { return v; } + float cast(float v) { return v; } + float cast(double v) { return v; } + + Histogram::ValueMap& _histogram; + + void update(int v) + { + _histogram[v]+=1.0; + } + + void normalize() + { + double maxValue = 0; + for(Histogram::ValueMap::iterator itr = _histogram.begin(); + itr != _histogram.end(); + ++itr) + { + if (itr->second>maxValue) maxValue = itr->second; + } + + for(Histogram::ValueMap::iterator itr = _histogram.begin(); + itr != _histogram.end(); + ++itr) + { + itr->second /= maxValue; + } + } + + void luminance(float l) { update(l); } + void alpha(float a) { update(a); } + void luminance_alpha(float l, float a) { update(l); } + void rgb(float r, float g, float b) { update(r); } + void rgba(float r, float g, float b, float a) { update(a); } +}; + +void Histogram::analyse(const osg::Image* image, double interval) +{ + PopulateHistogram populateHistogram(_valueMap); + readImage(image, populateHistogram); + populateHistogram.normalize(); + + for(Histogram::ValueMap::iterator itr = populateHistogram._histogram.begin(); + itr != populateHistogram._histogram.end(); + ++itr) + { + OSG_NOTICE<<" "<first<<", "<second<first) + { + _valueMap[xMin] = 0.0; + } + + if (xMax>_valueMap.rbegin()->first) + { + _valueMap[xMax] = 0.0; + } + + ValueMap::iterator itr = _valueMap.begin(); + float previous_x = itr->first; + for(; + itr != _valueMap.end(); + ++itr) + { + float current_x = itr->first; + float gap = current_x-previous_x; + if (gap>min_gap_for_double_insertion) + { + _valueMap[previous_x+interval] = 0.0f; + _valueMap[current_x-interval] = 0.0f; + } + else if (gap>min_gap_for_single_insertion) + { + _valueMap[(previous_x+current_x)*0.5]=0.0f; + } + previous_x = current_x; + } +} + +osg::Node* Histogram::createGraphicalRepresentation() +{ + if (_valueMap.empty()) return 0; + + osg::ref_ptr transform = new osg::MatrixTransform; + + float xMin = _valueMap.begin()->first; + float xMax = _valueMap.rbegin()->first; + + float depth = 0.0f; + float yMax = 0.0f; + + // find yMax + for(ValueMap::iterator itr = _valueMap.begin(); + itr != _valueMap.end(); + ++itr) + { + float y = itr->second; + if (y>yMax) yMax = y; + } + + float xScale = 1.0f/(xMax-xMin); + float yScale = 1.0f/yMax; + + { + osg::ref_ptr geode = new osg::Geode; + transform->addChild(geode.get()); + + osg::ref_ptr geometry = new osg::Geometry; + geode->addDrawable(geometry.get()); + geode->getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::OFF); + geode->getOrCreateStateSet()->setMode(GL_BLEND, osg::StateAttribute::ON); + + osg::ref_ptr vertices = new osg::Vec3Array; + geometry->setVertexArray(vertices.get()); + + osg::ref_ptr colours = new osg::Vec4Array; + geometry->setColorArray(colours.get(), osg::Array::BIND_PER_PRIMITIVE_SET); + colours->push_back(osg::Vec4(1.0,1.0,1.0,1.0)); + colours->push_back(osg::Vec4(1.0,1.0,1.0,1.0)); + colours->push_back(osg::Vec4(1.0,1.0,1.0,0.1)); + + + unsigned numColumnsRequired = _valueMap.size(); + vertices->reserve(numColumnsRequired*3); + for(ValueMap::iterator itr = _valueMap.begin(); + itr != _valueMap.end(); + ++itr) + { + float x = itr->first; + float y = itr->second; + + vertices->push_back(osg::Vec3(x*xScale, 0.0f, depth)); + vertices->push_back(osg::Vec3(x*xScale, y*yScale, depth)); + vertices->push_back(osg::Vec3(x*xScale, yMax*yScale, depth)); + } + + osg::ref_ptr background_primitives = new osg::DrawElementsUShort(GL_TRIANGLE_STRIP); + osg::ref_ptr historgram_primitives = new osg::DrawElementsUShort(GL_TRIANGLE_STRIP); + osg::ref_ptr outline_primitives = new osg::DrawElementsUShort(GL_LINE_STRIP); + for(unsigned int i=0; ipush_back(iv+2); + background_primitives->push_back(iv+1); + + historgram_primitives->push_back(iv+1); + historgram_primitives->push_back(iv+0); + + outline_primitives->push_back(iv+1); + + } + + geometry->addPrimitiveSet(outline_primitives.get()); + geometry->addPrimitiveSet(historgram_primitives.get()); + geometry->addPrimitiveSet(background_primitives.get()); + } + + //transform->setMatrix(osg::Matrix::scale(xScale/(maxX-minY), yScale/(yMax), 1.0f)); + + transform->setMatrix(osg::Matrix::scale(2.0,1.0,1.0)*osg::Matrix::rotate(osg::DegreesToRadians(90.0), osg::Vec3d(1.0,0.0,0.0))); + + return transform.release(); +} + +osg::Node* createGraphicalRepresentation(osg::TransferFunction1D* tf, unsigned int channel) +{ + typedef osg::TransferFunction1D::ColorMap ColorMap; + ColorMap& colorMap = tf->getColorMap(); + if (colorMap.empty()) return 0; + + osg::ref_ptr transform = new osg::MatrixTransform; + + float xMin = colorMap.begin()->first; + float xMax = colorMap.rbegin()->first; + + float depth = 0.0f; + float yMax = 0.0f; + + // find yMax + for(ColorMap::iterator itr = colorMap.begin(); + itr != colorMap.end(); + ++itr) + { + float y = itr->second[channel]; + if (y>yMax) yMax = y; + } + + float xScale = 1.0f/(xMax-xMin); + float yScale = 1.0f/yMax; + + { + osg::ref_ptr geode = new osg::Geode; + transform->addChild(geode.get()); + + osg::ref_ptr geometry = new osg::Geometry; + geode->addDrawable(geometry.get()); + geode->getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::OFF); + geode->getOrCreateStateSet()->setMode(GL_BLEND, osg::StateAttribute::ON); + + osg::ref_ptr vertices = new osg::Vec3Array; + geometry->setVertexArray(vertices.get()); + + osg::ref_ptr colours = new osg::Vec4Array; + geometry->setColorArray(colours.get(), osg::Array::BIND_PER_PRIMITIVE_SET); + colours->push_back(osg::Vec4(1.0,1.0,1.0,1.0)); + colours->push_back(osg::Vec4(1.0,1.0,1.0,1.0)); + colours->push_back(osg::Vec4(1.0,1.0,1.0,0.1)); + + + unsigned numColumnsRequired = colorMap.size(); + vertices->reserve(numColumnsRequired*3); + for(ColorMap::iterator itr = colorMap.begin(); + itr != colorMap.end(); + ++itr) + { + float x = itr->first; + float y = itr->second[channel]; + + vertices->push_back(osg::Vec3(x*xScale, 0.0f, depth)); + vertices->push_back(osg::Vec3(x*xScale, y*yScale, depth)); + vertices->push_back(osg::Vec3(x*xScale, yMax*yScale, depth)); + } + + osg::ref_ptr background_primitives = new osg::DrawElementsUShort(GL_TRIANGLE_STRIP); + osg::ref_ptr historgram_primitives = new osg::DrawElementsUShort(GL_TRIANGLE_STRIP); + osg::ref_ptr outline_primitives = new osg::DrawElementsUShort(GL_LINE_STRIP); + for(unsigned int i=0; ipush_back(iv+2); + background_primitives->push_back(iv+1); + + historgram_primitives->push_back(iv+1); + historgram_primitives->push_back(iv+0); + + outline_primitives->push_back(iv+1); + + } + + geometry->addPrimitiveSet(outline_primitives.get()); + geometry->addPrimitiveSet(historgram_primitives.get()); + geometry->addPrimitiveSet(background_primitives.get()); + } + + //transform->setMatrix(osg::Matrix::scale(xScale/(maxX-minY), yScale/(yMax), 1.0f)); + + transform->setMatrix(osg::Matrix::scale(2.0,1.0,1.0)*osg::Matrix::rotate(osg::DegreesToRadians(90.0), osg::Vec3d(1.0,0.0,0.0))); + + return transform.release(); +} + osg::TransferFunction1D* readTransferFunctionFile(const std::string& filename, float colorScale=1.0f) { @@ -108,8 +412,16 @@ int main(int argc, char ** argv) OSG_NOTICE<<"No image found."< group = new osg::Group; + group->addChild(histogram.createGraphicalRepresentation()); + //if (tf.valid()) group->addChild(createGraphicalRepresentation(tf.get(),1)); + + viewer.setSceneData(group.get()); + + osgDB::writeNodeFile(*viewer.getSceneData(),"graph.osgt"); return viewer.run(); }