Skip to content
Snippets Groups Projects
Commit e2cd1b89 authored by Ansgar Philippsen's avatar Ansgar Philippsen
Browse files

fixes and modifications to gfx.Gradient; pooled gfx py tests into one file

In Python, gfx.Gradient can now be initialized with a dictionary; for each
key: value pair, the key is a float between 0 and 1, and the value is either
a float triplet or a gfx.Color object.

In C++, Stop and StopList were moved into Gradient to avoid namespace
pollution. In Python, they were renamed to GradientStop and GradientStopList.
As a consequence, gui/pymod/scene/gradient_editor_widget.py has had a rename
of its GradientStop to MyGradientStop.
parent 68318cee
No related branches found
No related tags found
No related merge requests found
...@@ -11,6 +11,7 @@ set(OST_GFX_PYMOD_SOURCES ...@@ -11,6 +11,7 @@ set(OST_GFX_PYMOD_SOURCES
export_scene_observer.cc export_scene_observer.cc
export_render_options.cc export_render_options.cc
export_color.cc export_color.cc
export_gradient.cc
export_color_ops.cc export_color_ops.cc
export_glwin_base.cc export_glwin_base.cc
) )
......
//------------------------------------------------------------------------------
// This file is part of the OpenStructure project <www.openstructure.org>
//
// Copyright (C) 2008-2011 by the OpenStructure authors
//
// This library is free software; you can redistribute it and/or modify it under
// the terms of the GNU Lesser General Public License as published by the Free
// Software Foundation; either version 3.0 of the License, or (at your option)
// any later version.
// This library is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
// details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with this library; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
//------------------------------------------------------------------------------
#include <boost/python.hpp>
#include <boost/python/suite/indexing/vector_indexing_suite.hpp>
using namespace boost::python;
#include <ost/message.hh>
#include <ost/gfx/gradient.hh>
using namespace ost;
using namespace ost::gfx;
namespace {
Gradient* make_gradient(const dict& d)
{
std::auto_ptr<Gradient> grad(new Gradient);
list keys = d.keys();
for(int i=0;i<len(keys);++i) {
extract<float> fex(keys[i]);
if(!fex.check()) {
throw std::runtime_error("expected floats as keys");
}
float mark = fex();
Color col;
object val = d[keys[i]];
extract<Color> cex(val);
if(cex.check()) {
// use gfx.Color
col=cex();
} else {
// try simple sequence
if(len(val)!=3) {
throw std::runtime_error("expected values of gfx.Color or float triplets");
}
try {
col=gfx::Color(extract<float>(val[0]),extract<float>(val[1]),extract<float>(val[2]));
} catch (...) {
throw std::runtime_error("expected values of gfx.Color or float triplets");
}
}
grad->SetColorAt(mark,col);
}
return grad.release();
}
}
void export_gradient()
{
class_<Gradient>("Gradient", init<>())
.def(init<const String&>())
.def("__init__", make_constructor(make_gradient))
.def("SetColorAt", &Gradient::SetColorAt)
.def("GetColorAt", &Gradient::GetColorAt)
.def("GetStops", &Gradient::GetStops)
.def("GradientToInfo", &Gradient::GradientToInfo)
.def("GradientFromInfo", &Gradient::GradientFromInfo).staticmethod("GradientFromInfo")
;
implicitly_convertible<String, Gradient>();
class_<Gradient::StopList>("GradientStopList", init<>())
.def(vector_indexing_suite<Gradient::StopList>())
;
class_<Gradient::Stop>("GradientStop", init<>())
.def("GetColor", &Gradient::Stop::GetColor)
.add_property("color", &Gradient::Stop::GetColor)
.def("GetRel", &Gradient::Stop::GetRel)
.add_property("rel", &Gradient::Stop::GetRel)
;
}
...@@ -25,7 +25,6 @@ using namespace boost::python; ...@@ -25,7 +25,6 @@ using namespace boost::python;
#endif #endif
#include <ost/info/info.hh> #include <ost/info/info.hh>
#include <ost/gfx/prim_list.hh> #include <ost/gfx/prim_list.hh>
#include <ost/gfx/gradient.hh>
#include <ost/gfx/gfx_test_object.hh> #include <ost/gfx/gfx_test_object.hh>
#include <boost/python/suite/indexing/vector_indexing_suite.hpp> #include <boost/python/suite/indexing/vector_indexing_suite.hpp>
...@@ -37,6 +36,7 @@ extern void export_Surface(); ...@@ -37,6 +36,7 @@ extern void export_Surface();
extern void export_primlist(); extern void export_primlist();
extern void export_primitives(); extern void export_primitives();
extern void export_color(); extern void export_color();
extern void export_gradient();
#if OST_IMG_ENABLED #if OST_IMG_ENABLED
extern void export_Map(); extern void export_Map();
#endif #endif
...@@ -54,7 +54,6 @@ using namespace ost::gfx; ...@@ -54,7 +54,6 @@ using namespace ost::gfx;
BOOST_PYTHON_MODULE(_ost_gfx) BOOST_PYTHON_MODULE(_ost_gfx)
{ {
export_color();
export_Scene(); export_Scene();
export_GfxNode(); export_GfxNode();
export_GfxObj(); export_GfxObj();
...@@ -68,6 +67,10 @@ BOOST_PYTHON_MODULE(_ost_gfx) ...@@ -68,6 +67,10 @@ BOOST_PYTHON_MODULE(_ost_gfx)
export_SceneObserver(); export_SceneObserver();
export_ColorOps(); export_ColorOps();
export_GLWinBase(); export_GLWinBase();
export_primitives();
export_primlist();
export_color();
export_gradient();
enum_<RenderMode::Type>("RenderMode") enum_<RenderMode::Type>("RenderMode")
.value("SIMPLE",RenderMode::SIMPLE) .value("SIMPLE",RenderMode::SIMPLE)
...@@ -122,25 +125,6 @@ BOOST_PYTHON_MODULE(_ost_gfx) ...@@ -122,25 +125,6 @@ BOOST_PYTHON_MODULE(_ost_gfx)
class_<GfxTestObj, bases<GfxObj>, boost::noncopyable>("GfxTestObj", init<>()); class_<GfxTestObj, bases<GfxObj>, boost::noncopyable>("GfxTestObj", init<>());
class_<Gradient>("Gradient", init<>())
.def(init<const String&>())
.def("SetColorAt", &Gradient::SetColorAt)
.def("GetColorAt", &Gradient::GetColorAt)
.def("GetStops", &Gradient::GetStops)
.def("GradientToInfo", &Gradient::GradientToInfo)
.def("GradientFromInfo", &Gradient::GradientFromInfo).staticmethod("GradientFromInfo")
;
implicitly_convertible<String, Gradient>();
class_<StopList>("StopList", init<>())
.def(vector_indexing_suite<StopList>())
;
class_<Stop>("Stop", init<>())
.def("GetColor", &Stop::GetColor)
.def("GetRel", &Stop::GetRel)
;
#if OST_SHADER_SUPPORT_ENABLED #if OST_SHADER_SUPPORT_ENABLED
class_<Shader, boost::noncopyable>("Shader", no_init) class_<Shader, boost::noncopyable>("Shader", no_init)
.def("Instance",&Shader::Instance, .def("Instance",&Shader::Instance,
...@@ -151,8 +135,6 @@ BOOST_PYTHON_MODULE(_ost_gfx) ...@@ -151,8 +135,6 @@ BOOST_PYTHON_MODULE(_ost_gfx)
; ;
#endif #endif
export_primitives();
export_primlist();
} }
......
...@@ -76,22 +76,24 @@ Color Gradient::GetColorAt(float t) const ...@@ -76,22 +76,24 @@ Color Gradient::GetColorAt(float t) const
return stops_[c-1].color*(1.0-tt)+stops_[c].color*tt; return stops_[c-1].color*(1.0-tt)+stops_[c].color*tt;
} }
void Gradient::GradientToInfo(info::InfoGroup& group) const{ void Gradient::GradientToInfo(info::InfoGroup& group) const
{
std::ostringstream ss; std::ostringstream ss;
ss << stops_.size() << "\n"; ss << stops_.size() << "\n";
for( std::vector<Stop>::size_type i = 0; i < stops_.size(); i++ ) { for( StopList::size_type i = 0; i < stops_.size(); i++ ) {
ss << stops_[i].t << "\t" << stops_[i].color.Red() << "\t" << stops_[i].color.Green() << "\t" << stops_[i].color.Blue() << "\t" << stops_[i].color.Alpha() << "\n"; ss << stops_[i].t << "\t" << stops_[i].color.Red() << "\t" << stops_[i].color.Green() << "\t" << stops_[i].color.Blue() << "\t" << stops_[i].color.Alpha() << "\n";
} }
group.SetTextData(ss.str()); group.SetTextData(ss.str());
} }
StopList Gradient::GetStops() const{ Gradient::StopList Gradient::GetStops() const{
return stops_; return stops_;
} }
gfx::Gradient Gradient::GradientFromInfo(const info::InfoGroup& group){ Gradient Gradient::GradientFromInfo(const info::InfoGroup& group)
{
std::istringstream ss(group.GetTextData()); std::istringstream ss(group.GetTextData());
Gradient grad; Gradient grad;
...@@ -106,4 +108,5 @@ gfx::Gradient Gradient::GradientFromInfo(const info::InfoGroup& group){ ...@@ -106,4 +108,5 @@ gfx::Gradient Gradient::GradientFromInfo(const info::InfoGroup& group){
return grad; return grad;
} }
}} }}
...@@ -33,33 +33,6 @@ ...@@ -33,33 +33,6 @@
namespace ost { namespace gfx { namespace ost { namespace gfx {
struct Stop {
Stop(): t(0.0) {}
Stop(float tt, const Color& c): t(tt), color(c) {}
float t;
Color color;
Color GetColor(){
return color;
}
float GetRel(){
return t;
}
bool operator==(const Stop& ref) const
{
return t==ref.t && color==ref.color;
}
};
typedef std::vector<Stop> StopList;
/// \brief color gradient /// \brief color gradient
/// ///
/// Gradients map a scalar value in the range of 0 to 1 to a color. The /// Gradients map a scalar value in the range of 0 to 1 to a color. The
...@@ -68,10 +41,39 @@ typedef std::vector<Stop> StopList; ...@@ -68,10 +41,39 @@ typedef std::vector<Stop> StopList;
/// ///
/// \sa \ref gradient.py "Gradient Example" /// \sa \ref gradient.py "Gradient Example"
class DLLEXPORT_OST_GFX Gradient { class DLLEXPORT_OST_GFX Gradient {
public: public:
struct Stop {
Stop(): t(0.0) {}
Stop(float tt, const Color& c): t(tt), color(c) {}
float t;
Color color;
Color GetColor(){
return color;
}
float GetRel(){
return t;
}
bool operator==(const Stop& ref) const
{
return t==ref.t && color==ref.color;
}
};
typedef std::vector<Stop> StopList;
public:
/*!
In python, the gradient can also be initialize with a dictionary, mapping
stops to either float triplets or gfx.Color objects
*/
Gradient(); Gradient();
/// \brief initialize with a pre-define gradient name
Gradient(const String& name); Gradient(const String& name);
/// \brief get color /// \brief get color
......
set(OST_GFX_UNIT_TESTS set(OST_GFX_UNIT_TESTS
tests.cc tests.cc
test_gfx_node.cc test_gfx_node.cc
test_primlist.py test_gfx.py
test_color.py
) )
if (ENABLE_IMG) if (ENABLE_IMG)
list(APPEND OST_GFX_UNIT_TESTS test_map_octree.cc) list(APPEND OST_GFX_UNIT_TESTS test_map_octree.cc)
......
...@@ -4,15 +4,30 @@ if __name__== '__main__': ...@@ -4,15 +4,30 @@ if __name__== '__main__':
sys.path.insert(0,"../../../stage/lib64/openstructure/") sys.path.insert(0,"../../../stage/lib64/openstructure/")
import ost import ost
#import ost.gfx import ost.gfx as gfx
#import ost.geom import ost.geom as geom
class TestColor(unittest.TestCase): def col_delta(c1,c2):
def setUp(self): return geom.Distance(geom.Vec3(c1[0],c1[1],c1[2]),geom.Vec3(c2[0],c2[1],c2[2]))
pass
def test_(self): class TestGfx(unittest.TestCase):
c=ost.gfx.Color(0.5,0.3,0.2) def runTest(self):
self.test_gradient()
self.test_color()
self.test_primlist()
def test_gradient(self):
gs=[gfx.Gradient(),
gfx.Gradient({0.0: [1,0,0], 1.0: gfx.Color(0,1,0)})]
gs[0].SetColorAt(0.0,gfx.Color(1.0,0.0,0.0))
gs[0].SetColorAt(1.0,gfx.Color(0.0,1.0,0.0))
for g in gs:
self.assertAlmostEqual(col_delta(g.GetColorAt(0.0),gfx.Color(1.0,0,0)),0.0)
self.assertAlmostEqual(col_delta(g.GetColorAt(0.5),gfx.Color(0.5,0.5,0)),0.0)
self.assertAlmostEqual(col_delta(g.GetColorAt(1.0),gfx.Color(0,1.0,0)),0.0)
def test_color(self):
c=gfx.Color(0.5,0.3,0.2)
self.assertAlmostEqual(c.r,0.5) self.assertAlmostEqual(c.r,0.5)
self.assertAlmostEqual(c.g,0.3) self.assertAlmostEqual(c.g,0.3)
self.assertAlmostEqual(c.b,0.2) self.assertAlmostEqual(c.b,0.2)
...@@ -30,6 +45,19 @@ class TestColor(unittest.TestCase): ...@@ -30,6 +45,19 @@ class TestColor(unittest.TestCase):
self.assertAlmostEqual(c.red,0.9) self.assertAlmostEqual(c.red,0.9)
self.assertAlmostEqual(c[0],0.9) self.assertAlmostEqual(c[0],0.9)
def test_primlist(self):
pl=gfx.PrimList("foo")
pl.AddPoint([0,0,0])
pl.AddPoint(geom.Vec3(1,2,3),color=gfx.RED)
pl.AddLine([0,0,0],[1,2,3])
pl.AddLine(geom.Vec3(0,0,0),geom.Vec3(1,2,3),color=gfx.BLUE)
pl.AddSphere([0,0,0],radius=2.0)
pl.AddSphere(geom.Vec3(1,2,3),color=gfx.RED,radius=3.0)
pl.AddCyl([0,0,0],[1,2,3],radius=0.5,color=gfx.YELLOW)
pl.AddCyl(geom.Vec3(0,0,0),geom.Vec3(1,2,3),radius1=0.5,radius2=0.1,color1=gfx.BLUE,color2=gfx.GREEN)
pl.AddText("foo",[0,2,3])
pl.AddText("bar",[-2,0,0],color=gfx.WHITE,point_size=8)
if __name__== '__main__': if __name__== '__main__':
unittest.main() unittest.main()
import unittest
if __name__== '__main__':
import sys
sys.path.insert(0,"../../../stage/lib64/openstructure/")
import ost
import ost.gfx
import ost.geom
class TestPrimList(unittest.TestCase):
def setUp(self):
pass
def test_(self):
pl=ost.gfx.PrimList("foo")
pl.AddPoint([0,0,0])
pl.AddPoint(ost.geom.Vec3(1,2,3),color=ost.gfx.RED)
pl.AddLine([0,0,0],[1,2,3])
pl.AddLine(ost.geom.Vec3(0,0,0),ost.geom.Vec3(1,2,3),color=ost.gfx.BLUE)
pl.AddSphere([0,0,0],radius=2.0)
pl.AddSphere(ost.geom.Vec3(1,2,3),color=ost.gfx.RED,radius=3.0)
pl.AddCyl([0,0,0],[1,2,3],radius=0.5,color=ost.gfx.YELLOW)
pl.AddCyl(ost.geom.Vec3(0,0,0),ost.geom.Vec3(1,2,3),radius1=0.5,radius2=0.1,color1=ost.gfx.BLUE,color2=ost.gfx.GREEN)
pl.AddText("foo",[0,2,3])
pl.AddText("bar",[-2,0,0],color=gfx.WHITE,point_size=8)
if __name__== '__main__':
unittest.main()
...@@ -176,7 +176,7 @@ class GradientEdit(QtGui.QWidget): ...@@ -176,7 +176,7 @@ class GradientEdit(QtGui.QWidget):
QtGui.QMessageBox.question(self, "Information", "Please keep in mind, at least two stops are needed for a gradient!") QtGui.QMessageBox.question(self, "Information", "Please keep in mind, at least two stops are needed for a gradient!")
def AddStop(self, pos, color=None): def AddStop(self, pos, color=None):
stop = GradientStop(pos, self.border_offset_, self, color) stop = MyGradientStop(pos, self.border_offset_, self, color)
QtCore.QObject.connect(stop, QtCore.SIGNAL("gradientChanged"), self.UpdateGradient) QtCore.QObject.connect(stop, QtCore.SIGNAL("gradientChanged"), self.UpdateGradient)
QtCore.QObject.connect(stop, QtCore.SIGNAL("colorChanged"), self.UpdateGradient) QtCore.QObject.connect(stop, QtCore.SIGNAL("colorChanged"), self.UpdateGradient)
QtCore.QObject.connect(stop, QtCore.SIGNAL("colorChanged"), self.parent().Update) QtCore.QObject.connect(stop, QtCore.SIGNAL("colorChanged"), self.parent().Update)
...@@ -231,7 +231,7 @@ class GradientEdit(QtGui.QWidget): ...@@ -231,7 +231,7 @@ class GradientEdit(QtGui.QWidget):
self.width_ = event.size().width() self.width_ = event.size().width()
#Gradient Stop #Gradient Stop
class GradientStop(ColorSelectWidget): class MyGradientStop(ColorSelectWidget):
def __init__(self, pos, offset, parent, color=None): def __init__(self, pos, offset, parent, color=None):
#Defaults #Defaults
self.length_ = 20 self.length_ = 20
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment