From dce4061ee68767692435c4b5d1f4bc5c482db4cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20Tr=C3=B6ger?= Date: Fri, 1 Nov 2013 10:29:47 +0100 Subject: [PATCH] treat multiple assignment operator warning on msvc --- .../App/opendcm/core/clustergraph.hpp | 89 +++++--- .../Assembly/App/opendcm/core/equations.hpp | 15 +- src/Mod/Assembly/App/opendcm/core/object.hpp | 67 ++++-- .../App/opendcm/module3d/alignment.hpp | 2 +- .../App/opendcm/module3d/coincident.hpp | 4 +- .../Assembly/App/opendcm/module3d/module.hpp | 6 + .../App/opendcm/moduleShape3d/fixed.hpp | 1 - .../App/opendcm/moduleShape3d/generator.hpp | 106 +++++---- .../App/opendcm/moduleShape3d/module.hpp | 207 +++++++++++++++--- .../App/opendcm/moduleState/module.hpp | 1 - 10 files changed, 364 insertions(+), 134 deletions(-) diff --git a/src/Mod/Assembly/App/opendcm/core/clustergraph.hpp b/src/Mod/Assembly/App/opendcm/core/clustergraph.hpp index ed653a05c..44b6ac6bf 100644 --- a/src/Mod/Assembly/App/opendcm/core/clustergraph.hpp +++ b/src/Mod/Assembly/App/opendcm/core/clustergraph.hpp @@ -173,6 +173,11 @@ struct IDgen { }; }; +/** + * @brief Exception thrown from the graph at any occuring error + **/ +struct cluster_error : virtual boost::exception {}; + /** * @brief Pointer type to share a common ID generator @ref IDgen **/ @@ -467,7 +472,8 @@ public: * @param g the parent cluster graph **/ ClusterGraph(boost::shared_ptr g) : m_parent(g), m_id(new details::IDgen) { - if(g) m_id = g->m_id; + if(g) + m_id = g->m_id; }; ~ClusterGraph() {}; @@ -741,7 +747,7 @@ public: return (*it.first).first; } - return LocalVertex(); + throw details::cluster_error() << boost::errinfo_errno(12) << error_message("Cluster is not part of this graph"); }; /** @@ -785,7 +791,7 @@ public: typename ClusterMap::iterator it = m_clusters.find(v); if(it == m_clusters.end()) - return; //TODO:throw + throw details::cluster_error() << boost::errinfo_errno(11) << error_message("Cluster is not part of this graph"); std::pair > res = *it; @@ -908,9 +914,11 @@ public: boost::tie(e, done) = boost::edge(source, target, *this); //if done=true the edge alredy existed - if(!done) boost::tie(e, done) = boost::add_edge(source, target, *this); + if(!done) + boost::tie(e, done) = boost::add_edge(source, target, *this); - if(!done) return fusion::make_vector(LocalEdge(), GlobalEdge(), false); + if(!done) + return fusion::make_vector(LocalEdge(), GlobalEdge(), false); //init the bundle corecctly for new edge GlobalEdge global = { fusion::at_c<0> ((*this) [source]), fusion::at_c<0> ((*this) [target]), m_id->generate() }; @@ -948,7 +956,8 @@ public: boost::tie(v2, d2) = getContainingVertex(target); //if one vertex is not accessible from here this function fails - if(!(d1 && d2)) return fusion::make_vector(LocalEdge(), GlobalEdge(), false, false); + if(!(d1 && d2)) + return fusion::make_vector(LocalEdge(), GlobalEdge(), false, false); //if both vertices are in a subcluster this one must do the job as we cant access the local edge from here if(v1 == v2 && isCluster(v1)) { @@ -960,9 +969,11 @@ public: //check if we already have that Local edge boost::tie(e, d3) = boost::edge(v1, v2, *this); - if(!d3) boost::tie(e, d3) = boost::add_edge(v1, v2, *this); + if(!d3) + boost::tie(e, d3) = boost::add_edge(v1, v2, *this); - if(!d3) return fusion::make_vector(LocalEdge(), GlobalEdge(), false, false); + if(!d3) + return fusion::make_vector(LocalEdge(), GlobalEdge(), false, false); //init the bundle corectly for new edge GlobalEdge global = { source, target, m_id->generate() }; @@ -1111,11 +1122,14 @@ private: bool operator()(edge_bundle_single& e) { bool res; + //this predicate can be used to compare the edge itself or the vertives it connects. See + //if we are a relevant edge if(isEdge) res = (edge == fusion::at_c<1> (e)); else res = (vert == fusion::at_c<1> (e).source) || (vert == fusion::at_c<1> (e).target); + //we are a hit, invoke the functor. if(res || vert < 0) func(fusion::at_c<1> (e)); @@ -1133,8 +1147,11 @@ private: std::pair res = getContainingVertex(v); + //we don't throw, as this function gets invoked recursivly and it may happen that the + //vertex to remove is only in the top layers, not the button ones if(!res.second) - return; //TODO:throw + return; + //iterate over every edge that connects to the global vertex or the cluster in which it is in std::vector re; //remove edges @@ -1180,6 +1197,9 @@ public: **/ template void removeVertex(LocalVertex id, Functor& f) { + //it is important to delete the global vertex, not the only local one as it's possible that + //we are in a subcluster and there are connections to the global vertex in the parent. They + //need to be deleted too. removeVertex(getGlobalVertex(id), f); }; //no default template arguments for template functions allowed before c++0x, so a little workaround @@ -1271,7 +1291,8 @@ protected: typename boost::enable_if < boost::is_same::type>, result_type >::type operator()(bundle& p) { - if(Type::value) fusion::for_each(fusion::at_c<2> (p), details::clear_ptr()); + if(Type::value) + fusion::for_each(fusion::at_c<2> (p), details::clear_ptr()); return object_extractor()(p); } @@ -1287,7 +1308,8 @@ protected: for(edge_single_iterator it = ebsv.begin(); it != ebsv.end(); it++) { if(global_extractor()(*it) == m_key) { - if(Type::value) fusion::for_each(fusion::at_c<0> (*it), details::clear_ptr()); + if(Type::value) + fusion::for_each(fusion::at_c<0> (*it), details::clear_ptr()); e = it; break; @@ -1301,7 +1323,8 @@ protected: template typename boost::enable_if < mpl::and_ < boost::is_same::type>, boost::is_same > , result_type >::type operator()(bundle& p) { - if(Type::value) fusion::for_each(fusion::at_c<0> (fusion::at_c<1> (p).front()), details::clear_ptr()); + if(Type::value) + fusion::for_each(fusion::at_c<0> (fusion::at_c<1> (p).front()), details::clear_ptr()); return object_extractor()(fusion::at_c<1> (p).front()); } @@ -1637,7 +1660,8 @@ public: bool done; boost::tie(e, done) = boost::edge(target, Cluster, *this); - if(!done) boost::tie(e, done) = boost::add_edge(target, Cluster, *this); + if(!done) + boost::tie(e, done) = boost::add_edge(target, Cluster, *this); //if(!done) TODO: throw @@ -1680,7 +1704,8 @@ public: bool done; boost::tie(e, done) = boost::edge(nv, res.first, *cg); - if(!done) boost::tie(e, done) = boost::add_edge(nv, res.first, *cg); + if(!done) + boost::tie(e, done) = boost::add_edge(nv, res.first, *cg); //if(!done) TODO: throw @@ -1747,8 +1772,10 @@ public: GlobalVertex target; //a bit cumbersome to allow cluster moving - if(parent()->getContainingVertex(global.source).first == nv) target = global.target; - else if(parent()->getContainingVertex(global.target).first == nv) target = global.source; + if(parent()->getContainingVertex(global.source).first == nv) + target = global.target; + else if(parent()->getContainingVertex(global.target).first == nv) + target = global.source; else { i++; continue; @@ -1761,7 +1788,8 @@ public: bool done; boost::tie(e, done) = boost::edge(nv, res.first, *parent()); - if(!done) boost::tie(e, done) = boost::add_edge(nv, res.first, *parent()); + if(!done) + boost::tie(e, done) = boost::add_edge(nv, res.first, *parent()); //if(!done) TODO: throw @@ -1771,14 +1799,16 @@ public: } //see if we should destroy this edge (no global edges remain in local one) - if(vec.empty()) edge_vec.push_back(*it.first); + if(vec.empty()) + edge_vec.push_back(*it.first); } //create a edge between new vertex and this cluster and add all global edges from within this cluster it = boost::out_edges(v, *this); LocalEdge e; - if(it.first != it.second) e = boost::add_edge(nv, this_v, *parent()).first; + if(it.first != it.second) + e = boost::add_edge(nv, this_v, *parent()).first; for(; it.first != it.second; it.first++) { std::vector& ep = fusion::at_c<1> ((*this) [*it.first]); @@ -1834,7 +1864,8 @@ protected: for(cluster_iterator it = m_clusters.begin(); it != m_clusters.end(); it++) { std::pair res = ((*it).second)->getContainingVertex(id); - if(res.second) return std::make_pair((*it).first, true); + if(res.second) + return std::make_pair((*it).first, true); } } @@ -1850,11 +1881,13 @@ protected: bool done; boost::tie(v, done) = getContainingVertex(id); - if(!done) return fusion::make_vector(LocalVertex(), boost::shared_ptr(), false); + if(!done) + return fusion::make_vector(LocalVertex(), boost::shared_ptr(), false); if(isCluster(v) && (getGlobalVertex(v) != id)) return m_clusters[v]->getContainingVertexGraph(id); - else return fusion::make_vector(v, sp_base::shared_from_this(), true); + else + return fusion::make_vector(v, sp_base::shared_from_this(), true); }; /* Searches the global edge in all local edges of this graph, and returns the local @@ -1868,7 +1901,8 @@ protected: boost::tie(v1, d1) = getContainingVertex(id.source, true); boost::tie(v2, d2) = getContainingVertex(id.target, true); - if(!((d1 && d2) && (v1 != v2))) return std::make_pair(LocalEdge(), false); + if(!((d1 && d2) && (v1 != v2))) + return std::make_pair(LocalEdge(), false); return boost::edge(v1, v2, *this); }; @@ -1883,9 +1917,11 @@ protected: boost::tie(v1, d1) = getContainingVertex(id.source, true); boost::tie(v2, d2) = getContainingVertex(id.target, true); - if(!(d1 && d2)) return fusion::make_vector(LocalEdge(), (ClusterGraph*) NULL, false); + if(!(d1 && d2)) + return fusion::make_vector(LocalEdge(), (ClusterGraph*) NULL, false); - if(v1 == v2) return m_clusters[v1]->getContainingEdgeGraph(id); + if(v1 == v2) + return m_clusters[v1]->getContainingEdgeGraph(id); return fusion::make_vector(boost::edge(v1, v2, *this).first, this, true); }; @@ -1935,7 +1971,8 @@ protected: //TODO:Throw } - if((v1 == v2) && isCluster(v1)) return m_clusters[v1]->apply_to_bundle(k, f); + if((v1 == v2) && isCluster(v1)) + return m_clusters[v1]->apply_to_bundle(k, f); else { LocalEdge e; bool done; diff --git a/src/Mod/Assembly/App/opendcm/core/equations.hpp b/src/Mod/Assembly/App/opendcm/core/equations.hpp index f04218e11..bc34e6d45 100644 --- a/src/Mod/Assembly/App/opendcm/core/equations.hpp +++ b/src/Mod/Assembly/App/opendcm/core/equations.hpp @@ -232,8 +232,10 @@ struct Equation : public EQ { typename boost::enable_if, Derived&>::type operator=(const T& val) { return operator()(val); }; - //assign complete equation - Derived& operator=(const Derived& eq) { + //assign complete equation (we need to override the operator= in the derived class anyway as it + //is automaticly created by the compiler, so we use a different name here to avoid duplicate + //operator= warning on msvc) + Derived& assign(const Derived& eq) { //we only copy the values which were set and are therefore valid option_copy oc(values); @@ -303,7 +305,7 @@ struct print_pair { template typename boost::enable_if, std::basic_ostream&>::type -operator << (std::basic_ostream & stream, const Eq& equation) +operator << (std::basic_ostream& stream, const Eq& equation) { print_pair pr; pr.stream = &stream; @@ -323,7 +325,7 @@ struct Distance : public Equation //override needed ass assignmend operator is always created by the compiler //and we need to ensure that our custom one is used Distance& operator=(const Distance& d) { - return Equation::operator=(d); + return Equation::assign(d); }; void setDefault() { @@ -397,7 +399,7 @@ struct Orientation : public Equation { //override needed ass assignmend operator is always created by the compiler //and we need to ensure that our custom one is used Orientation& operator=(const Orientation& d) { - return Equation::operator=(d); + return Equation::assign(d); }; void setDefault() { @@ -455,6 +457,7 @@ struct Orientation : public Equation { struct Angle : public Equation, true> { using Equation::operator=; + Angle() : Equation() { setDefault(); }; @@ -462,7 +465,7 @@ struct Angle : public Equation, true> //override needed ass assignmend operator is always created by the compiler //and we need to ensure that our custom one is used Angle& operator=(const Angle& d) { - return Equation::operator=(d); + return Equation::assign(d); }; void setDefault() { diff --git a/src/Mod/Assembly/App/opendcm/core/object.hpp b/src/Mod/Assembly/App/opendcm/core/object.hpp index 29c70663a..99ac0ac13 100644 --- a/src/Mod/Assembly/App/opendcm/core/object.hpp +++ b/src/Mod/Assembly/App/opendcm/core/object.hpp @@ -21,7 +21,7 @@ #define GCM_OBJECT_H #include -#include +#include #include #include @@ -44,7 +44,6 @@ #include #include -#include #include "property.hpp" @@ -54,7 +53,7 @@ namespace fusion = boost::fusion; /* Preprocessor implementation of emit signal. As we need many overloads with diffrent number of * templated parameters we use boost preprocessor to do the hard repetive work. The definition and - * implementation are definded first as they need to be known before usage + * implementation are definded first as they need to be known before usage * */ #define EMIT_ARGUMENTS(z, n, data) \ BOOST_PP_CAT(data, n) @@ -78,12 +77,14 @@ namespace fusion = boost::fusion; BOOST_PP_ENUM_BINARY_PARAMS(n, Arg, const& arg) \ ) \ { \ - typedef typename mpl::find::type iterator; \ - typedef typename mpl::distance::type, iterator>::type distance; \ - typedef typename fusion::result_of::value_at::type list_type; \ - list_type& list = fusion::at(m_signals); \ - for (typename list_type::iterator it=list.begin(); it != list.end(); it++) \ - (*it)(BOOST_PP_ENUM(n, EMIT_ARGUMENTS, arg)); \ + if(m_emit_signals) {\ + typedef typename mpl::find::type iterator; \ + typedef typename mpl::distance::type, iterator>::type distance; \ + typedef typename fusion::result_of::value_at::type map_type; \ + map_type& map = fusion::at(m_signals); \ + for (typename map_type::iterator it=map.begin(); it != map.end(); it++) \ + (it->second)(BOOST_PP_ENUM(n, EMIT_ARGUMENTS, arg)); \ + }\ }; namespace dcm { @@ -98,10 +99,12 @@ namespace dcm { //few standart signal names struct remove {}; -typedef boost::any Connection; +typedef int Connection; template struct SignalOwner { + + SignalOwner(); /** * @brief Connects a slot to a specified signal. @@ -130,9 +133,21 @@ struct SignalOwner { template void disconnectSignal(Connection c); + + /** + * @brief Enable or disable signal emittion + * + * If you want to supress all signals emitted by a object you can do this by calling this function. + * All calls to emitSignal() will be blocked until signals aer reenabled by using this function with + * onoff = true. Note that signals are not queued, if emitting is disabled all signals are lost. + * + * @param onoff bool value if signals shall be emitted or if they are disabled + */ + void enableSignals(bool onoff); + //with no vararg templates before c++11 we need preprocessor to create the overloads of emit signal we need BOOST_PP_REPEAT(5, EMIT_CALL_DEF, ~) - + protected: /*signal handling * extract all signal types to allow index search (inex search on signal functions would fail as same @@ -144,17 +159,19 @@ protected: typedef typename mpl::fold < SigMap, mpl::vector<>, mpl::push_back > >::type sig_functions; typedef typename mpl::fold < sig_functions, mpl::vector<>, - mpl::push_back > >::type sig_vectors; + mpl::push_back > >::type sig_vectors; typedef typename fusion::result_of::as_vector::type Signals; Signals m_signals; + bool m_emit_signals; + int m_signal_count; }; /** * @brief Base class for all object types * * This class add's property and signal capabilitys to all deriving classes. For properties it is tigthly - * integrated with the system class: It searches systems property list for the derived class as specified by + * integrated with the system class: It searches systems property map for the derived class as specified by * the second template parameter and makes it accessible via appopriate functions. Signals are speciefied by a * mpl::map with signal name type as key and a boost::function as values. * @@ -164,7 +181,7 @@ protected: **/ template struct Object : public PropertyOwner::type>, - public SignalOwner, + public SignalOwner, boost::enable_shared_from_this { Object() {}; @@ -204,15 +221,19 @@ boost::shared_ptr Object::clone(Sys& newSys) return np; }; +template +SignalOwner::SignalOwner() : m_emit_signals(true), m_signal_count(0) {}; + template template Connection SignalOwner::connectSignal(typename mpl::at::type function) { typedef typename mpl::find::type iterator; typedef typename mpl::distance::type, iterator>::type distance; - typedef typename fusion::result_of::value_at::type list_type; - list_type& list = fusion::at(m_signals); - return list.insert(list.begin(), function); + typedef typename fusion::result_of::value_at::type map_type; + map_type& map = fusion::at(m_signals); + map[++m_signal_count] = function; + return m_signal_count; }; template @@ -222,9 +243,15 @@ void SignalOwner::disconnectSignal(Connection c) typedef typename mpl::find::type iterator; typedef typename mpl::distance::type, iterator>::type distance; - typedef typename fusion::result_of::value_at::type list_type; - list_type& list = fusion::at(m_signals); - list.erase(boost::any_cast(c)); + typedef typename fusion::result_of::value_at::type map_type; + map_type& map = fusion::at(m_signals); + map.erase(c); +}; + +template +void SignalOwner::enableSignals(bool onoff) +{ + m_emit_signals = onoff; }; BOOST_PP_REPEAT(5, EMIT_CALL_DEC, ~) diff --git a/src/Mod/Assembly/App/opendcm/module3d/alignment.hpp b/src/Mod/Assembly/App/opendcm/module3d/alignment.hpp index df4764556..ce36d7728 100644 --- a/src/Mod/Assembly/App/opendcm/module3d/alignment.hpp +++ b/src/Mod/Assembly/App/opendcm/module3d/alignment.hpp @@ -38,7 +38,7 @@ struct al_orientation : public Equation { }; al_orientation& operator=(const al_orientation& d) { - return Equation::operator=(d); + return Equation::assign(d); }; void setDefault() { diff --git a/src/Mod/Assembly/App/opendcm/module3d/coincident.hpp b/src/Mod/Assembly/App/opendcm/module3d/coincident.hpp index 86fb69016..3ddc356c7 100644 --- a/src/Mod/Assembly/App/opendcm/module3d/coincident.hpp +++ b/src/Mod/Assembly/App/opendcm/module3d/coincident.hpp @@ -37,7 +37,7 @@ struct ci_orientation : public Equation { }; ci_orientation& operator=(const ci_orientation& d) { - return Equation::operator=(d); + return Equation::assign(d); }; void setDefault() { @@ -193,7 +193,7 @@ struct ci_distance : public Equation struct Module3D { @@ -773,6 +774,9 @@ void Module3D::type::inheriter_id::removeGeometry3D(Identifie if(hasGeometry3D(id)) inheriter_base::removeGeometry3D(getGeometry3D(id)); + else + throw module3d_error() << boost::errinfo_errno(410) << error_message("no geometry with this ID in this system"); + }; template @@ -792,6 +796,8 @@ void Module3D::type::inheriter_id::removeConstraint3D(Identif if(hasConstraint3D(id)) removeConstraint3D(getConstraint3D(id)); + else + throw module3d_error() << boost::errinfo_errno(411) << error_message("no constraint with this ID in this system"); }; diff --git a/src/Mod/Assembly/App/opendcm/moduleShape3d/fixed.hpp b/src/Mod/Assembly/App/opendcm/moduleShape3d/fixed.hpp index acff26292..3b4252124 100644 --- a/src/Mod/Assembly/App/opendcm/moduleShape3d/fixed.hpp +++ b/src/Mod/Assembly/App/opendcm/moduleShape3d/fixed.hpp @@ -33,7 +33,6 @@ namespace details { //this fixed equation struct Fixed : public Equation { - using Equation::operator=; using Equation::options; Fixed() : Equation() { setDefault(); diff --git a/src/Mod/Assembly/App/opendcm/moduleShape3d/generator.hpp b/src/Mod/Assembly/App/opendcm/moduleShape3d/generator.hpp index d2977b982..38eb3b8d3 100644 --- a/src/Mod/Assembly/App/opendcm/moduleShape3d/generator.hpp +++ b/src/Mod/Assembly/App/opendcm/moduleShape3d/generator.hpp @@ -43,6 +43,10 @@ struct ShapeGeneratorBase { typedef typename module3d::Constraint3D Constraint3D; typedef typename system_traits::template getModule::type moduleShape3d; typedef typename moduleShape3d::Shape3D Shape3D; + + typedef typename Shape3D::ShapeVector ShapeVector; + typedef typename Shape3D::GeometryVector GeometryVector; + typedef typename Shape3D::ConstraintVector ConstraintVector; typedef typename moduleShape3d::shape_purpose_prop shape_purpose_prop; typedef typename moduleShape3d::shape_geometry_prop shape_geometry_prop; @@ -50,17 +54,17 @@ struct ShapeGeneratorBase { Sys* m_system; boost::shared_ptr m_shape; - std::vector >* m_geometries; - std::vector >* m_shapes; - std::vector >* m_constraints; + GeometryVector* m_geometries; + ShapeVector* m_shapes; + ConstraintVector* m_constraints; ShapeGeneratorBase(Sys* system) : m_system(system) {}; virtual ~ShapeGeneratorBase() {}; void set(boost::shared_ptr shape, - std::vector >* geometries, - std::vector >* shapes, - std::vector >* constraints) { + GeometryVector* geometries, + ShapeVector* shapes, + ConstraintVector* constraints) { m_shape = shape; m_geometries = geometries; @@ -76,6 +80,17 @@ struct ShapeGeneratorBase { virtual boost::shared_ptr getOrCreateG3d(int type) = 0; //get hlgeometry3d for optional types virtual boost::shared_ptr getOrCreateHLG3d(int type) = 0; + + //append needs to be on this base class as the shape appends are protected + void append(boost::shared_ptr g) { + m_shape->append(g); + }; + void append(boost::shared_ptr g) { + m_shape->append(g); + }; + void append(boost::shared_ptr g) { + m_shape->append(g); + }; }; } //details @@ -117,7 +132,7 @@ struct segment3D { typedef typename Sys::Kernel Kernel; using typename base::Geometry3D; using typename base::Constraint3D; - using typename base::Shape3D; + using typename base::Shape3D; type(Sys* system) : details::ShapeGeneratorBase(system) {}; @@ -141,17 +156,17 @@ struct segment3D { //link the line geometrie to our shape boost::shared_ptr g1 = base::m_system->createGeometry3D(); - base::m_geometries->push_back(g1); + base::append(g1); g1->template linkTo(base::m_shape,0); g1->template setProperty(line); - g1->template connectSignal(boost::bind(&base::Shape3D::recalc, base::m_shape, _1)); + g1->template connectSignal(boost::bind(&base::Shape3D::recalc, base::m_shape, _1)); //we have a segment, lets link the two points to it boost::shared_ptr g2 = base::m_system->createGeometry3D(); - base::m_geometries->push_back(g2); + base::append(g2); g2->template setProperty(startpoint); boost::shared_ptr g3 = base::m_system->createGeometry3D(); - base::m_geometries->push_back(g3); + base::append(g3); g3->template setProperty(endpoint); //link the points to our new segment @@ -162,49 +177,52 @@ struct segment3D { boost::shared_ptr c1 = base::m_system->createConstraint3D(g1,g2, details::fixed); boost::shared_ptr c2 = base::m_system->createConstraint3D(g1,g3, details::fixed); c1->disable(); //required by fixed constraint + base::append(c1); c2->disable(); //requiered by fixed constraint + base::append(c2); } - else - if(base::m_geometries->size() == 2) { - //we have two points, lets get them - boost::shared_ptr g1 = base::m_geometries->operator[](0); - boost::shared_ptr g2 = base::m_geometries->operator[](1); + else if(base::m_geometries->size() == 2) { + //we have two points, lets get them + boost::shared_ptr g1 = fusion::at_c<0>(base::m_geometries->operator[](0)); + boost::shared_ptr g2 = fusion::at_c<0>(base::m_geometries->operator[](1)); - //possibility 1: two points. we add a segment line an link the point in - if(g1->getGeometryType() == tag::weight::point::value || g2->getGeometryType() == tag::weight::point::value) { + //possibility 1: two points. we add a segment line an link the point in + if(g1->getGeometryType() == tag::weight::point::value || g2->getGeometryType() == tag::weight::point::value) { - g1->template setProperty(startpoint); - g2->template setProperty(endpoint); + g1->template setProperty(startpoint); + g2->template setProperty(endpoint); - //construct our segment value - typename Kernel::Vector val(6); - val.head(3) = g1->getValue(); - val.tail(3) = g2->getValue(); + //construct our segment value + typename Kernel::Vector val(6); + val.head(3) = g1->getValue(); + val.tail(3) = g2->getValue(); - //the shape is a segment - base::m_shape->template setValue(val); + //the shape is a segment + base::m_shape->template setValue(val); - //and create a segment geometry we use as line - boost::shared_ptr g3 = base::m_system->createGeometry3D(); - base::m_geometries->push_back(g3); - g3->template linkTo(base::m_shape,0); - g3->template setProperty(line); - g3->template connectSignal(boost::bind(&base::Shape3D::recalc, base::m_shape, _1)); + //and create a segment geometry we use as line + boost::shared_ptr g3 = base::m_system->createGeometry3D(); + base::append(g3); + g3->template linkTo(base::m_shape,0); + g3->template setProperty(line); + g3->template connectSignal(boost::bind(&base::Shape3D::recalc, base::m_shape, _1)); - //link the points to our new segment - g1->template linkTo(base::m_shape, 0); - g2->template linkTo(base::m_shape, 3); + //link the points to our new segment + g1->template linkTo(base::m_shape, 0); + g2->template linkTo(base::m_shape, 3); - //add the fix constraints to show our relation - boost::shared_ptr c1 = base::m_system->createConstraint3D(g1,g3, details::fixed); - boost::shared_ptr c2 = base::m_system->createConstraint3D(g1,g3, details::fixed); - c1->disable(); //required by fixed constraint - c2->disable(); //requiered by fixed constraint + //add the fix constraints to show our relation + boost::shared_ptr c1 = base::m_system->createConstraint3D(g1,g3, details::fixed); + boost::shared_ptr c2 = base::m_system->createConstraint3D(g1,g3, details::fixed); + c1->disable(); //required by fixed constraint + base::append(c1); + c2->disable(); //requiered by fixed constraint + base::append(c2); - } - else - throw creation_error() << boost::errinfo_errno(501) << error_message("Wrong geometries for segment construction"); - }; + } + else + throw creation_error() << boost::errinfo_errno(501) << error_message("Wrong geometries for segment construction"); + }; }; //get geometry3d for optional types (e.g. midpoints) virtual boost::shared_ptr::Geometry3D> getOrCreateG3d(int type) { diff --git a/src/Mod/Assembly/App/opendcm/moduleShape3d/module.hpp b/src/Mod/Assembly/App/opendcm/moduleShape3d/module.hpp index 4517144e1..97c228da4 100644 --- a/src/Mod/Assembly/App/opendcm/moduleShape3d/module.hpp +++ b/src/Mod/Assembly/App/opendcm/moduleShape3d/module.hpp @@ -191,7 +191,9 @@ struct ModuleShape3D { struct inheriter_base; struct Shape3D; - typedef mpl::map0<> ShapeSig; + typedef mpl::map2< + mpl::pair) > >, + mpl::pair) > > > ShapeSig; template struct Shape3D_base : public details::Geometry, public Object { @@ -235,34 +237,73 @@ struct ModuleShape3D { virtual boost::shared_ptr clone(Sys& newSys); - /*shape access functions*/ - typedef typename std::vector >::const_iterator geometry3d_iterator; - typedef typename std::vector >::const_iterator shape3d_iterator; - typedef typename std::vector >::const_iterator constraint3d_iterator; + /*shape access functions and extractors to mimic vector<> iterators*/ + typedef std::vector, Connection> > GeometryVector; + typedef std::vector, Connection> > ShapeVector; + typedef std::vector, Connection> > ConstraintVector; + + struct geom_extractor { + typedef boost::shared_ptr result_type; + template + result_type operator()(T& pair) const { + return fusion::at_c<0>(pair); + }; + }; + struct shape_extractor { + typedef boost::shared_ptr result_type; + template + result_type operator()(T& pair) const { + return fusion::at_c<0>(pair); + }; + }; + struct cons_extractor { + typedef boost::shared_ptr result_type; + template + result_type operator()(T& pair) const { + return fusion::at_c<0>(pair); + }; + }; + typedef boost::transform_iterator geometry3d_iterator; + typedef boost::transform_iterator shape3d_iterator; + typedef boost::transform_iterator constraint3d_iterator; + shape3d_iterator beginShape3D() { - return m_shapes.begin(); + return boost::make_transform_iterator(m_shapes.begin(), shape_extractor()); }; shape3d_iterator endShape3D() { - return m_shapes.end(); + return boost::make_transform_iterator(m_shapes.end(), shape_extractor()); }; geometry3d_iterator beginGeometry3D() { - return m_geometries.begin(); + return boost::make_transform_iterator(m_geometries.begin(), geom_extractor()); }; geometry3d_iterator endGeometry3D() { - return m_geometries.end(); + return boost::make_transform_iterator(m_geometries.end(), geom_extractor()); }; constraint3d_iterator beginConstraint3D() { - return m_constraints.begin(); + return boost::make_transform_iterator(m_constraints.begin(), cons_extractor()); }; - constraint3d_iterator endConstraint3D() { - return m_constraints.end(); + constraint3d_iterator endConstraint3D() { + return boost::make_transform_iterator(m_constraints.end(), cons_extractor()); }; boost::shared_ptr geometry(purpose f); template boost::shared_ptr subshape(); + //callbacks void recalc(boost::shared_ptr g); + void remove(boost::shared_ptr g); + void remove(boost::shared_ptr g); + void remove(boost::shared_ptr g); + + private: + + //we store all geometries, shapes and constraint which belong to this shape. + //Furthermore we store the remove connections, as we need to disconnect them later + GeometryVector m_geometries; + ShapeVector m_shapes; + ConstraintVector m_constraints; + protected: #ifdef USE_LOGGING @@ -301,11 +342,7 @@ struct ModuleShape3D { Variant m_geometry; //Variant holding the real geometry type boost::shared_ptr< details::ShapeGeneratorBase > m_generator; - using Object >::m_system; - - std::vector > m_geometries; - std::vector > m_shapes; - std::vector > m_constraints; + using Object::m_system; template void initShape() { @@ -318,9 +355,14 @@ struct ModuleShape3D { m_generator->init(); }; + //disconnect all remove signals of stored geometry/shapes/constraints + void disconnectAll(); + //the stroage is private, all things need to be added by this methods. + //this is used to ensure the proper event connections boost::shared_ptr append(boost::shared_ptr g); boost::shared_ptr append(boost::shared_ptr g); + boost::shared_ptr append(boost::shared_ptr g); //override protected event functions to emit signals void reset() {}; @@ -370,6 +412,7 @@ struct ModuleShape3D { friend struct details::SystemSolver; friend struct details::SystemSolver::Rescaler; friend struct inheriter_base; + friend struct details::ShapeGeneratorBase; public: //the geometry class itself does not hold an aligned eigen object, but maybe the variant @@ -400,9 +443,11 @@ struct ModuleShape3D { void removeShape3D(ID id); bool hasShape3D(ID id); boost::shared_ptr getShape3D(ID id); - - protected: - using inheriter_base::m_this; + + using inheriter_base::removeShape3D; + + protected: + using inheriter_base::m_this; }; struct inheriter : public mpl::if_, inheriter_base, inheriter_id>::type {}; @@ -507,7 +552,7 @@ template boost::shared_ptr::template getModule::type::Geometry3D> ModuleShape3D::type::Shape3D_base::geometry(purpose f) { - for(geometry3d_iterator it = m_geometries.begin(); it != m_geometries.end(); it++) { + for(geometry3d_iterator it = beginGeometry3D(); it != endGeometry3D(); it++) { if((*it)->template getProperty() == f) return *it; @@ -520,8 +565,11 @@ template template boost::shared_ptr ModuleShape3D::type::Shape3D_base::append(boost::shared_ptr g) { - m_geometries.push_back(g); + g->template setProperty(true); + Connection c = g->template connectSignal(boost::bind(static_cast)>(&Shape3D_base::remove) , this, _1)); + m_geometries.push_back(fusion::make_vector(g,c)); + return ObjBase::shared_from_this(); }; @@ -531,10 +579,42 @@ template template boost::shared_ptr ModuleShape3D::type::Shape3D_base::append(boost::shared_ptr g) { - m_shapes.push_back(g); + + Connection c = g->template connectSignal(boost::bind(static_cast)>(&Shape3D_base::remove) , this, _1)); + m_shapes.push_back(fusion::make_vector(g,c)); + return ObjBase::shared_from_this(); }; +template +template +template +boost::shared_ptr +ModuleShape3D::type::Shape3D_base::append(boost::shared_ptr g) { + + Connection c = g->template connectSignal(boost::bind(static_cast)>(&Shape3D_base::remove) , this, _1)); + m_constraints.push_back(fusion::make_vector(g,c)); + + return ObjBase::shared_from_this(); +}; +template +template +template +void ModuleShape3D::type::Shape3D_base::disconnectAll() { + + typename GeometryVector::iterator git; + for(git = m_geometries.begin(); git!=m_geometries.end(); git++) + fusion::at_c<0>(*git)->template disconnectSignal(fusion::at_c<1>(*git)); + + typename ShapeVector::iterator sit; + for(sit = m_shapes.begin(); sit!=m_shapes.end(); sit++) + fusion::at_c<0>(*sit)->template disconnectSignal(fusion::at_c<1>(*sit)); + + typename ConstraintVector::iterator cit; + for(cit = m_constraints.begin(); cit!=m_constraints.end(); cit++) + fusion::at_c<0>(*cit)->template disconnectSignal(fusion::at_c<1>(*cit)); +}; + template template template @@ -544,6 +624,63 @@ void ModuleShape3D::type::Shape3D_base::recalc(boost Base::finishCalculation(); }; +template +template +template +void ModuleShape3D::type::Shape3D_base::remove(boost::shared_ptr g) { + + //before we delete this shape by calling the system remove function, we need to remove + //this geometry as this would be deleted again by the system call and we would go into infinit recoursion + + //get the vector object where the geometry is part of + typename GeometryVector::const_iterator it; + for(it=m_geometries.begin(); it!=m_geometries.end(); it++) { + if(fusion::at_c<0>(*it)==g) + break; + }; + + m_geometries.erase(std::remove(m_geometries.begin(), m_geometries.end(), *it), m_geometries.end()); + ObjBase::m_system->removeShape3D(ObjBase::shared_from_this()); +}; + +template +template +template +void ModuleShape3D::type::Shape3D_base::remove(boost::shared_ptr g) { + + //before we delete this shape by calling the system remove function, we need to remove + //this geometry as this would be deleted again by the system call and we would go into infinit recoursion + + //get the vector object where the geometry is part of + typename ShapeVector::const_iterator it; + for(it=m_shapes.begin(); it!=m_shapes.end(); it++) { + if(fusion::at_c<0>(*it)==g) + break; + }; + + m_shapes.erase(std::remove(m_shapes.begin(), m_shapes.end(), *it), m_shapes.end()); + ObjBase::m_system->removeShape3D(ObjBase::shared_from_this()); +}; + +template +template +template +void ModuleShape3D::type::Shape3D_base::remove(boost::shared_ptr g) { + + //before we delete this shape by calling the system remove function, we need to remove + //this geometry as this would be deleted again by the system call and we would go into infinit recoursion + + //get the vector object where the geometry is part of + typename ConstraintVector::const_iterator it; + for(it=m_constraints.begin(); it!=m_constraints.end(); it++) { + if(fusion::at_c<0>(*it)==g) + break; + }; + + m_constraints.erase(std::remove(m_constraints.begin(), m_constraints.end(), *it), m_constraints.end()); + ObjBase::m_system->removeShape3D(ObjBase::shared_from_this()); +}; + template template template @@ -636,20 +773,23 @@ template template void ModuleShape3D::type::inheriter_base::removeShape3D(boost::shared_ptr g) { - //remove all constraints - typedef typename Shape3D::constraint3d_iterator cit; - for(cit it=g->constraint3dBegin(); it!=g->constraint3dEnd(); it++) - m_this->removeConstraint3D(*it); + //disconnect all shapes, geometries and constraints, as otherwise we would go into infinite + //recursion + g->disconnectAll(); + //remove all constraints is unnessecary as they get removed together with the geometries //remove all geometries typedef typename Shape3D::geometry3d_iterator git; - for(git it=g->geometry3dBegin(); it!=g->geometry3dEnd(); it++) + for(git it=g->beginGeometry3D(); it!=g->endGeometry3D(); it++) m_this->removeGeometry3D(*it); - - //remove all subshapes - typedef typename Shape3D::shape3d_iterator sit; - for(sit it=g->shape3dBegin(); it!=g->shape3dEnd(); it++) - m_this->removeShape3D(*it); + + + /* TODO: find out why it iterates over a empty vector and crashs... + //remove all subshapes + typedef typename Shape3D::shape3d_iterator sit; + for(sit it=g->beginShape3D(); it!=g->endShape3D(); it++) { + m_this->removeShape3D(*it); + };*/ //emit remove shape signal bevore actually deleting it g->template emitSignal(g); @@ -689,3 +829,4 @@ void ModuleShape3D::type::inheriter_id::removeShape3D(Identif }//dcm #endif //GCM_MODULE_SHAPE3D_H + diff --git a/src/Mod/Assembly/App/opendcm/moduleState/module.hpp b/src/Mod/Assembly/App/opendcm/moduleState/module.hpp index c6760c371..d18600160 100644 --- a/src/Mod/Assembly/App/opendcm/moduleState/module.hpp +++ b/src/Mod/Assembly/App/opendcm/moduleState/module.hpp @@ -92,4 +92,3 @@ struct ModuleState { -