diff --git a/modules/gfx/pymod/CMakeLists.txt b/modules/gfx/pymod/CMakeLists.txt index 253e8e59989fe3961f893cc435779c846256f0b9..210cce509623565695582e20969f818e8f2e042d 100644 --- a/modules/gfx/pymod/CMakeLists.txt +++ b/modules/gfx/pymod/CMakeLists.txt @@ -11,6 +11,7 @@ set(OST_GFX_PYMOD_SOURCES export_scene_observer.cc export_render_options.cc export_color.cc + export_gradient.cc export_color_ops.cc export_glwin_base.cc ) diff --git a/modules/gfx/pymod/export_gradient.cc b/modules/gfx/pymod/export_gradient.cc new file mode 100644 index 0000000000000000000000000000000000000000..e24cc9cee5fec611fc536b8c0ab5a4e95c3712a1 --- /dev/null +++ b/modules/gfx/pymod/export_gradient.cc @@ -0,0 +1,86 @@ +//------------------------------------------------------------------------------ +// 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) + ; + +} diff --git a/modules/gfx/pymod/wrap_gfx.cc b/modules/gfx/pymod/wrap_gfx.cc index c77b5bc5ce5646080367d8d49105f6666deda768..0198d3a0fb27ae5869ff572b9335e6580737b8e9 100644 --- a/modules/gfx/pymod/wrap_gfx.cc +++ b/modules/gfx/pymod/wrap_gfx.cc @@ -25,7 +25,6 @@ using namespace boost::python; #endif #include <ost/info/info.hh> #include <ost/gfx/prim_list.hh> -#include <ost/gfx/gradient.hh> #include <ost/gfx/gfx_test_object.hh> #include <boost/python/suite/indexing/vector_indexing_suite.hpp> @@ -37,6 +36,7 @@ extern void export_Surface(); extern void export_primlist(); extern void export_primitives(); extern void export_color(); +extern void export_gradient(); #if OST_IMG_ENABLED extern void export_Map(); #endif @@ -54,7 +54,6 @@ using namespace ost::gfx; BOOST_PYTHON_MODULE(_ost_gfx) { - export_color(); export_Scene(); export_GfxNode(); export_GfxObj(); @@ -68,6 +67,10 @@ BOOST_PYTHON_MODULE(_ost_gfx) export_SceneObserver(); export_ColorOps(); export_GLWinBase(); + export_primitives(); + export_primlist(); + export_color(); + export_gradient(); enum_<RenderMode::Type>("RenderMode") .value("SIMPLE",RenderMode::SIMPLE) @@ -122,25 +125,6 @@ BOOST_PYTHON_MODULE(_ost_gfx) 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 class_<Shader, boost::noncopyable>("Shader", no_init) .def("Instance",&Shader::Instance, @@ -151,8 +135,6 @@ BOOST_PYTHON_MODULE(_ost_gfx) ; #endif - export_primitives(); - export_primlist(); } diff --git a/modules/gfx/src/gradient.cc b/modules/gfx/src/gradient.cc index b2cca70fed271194366f8cc4f3795e1beb0f2bea..3414135afb8cb605ba0a3874d3a91af0748f1e89 100644 --- a/modules/gfx/src/gradient.cc +++ b/modules/gfx/src/gradient.cc @@ -76,22 +76,24 @@ Color Gradient::GetColorAt(float t) const 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; 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"; } group.SetTextData(ss.str()); } -StopList Gradient::GetStops() const{ +Gradient::StopList Gradient::GetStops() const{ return stops_; } -gfx::Gradient Gradient::GradientFromInfo(const info::InfoGroup& group){ +Gradient Gradient::GradientFromInfo(const info::InfoGroup& group) +{ std::istringstream ss(group.GetTextData()); Gradient grad; @@ -106,4 +108,5 @@ gfx::Gradient Gradient::GradientFromInfo(const info::InfoGroup& group){ return grad; } + }} diff --git a/modules/gfx/src/gradient.hh b/modules/gfx/src/gradient.hh index bd142489cde82ebf581d386ccd57b28b313551af..0b220faf060cc656cf9a52dbd3bccee98f2d8821 100644 --- a/modules/gfx/src/gradient.hh +++ b/modules/gfx/src/gradient.hh @@ -33,33 +33,6 @@ 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 /// /// 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; /// /// \sa \ref gradient.py "Gradient Example" class DLLEXPORT_OST_GFX Gradient { - 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(); + /// \brief initialize with a pre-define gradient name Gradient(const String& name); /// \brief get color diff --git a/modules/gfx/tests/CMakeLists.txt b/modules/gfx/tests/CMakeLists.txt index adf0a676991f2bbb7d31c06e8a95c6cf4b8a6683..b5bb03b71e8eb2dbf90fc8886f1cf34157e52670 100644 --- a/modules/gfx/tests/CMakeLists.txt +++ b/modules/gfx/tests/CMakeLists.txt @@ -1,8 +1,7 @@ set(OST_GFX_UNIT_TESTS tests.cc test_gfx_node.cc - test_primlist.py - test_color.py + test_gfx.py ) if (ENABLE_IMG) list(APPEND OST_GFX_UNIT_TESTS test_map_octree.cc) diff --git a/modules/gfx/tests/test_color.py b/modules/gfx/tests/test_color.py deleted file mode 100644 index 58a1afa0494cbfe2ece14f5e4811fd8945e56f01..0000000000000000000000000000000000000000 --- a/modules/gfx/tests/test_color.py +++ /dev/null @@ -1,35 +0,0 @@ -import unittest -if __name__== '__main__': - import sys - sys.path.insert(0,"../../../stage/lib64/openstructure/") - -import ost -#import ost.gfx -#import ost.geom - -class TestColor(unittest.TestCase): - def setUp(self): - pass - - def test_(self): - c=ost.gfx.Color(0.5,0.3,0.2) - self.assertAlmostEqual(c.r,0.5) - self.assertAlmostEqual(c.g,0.3) - self.assertAlmostEqual(c.b,0.2) - self.assertAlmostEqual(c.a,1.0) - self.assertAlmostEqual(c.red,0.5) - self.assertAlmostEqual(c.green,0.3) - self.assertAlmostEqual(c.blue,0.2) - self.assertAlmostEqual(c.alpha,1.0) - self.assertAlmostEqual(c[0],0.5) - self.assertAlmostEqual(c[1],0.3) - self.assertAlmostEqual(c[2],0.2) - self.assertAlmostEqual(c[3],1.0) - c.r=0.9 - self.assertAlmostEqual(c.r,0.9) - self.assertAlmostEqual(c.red,0.9) - self.assertAlmostEqual(c[0],0.9) - -if __name__== '__main__': - unittest.main() - diff --git a/modules/gfx/tests/test_gfx.py b/modules/gfx/tests/test_gfx.py new file mode 100644 index 0000000000000000000000000000000000000000..ff0d32d9ad7415c01f54b92683dffa6bad17ad41 --- /dev/null +++ b/modules/gfx/tests/test_gfx.py @@ -0,0 +1,63 @@ +import unittest +if __name__== '__main__': + import sys + sys.path.insert(0,"../../../stage/lib64/openstructure/") + +import ost +import ost.gfx as gfx +import ost.geom as geom + +def col_delta(c1,c2): + return geom.Distance(geom.Vec3(c1[0],c1[1],c1[2]),geom.Vec3(c2[0],c2[1],c2[2])) + +class TestGfx(unittest.TestCase): + 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.g,0.3) + self.assertAlmostEqual(c.b,0.2) + self.assertAlmostEqual(c.a,1.0) + self.assertAlmostEqual(c.red,0.5) + self.assertAlmostEqual(c.green,0.3) + self.assertAlmostEqual(c.blue,0.2) + self.assertAlmostEqual(c.alpha,1.0) + self.assertAlmostEqual(c[0],0.5) + self.assertAlmostEqual(c[1],0.3) + self.assertAlmostEqual(c[2],0.2) + self.assertAlmostEqual(c[3],1.0) + c.r=0.9 + self.assertAlmostEqual(c.r,0.9) + self.assertAlmostEqual(c.red,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__': + unittest.main() + diff --git a/modules/gfx/tests/test_primlist.py b/modules/gfx/tests/test_primlist.py deleted file mode 100644 index 55660f9554a958c8fbf1ee09cf8fb5a2e868f462..0000000000000000000000000000000000000000 --- a/modules/gfx/tests/test_primlist.py +++ /dev/null @@ -1,29 +0,0 @@ -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() - diff --git a/modules/gui/pymod/scene/gradient_editor_widget.py b/modules/gui/pymod/scene/gradient_editor_widget.py index 3c5b8629433707548bab7453d7592df57a1e6aab..34c11a24ac0d70b2a2026308365ad8f351a64005 100644 --- a/modules/gui/pymod/scene/gradient_editor_widget.py +++ b/modules/gui/pymod/scene/gradient_editor_widget.py @@ -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!") 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("colorChanged"), self.UpdateGradient) QtCore.QObject.connect(stop, QtCore.SIGNAL("colorChanged"), self.parent().Update) @@ -231,7 +231,7 @@ class GradientEdit(QtGui.QWidget): self.width_ = event.size().width() #Gradient Stop -class GradientStop(ColorSelectWidget): +class MyGradientStop(ColorSelectWidget): def __init__(self, pos, offset, parent, color=None): #Defaults self.length_ = 20