diff --git a/src/Mod/Assembly/App/opendcm/.kdev_include_paths b/src/Mod/Assembly/App/opendcm/.kdev_include_paths index c0f755818..a97390572 100644 --- a/src/Mod/Assembly/App/opendcm/.kdev_include_paths +++ b/src/Mod/Assembly/App/opendcm/.kdev_include_paths @@ -1 +1,3 @@ /usr/include/eigen3 +/home/stefan/Projects/openDCM/opendcm/ +/home/stefan/Projects/openDCM/ diff --git a/src/Mod/Assembly/App/opendcm/core.hpp b/src/Mod/Assembly/App/opendcm/core.hpp index f9eacdf67..6a4612f76 100644 --- a/src/Mod/Assembly/App/opendcm/core.hpp +++ b/src/Mod/Assembly/App/opendcm/core.hpp @@ -34,6 +34,7 @@ #endif +#include "core/defines.hpp" #include "core/geometry.hpp" #include "core/kernel.hpp" #include "core/system.hpp" diff --git a/src/Mod/Assembly/App/opendcm/core/clustergraph.hpp b/src/Mod/Assembly/App/opendcm/core/clustergraph.hpp index 9ac0cb3fe..ed653a05c 100644 --- a/src/Mod/Assembly/App/opendcm/core/clustergraph.hpp +++ b/src/Mod/Assembly/App/opendcm/core/clustergraph.hpp @@ -59,20 +59,75 @@ namespace fusion = boost::fusion; namespace dcm { +/** @addtogroup Core + * @{ + * */ + +/** @addtogroup ClusterGraph + * @{*/ + namespace details { -template -struct vector_fold : mpl::fold< seq, state, - mpl::push_back > {}; - -//also add basic properties for graph algorithms like index and color -typedef mpl::vector2 bgl_v_props; -typedef mpl::vector2 bgl_e_props; +/** @addtogroup Metafunctions + * @{*/ + +/** + * @brief Appends a mpl sequences to another + * + * Makes two sequence to one by appending all types of the first to the second sequence. The new + * mpl sequence can be accessed by the ::type typedef. + * Usage: @code vector_fold::type @endcode + * + * @tparam state the mpl sequence which will be expanded + * @tparam seq the mpl sequence which will be appended + **/ +template +struct vector_fold : mpl::fold < seq, state, + mpl::push_back > {}; + +/** + * @brief Creates a fusion::vector of boost shared_ptr's from the given types + * + * Creates a shared pointer sequence (sps) of the supplied types by converting them to + * boost::shared_ptr's first and creating a fusion::vector of all pointers afterwards which can be + * accessed by the type typedef. Usage: @code sps::type @endcode + * + * @tparam seq the mpl::sequence with the types to convert to shared_ptr's + **/ +template +struct sps { //shared_ptr sequence + typedef typename mpl::transform >::type spv; + typedef typename fusion::result_of::as_vector::type type; +}; +/**@}*/ + +//Define vertex and edge properties which are always added for use in the boost graph library algorithms +//which are used in the ClusterGraph implementation +typedef mpl::vector1 bgl_v_props; +typedef mpl::vector1 bgl_e_props; + + - typedef boost::adjacency_list_traits list_traits; + + +/** + * @brief A type to be used as identifier for vertices and edges + * + * Vertices and edges need to be identified in a stable(safe/load), unique(over multiple clusters) and + * comparable manner. The bgl vertex and edge discriptors don't fullfill this need as they have a direct + * relation to the graphs storage. Therefore they change value on moving entitiys to diffrent clusters or + * clone actions. This class is used to overcome this problem. + **/ typedef int universalID; +/** + * @brief Generator for unique identifiers + * + * The universalID used to identify vertices and edges globaly need to be unique and therefore can't be + * created at good will. This generator creates universalID's in a incremental manner and is intended to + * to be shared between all graphs of a system, so that all created ID's are unique. + **/ struct IDgen { universalID* counter; @@ -85,19 +140,50 @@ struct IDgen { ~IDgen() { delete counter; }; + /** + * @brief Generates a new unique ID + * + * @return :details::universalID + **/ universalID generate() { - return ++(*counter); + return ++ (*counter); }; + /** + * @brief Returns the amount if generated ID's + * + * As universalID's are integers the returned count is a ID and can therefore also be used as the last + * created ID. + * + * @return :details::universalID + **/ universalID count() { return (*counter); }; + /** + * @brief Set the current value for incremental creation + * + * ID's are created incrementaly and if a specific startingpoint is whised it can be set here by + * supplying the last created ID or the amount of totaly created ID's + * + * @param id The last created ID + * @return void + **/ void setCount(universalID id) { *counter = id; }; }; +/** + * @brief Pointer type to share a common ID generator @ref IDgen + **/ typedef boost::shared_ptr IDpointer; +/** @ingroup Functors + * @brief Functor to clear vertex or edge objects + * + * All objects are boost::shared_ptr, therefore they can be cleared by calling the reset() method. As + * objects are stored within fusion::sequences a functor is needed to clear all of them. + **/ struct clear_ptr { template void operator()(T& t) const { @@ -105,85 +191,161 @@ struct clear_ptr { }; }; -template -struct sps { //shared_ptr sequence - typedef typename mpl::transform >::type spv; - typedef typename fusion::result_of::as_vector::type type; -}; - } +/** @name Descriptors */ +/**@{ + * @brief Identifier for local vertices + * + * The boost graph library works with identifiers for vertices which directly relate to there storage. + * Therefore they can be used only in the relevant cluster, they are local. These are the descriptors + * which need to be used for all bgl algorithms. + **/ typedef details::list_traits::vertex_descriptor LocalVertex; + +/** + * @brief Indentifier for local edge + * + * The boost graph library works with identifiers for edges which directly relate to there storage. + * Therefore they can be used only in the relevant cluster, they are local. These are the descriptors + * which need to be used for all bgl algorithms. + **/ typedef details::list_traits::edge_descriptor LocalEdge; + +/** + * @brief Identifier for global vertex + * + * To overcome the locality of the bgl vertex descriptors a global alternative is introduced. This descriptor + * is unique over clusters and stable on moves and clones. + **/ typedef details::universalID GlobalVertex; + +/** + * @brief Identifier for global edge + * + * To overcome the locality of the bgl edge discriptors a global alternative is introduced. This descriptor + * is unique over clusters and stable on moves and clones. It holds it's source and target also as global + * descriptors of type GlobalVertex and has a unique ID in form of a universalID assigned. + **/ struct GlobalEdge { GlobalVertex source; GlobalVertex target; details::universalID ID; - bool operator==(const GlobalEdge& second) const { - return ID==second.ID; + bool operator== (const GlobalEdge& second) const { + return ID == second.ID; }; - bool operator!=(const GlobalEdge& second) const { - return ID!=second.ID; + bool operator!= (const GlobalEdge& second) const { + return ID != second.ID; }; bool valid() { - return ID>9; + return ID > 9; }; }; +/**@}*/ +/** + * @brief A graph that can be stacked in a tree-like manner without loosing it connections + * + * This is basicly a boost adjacency_list with single linked lists 'listS' as storage for vertices and + * edges. The edges are undirected. This allows to use all boost graph algorithms and provides therefore + * an comprehensive way for analysing and manipulating its content. It further extends the class with the + * possibility to cluster its content and to add properties and objects to all entitys. For more + * information, see the module ClusterGraph + * + * @tparam edge_prop a mpl::vector with properties which are added to local edges + * @tparam vertex_prop a mpl::vector with properties which are added to vertices + * @tparam cluster_prop a mpl::vector with properties which are added to all clusters + * @tparam objects a mpl::vector with all object types which shall be stored at vertices and edges + **/ template< typename edge_prop, typename vertex_prop, typename cluster_prop, typename objects> -class ClusterGraph : public boost::adjacency_list< boost::listS, boost::listS, +class ClusterGraph : public boost::adjacency_list < boost::listS, boost::listS, boost::undirectedS, - fusion::vector< GlobalVertex, - typename details::pts::type>::type, - typename details::sps::type>, - fusion::vector< typename details::pts::type>::type, - std::vector< fusion::vector< typename details::sps::type, GlobalEdge > > > >, - public boost::noncopyable, - public boost::enable_shared_from_this > { + fusion::vector < GlobalVertex, + typename details::pts< typename details::ensure_properties::type >::type, + typename details::sps::type > , + fusion::vector < typename details::pts< typename details::ensure_properties::type >::type, + std::vector< fusion::vector< typename details::sps::type, GlobalEdge > > > > , +public PropertyOwner::type>, +public boost::noncopyable, + public boost::enable_shared_from_this > { public: - typedef typename details::vector_fold::type edge_properties; - typedef typename details::vector_fold::type vertex_properties; - + /** + * @brief mpl::vector with all edge properties + * + * The edge properties supplied as template argument to the ClusterGraph are extended with graph + * specific properties, for example a edge_index_prop. These extra properties are intendet to be + * used with boost graph algorithms as property maps. They need to be in specefied by the ClusterGraph + * as they are used within it's implementation. If the graph specific properties are already a part + * of the given property sequence, nothing happens, they are not added twice. + **/ + typedef typename details::ensure_properties::type edge_properties; + /** + * @brief mpl::vector with all vertex properties + * + * The vertex properties supplied as template argument to the ClusterGraph are extended with graph + * specific properties as vertex_index_prop. These extra properties are intendet to be + * used with boost graph algorithms as property maps. They need to be in specefied by the ClusterGraph + * as they are used within it's implementation.If the graph specific properties are already a part + * of the given property sequence, nothing happens, they are not added twice. + **/ + typedef typename details::ensure_properties::type vertex_properties; + + /** + * @brief The property bundle for GlobalEdges + * + * A local edge in a cluster can hold multiple gloabal ones. Therefor we need an extra bundle for + * the GlobalEdges. This bundle holds the objects which are added to that global edge and it's identifier. + * Note that global edges don't have properties, these are only for local ones. + **/ typedef fusion::vector< typename details::sps::type, GlobalEdge > edge_bundle_single; + /** + * @brief The property bundle for local edges + * + * Local edges can hold multiple global ones, we therefore need a std::vector of global edges. As + * they are fully described by a edge_bundle_single we store those. Also local edges can have properties, + * so store a fusion sequence of them too. + **/ typedef fusion::vector< typename details::pts::type, std::vector< edge_bundle_single > > edge_bundle; + /** + * @brief Iteator to access all edge_bundle_single stored in a edge_bundle + **/ typedef typename std::vector< edge_bundle_single >::iterator edge_single_iterator; - typedef fusion::vector< GlobalVertex, typename details::pts::type, + /** + * @brief Property bundle for local vertices + * + * This bundle is simpler than the edge one, as every vertex has on single bundle. We therefore + * store the global descriptor for identification, the fusion sequence with the properties and + * the objects all in one bundle. + **/ + typedef fusion::vector < GlobalVertex, typename details::pts::type, typename details::sps::type > vertex_bundle; - - typedef boost::adjacency_list< boost::listS, boost::listS, + /** + * @brief The adjacency_list type ClusterGraph inherited from + **/ + typedef boost::adjacency_list < boost::listS, boost::listS, boost::undirectedS, vertex_bundle, edge_bundle > Graph; - + typedef boost::enable_shared_from_this > sp_base; //if changed_prop is not a property we have to add it now - typedef typename mpl::if_< - boost::is_same< - typename mpl::find::type, - typename mpl::end::type >, - typename mpl::push_back::type, - cluster_prop >::type cluster_properties; - - typedef typename details::pts::type cluster_bundle; + typedef typename details::ensure_property::type cluster_properties; typedef typename boost::graph_traits::vertex_iterator local_vertex_iterator; typedef typename boost::graph_traits::edge_iterator local_edge_iterator; typedef typename boost::graph_traits::out_edge_iterator local_out_edge_iterator; - typedef std::map > ClusterMap; - - cluster_bundle m_cluster_bundle; + typedef std::map > ClusterMap; private: struct global_extractor { typedef GlobalEdge& result_type; template result_type operator()(T& bundle) const { - return fusion::at_c<1>(bundle); + return fusion::at_c<1> (bundle); }; }; struct global_vertex_extractor { @@ -205,10 +367,10 @@ private: BOOST_MPL_ASSERT((mpl::not_::type > >)); result_type operator()(vertex_bundle& bundle) const { - return fusion::at(fusion::at_c<2>(bundle)); + return fusion::at (fusion::at_c<2> (bundle)); }; result_type operator()(edge_bundle_single& bundle) const { - return fusion::at(fusion::at_c<0>(bundle)); + return fusion::at (fusion::at_c<0> (bundle)); }; }; @@ -221,11 +383,11 @@ private: typedef typename mpl::if_< is_edge_property, edge_properties, vertex_properties >::type sequence; typedef typename mpl::find::type iterator; typedef typename mpl::distance::type, iterator>::type distance; - typedef typename mpl::if_< is_edge_property, mpl::int_<0>, mpl::int_<1> >::type pos; + typedef typename mpl::if_< is_edge_property, mpl::int_<0>, mpl::int_<1> >::type pos; template< typename seq> result_type operator()(seq& b) const { - return fusion::at(fusion::at(b)); + return fusion::at (fusion::at (b)); }; }; @@ -253,20 +415,57 @@ private: public: //iterators + /** + * @brief Iterator for global edge descriptors \ref GlobalEdge + **/ typedef boost::transform_iterator global_edge_iterator; + + /** + * @brief Iterator for global vertex descriptor \ref GlobalVertex + **/ typedef boost::transform_iterator global_vertex_iterator; + /** + * @brief Iterator for objects of given type + * + * Allows to iterate over all objects of given type, dereferencing gives the boost::shared_ptr + * + * @tparam Obj the object type to iterate over + **/ template struct object_iterator : public boost::transform_iterator, edge_single_iterator> { object_iterator(edge_single_iterator it, object_extractor f) - : boost::transform_iterator,edge_single_iterator>(it, f) {}; + : boost::transform_iterator, edge_single_iterator> (it, f) {}; }; + /** + * @brief Iterator for clusters + * + * Allows to iterate over all subclusters. + **/ typedef typename ClusterMap::iterator cluster_iterator; + /** + * @brief Const equivalent to \ref cluster_iterator + **/ typedef typename ClusterMap::const_iterator const_cluster_iterator; + /** + * @brief Basic constructor + * + * This constructor creates a empty cluster with a new ID generator. This is to be used on initial + * clustergraph creation, so only for the very first cluster. + **/ ClusterGraph() : m_id(new details::IDgen) {}; - + + /** + * @brief Dependent constructor + * + * This constructor creates a new cluster, but uses the given cluster as parent. It will therefore + * create a tree-like relationship. Be aware, that the new cluster is not added to the parents + * subcluster list, that has to be done manualy. The new cluster shares the parents ID generator. + * + * @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; }; @@ -287,14 +486,15 @@ public: template void copyInto(boost::shared_ptr into, Functor& functor) const { - //lists does not provide vertex index, so we have to build our own (cant use the internal - //vertex_index_property as we would need to reset the indices and that's not possible in const graph) + //lists does not provide vertex index, so we have to build our own (cant use the internal + //vertex_index_property as we would need to reset the indices and that's not possible in const graph) typedef std::map IndexMap; IndexMap mapIndex; boost::associative_property_map propmapIndex(mapIndex); std::pair vit = boost::vertices(*this); - for(int c=0; vit.first != vit.second; vit.first++, c++) + + for(int c = 0; vit.first != vit.second; vit.first++, c++) put(propmapIndex, *vit.first, c); //first copy all vertices and edges, but be aware that the objects in the new graph @@ -311,9 +511,10 @@ public: //now that we have all vertices we can recreate the subclusters std::pair it = clusters(); - for(; it.first!=it.second; it.first++) { + + for(; it.first != it.second; it.first++) { //create the new Graph - boost::shared_ptr ng = boost::shared_ptr(new ClusterGraph(into)); + boost::shared_ptr ng = boost::shared_ptr (new ClusterGraph(into)); //we already have the new vertex, however, we need to find it GlobalVertex gv = getGlobalVertex((*it.first).first); @@ -329,115 +530,240 @@ public: //lets see if the objects need special treatment into->for_each_object(functor, false); }; - + + /** + * @brief Compare by adress, not by content + * @param other the cluster to compare with + * @return bool if this is the same cluster in memory + **/ template - bool operator==(const T& other) const { + bool operator== (const T& other) const { return this == &other; }; + /** + * @brief Compare by adress, not by content + * @param other the cluster to compare with + * @return bool if this is the not same cluster in memory + **/ template - bool operator!=(const T& other) const { + bool operator!= (const T& other) const { return !(this == &other); }; - + + /** + * @brief Set diffrent behaviour for changed markers + * + * Some methods of the ClusterGraph set it's changed_prop to true. Thats sensible, as they change + * the graph. However, there are situations where you want to use the methods but don't want the change + * marked. For example recreations while cloning. This method can be used to disable the changed setting. + * @param on Turn change markers on or of + * @return void + **/ void setCopyMode(bool on) { - copy_mode = on; + copy_mode = on; }; - void setChanged() { - if(!copy_mode) - setClusterProperty(true); - }; + //Make sure the compiler finds the base class setters even with equal named functions in this class + using PropertyOwner::getProperty; + using PropertyOwner::setProperty; - /* ******************************************************* - * Cluster Property - * *******************************************************/ - template - typename P::type& getClusterProperty() { - typedef typename mpl::find::type iterator; - typedef typename mpl::distance::type, iterator>::type distance; - BOOST_MPL_ASSERT((mpl::not_::type > >)); - return fusion::at(m_cluster_bundle); - }; + /** + * @brief Set the property of a owned cluster + * + * Makes it easy to set a property of a subcluster without retrieving it first + * + * @tparam P the property type which shall be set + * @param v the local vertex which describes the subcluster + **/ template typename P::type& getSubclusterProperty(LocalVertex v) { - return getVertexCluster(v)->template getClusterProperty

(); + return getVertexCluster(v)->template getProperty

(); }; - template - void setClusterProperty(typename P::type p) { - getClusterProperty

() = p; + /** + * @brief Mark if the cluster was changed + * + * @return void + **/ + void setChanged() { + if(!copy_mode) + PropertyOwner::template setProperty (true); }; /* ******************************************************* * Subclustering * *******************************************************/ + + /** + * @brief Creates a new subcluster + * + * As clusters can be stacked in a tree like manner, this function can be used to create new + * children. It automaticly adds it to the subcluster list and adds it to the graph. The new + * subcluster is fully defined by its object and the vertex descriptor which is it's position + * in the current cluster. + * + * @return :pair< boost::shared_ptr< ClusterGraph >, LocalVertex > Subcluster and its descriptor + **/ std::pair, LocalVertex> createCluster() { vertex_bundle vp; - fusion::at_c<0>(vp) = m_id->generate(); - LocalVertex v= boost::add_vertex(vp, *this); - return std::pair, LocalVertex>(m_clusters[v] = boost::shared_ptr(new ClusterGraph(sp_base::shared_from_this())), v); + fusion::at_c<0> (vp) = m_id->generate(); + LocalVertex v = boost::add_vertex(vp, *this); + return std::pair, LocalVertex> (m_clusters[v] = boost::shared_ptr (new ClusterGraph(sp_base::shared_from_this())), v); }; + /** + * @brief Returns the parent cluster + * + * In the stacked cluster hirarchy most clusters have a parent whcih can be accessed with this function. + * However, the toplevel cluster dos nothave a parent and a empty shared_ptr is returned. + * + * @return :shared_ptr< ClusterGraph > the parent cluster or empty pointer + **/ inline boost::shared_ptr parent() { - return boost::shared_ptr(m_parent); + return boost::shared_ptr (m_parent); }; + /** + * @brief const version of \ref parent() + * + * @return :shared_ptr< ClusterGraph > + **/ inline const boost::shared_ptr parent() const { - return boost::shared_ptr(m_parent); - }; - bool isRoot() const { - return m_parent.expired(); + return boost::shared_ptr (m_parent); }; + /** + * @brief Is this the toplevel cluster? + * + * @return bool if it is + **/ + bool isRoot() const { + return m_parent.expired(); + }; + + /** + * @brief Returns the toplevel cluster + * + * @return :shared_ptr< ClusterGraph > + **/ boost::shared_ptr root() { return isRoot() ? sp_base::shared_from_this() : parent()->root(); }; + /** + * @brief const equivalent of \ref root() + * + * @return :shared_ptr< ClusterGraph > + **/ const boost::shared_ptr root() const { return isRoot() ? sp_base::shared_from_this() : parent()->root(); }; + /** + * @brief Iterators for all subclusters + * + * A pair with two \ref cluster_iterator is returned which point to the first cluster and + * to one after the last. #this allows full iteration over all subclusters + * + * @return :pair< cluster_iterator, cluster_iterator > + **/ std::pair clusters() { return std::make_pair(m_clusters.begin(), m_clusters.end()); } + + /** + * @brief const equivalent to \ref clusters() + * + * @return :pair< const_cluster_iterator, const_cluster_iterator > + **/ std::pair clusters() const { return std::make_pair(m_clusters.begin(), m_clusters.end()); } + /** + * @brief The amount of all subclusters + * + * @return :size_t + **/ std::size_t numClusters() const { return m_clusters.size(); } + /** + * @brief Check if this vertex is a cluster + * + * A subcluster is added as normal vertex to the parent cluster. There is no way to distinguish + * between clusters and normal vertices with global or local descriptors only. Therefore this + * function can be used to get information about the type. If it is a cluster, it can be accessed + * with \ref getVertexCluster + * + * @param v The vertex to be checked + * @return bool is cluster or not + **/ bool isCluster(LocalVertex v) { return (m_clusters.find(v) != m_clusters.end()); }; + /** + * @brief Get the cluster corresponding the discriptor + * + * A subcluster is added as normal vertex to the parent cluster. There is no way to access + * the clusters object with global or local descriptors only. Therefore this + * function can be used to get the object belonging to the descriptor. If the vertex is not + * a cluster an empty pointer is returned. + * + * @param v The vertex for which the cluster is wanted + * @return boost::shared_ptr the coresponding cluster orempty pointer + **/ boost::shared_ptr getVertexCluster(LocalVertex v) { if(isCluster(v)) return m_clusters[v]; + //TODO:throw if not a cluster return sp_base::shared_from_this(); }; + /** + * @brief Get the vertex descrptor which descripes the clusters position in the graph + * + * This function is the inverse to \ref getVertexCluster + * + * @param g the graph for which the vertex is searched + * @return :LocalVertex + **/ LocalVertex getClusterVertex(boost::shared_ptr g) { std::pair it = clusters(); - for(; it.first!=it.second; it.first++) { + + for(; it.first != it.second; it.first++) { if((*it.first).second == g) return (*it.first).first; } + return LocalVertex(); }; + /** + * @brief Convinience function for \ref removeCluster + **/ template void removeCluster(boost::shared_ptr g, Functor& f) { removeCluster(getClusterVertex(g), f); }; + /** + * @brief Convinience function for \ref removeCluster + **/ void removeCluster(boost::shared_ptr g) { placehoder p; removeCluster(getClusterVertex(g), p); }; + /** + * @brief Delete all subcluster + * + * @return void + **/ + void clearClusters() { m_clusters.clear(); }; @@ -457,6 +783,7 @@ public: void removeCluster(LocalVertex v, Functor& f) { typename ClusterMap::iterator it = m_clusters.find(v); + if(it == m_clusters.end()) return; //TODO:throw @@ -468,7 +795,7 @@ public: //remove from map, delete subcluster and remove vertex m_clusters.erase(v); - boost::clear_vertex(v, *this); //should not be needed, just to ensure it + boost::clear_vertex(v, *this); //should not be needed, just to ensure it boost::remove_vertex(v, *this); }; void removeCluster(LocalVertex v) { @@ -481,9 +808,10 @@ protected: void remove_vertices(Functor& f, bool recursive = false) { std::pair vit = boost::vertices(*this); + //we iterate forward before deleting to not invalidate our iterator while(vit.first != vit.second) { - LocalVertex v = *(vit.first); + LocalVertex v = * (vit.first); vit.first++; if(!isCluster(v)) { @@ -496,7 +824,8 @@ protected: if(recursive) { cluster_iterator cit; - for(cit=m_clusters.begin(); cit != m_clusters.end(); cit++) { + + for(cit = m_clusters.begin(); cit != m_clusters.end(); cit++) { f((*cit).second); (*cit).second->remove_vertices(f, recursive); } @@ -513,24 +842,32 @@ public: /** * @brief Add a vertex to the local cluster * - * @return fusion:vector< LocalVertex, GlobalVertex > with the local and global vertex descriptor + * @return fusion::vector the local and global vertex descriptor **/ fusion::vector addVertex() { vertex_bundle vp; - fusion::at_c<0>(vp) = m_id->generate(); - LocalVertex v= boost::add_vertex(vp, *this); + fusion::at_c<0> (vp) = m_id->generate(); + LocalVertex v = boost::add_vertex(vp, *this); setChanged(); return fusion::make_vector(v, m_id->count()); }; + /** + * @brief Iterators of all global vertices in this cluster + * + * Returns the iterator for the first global vertex and the end() iterator as reference for + * iterating + * + * @return std::pair< global_vertex_iterator, global_vertex_iterator > global vertex iterators + **/ std::pair globalVertices() { std::pair res = boost::vertices(*this); global_vertex_iterator begin = boost::make_transform_iterator(res.first, global_vertex_extractor(*this)); global_vertex_iterator end = boost::make_transform_iterator(res.second, global_vertex_extractor(*this)); - return std::pair(begin, end); + return std::pair (begin, end); }; /** @@ -563,22 +900,23 @@ public: fusion::vector addEdge(LocalVertex source, LocalVertex target) { //manual edge creation with cluster is not allowed - if((source==target) || isCluster(source) || isCluster(target)) + if((source == target) || isCluster(source) || isCluster(target)) return fusion::make_vector(LocalEdge(), GlobalEdge(), false); LocalEdge e; bool done; - boost::tie(e,done) = boost::edge(source, target, *this); + 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); //init the bundle corecctly for new edge - GlobalEdge global = { fusion::at_c<0>((*this)[source]), fusion::at_c<0>((*this)[target]), m_id->generate() }; + GlobalEdge global = { fusion::at_c<0> ((*this) [source]), fusion::at_c<0> ((*this) [target]), m_id->generate() }; edge_bundle_single s; - fusion::at_c<1>(s) = global; - fusion::at_c<1>((*this)[e]).push_back(s); + fusion::at_c<1> (s) = global; + fusion::at_c<1> ((*this) [e]).push_back(s); setChanged(); return fusion::make_vector(e, global, true); @@ -603,32 +941,34 @@ public: **/ fusion::vector addEdge(GlobalVertex source, GlobalVertex target) { - LocalVertex v1,v2; + LocalVertex v1, v2; LocalEdge e; - bool d1,d2,d3; - boost::tie(v1,d1) = getContainingVertex(source); - boost::tie(v2,d2) = getContainingVertex(target); + bool d1, d2, d3; + boost::tie(v1, d1) = getContainingVertex(source); + 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)) { + if(v1 == v2 && isCluster(v1)) { fusion::vector res = getVertexCluster(v1)->addEdge(source, target); - fusion::at_c<3>(res)=false; + fusion::at_c<3> (res) = false; return res; } //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); + boost::tie(e, d3) = boost::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); //init the bundle corectly for new edge GlobalEdge global = { source, target, m_id->generate() }; edge_bundle_single s; - fusion::at_c<1>(s) = global; - fusion::at_c<1>((*this)[e]).push_back(s); + fusion::at_c<1> (s) = global; + fusion::at_c<1> ((*this) [e]).push_back(s); setChanged(); return fusion::make_vector(e, global, true, true); @@ -652,12 +992,12 @@ public: **/ std::pair getGlobalEdges(LocalEdge e) { - std::vector& vec = fusion::at_c<1>((*this)[e]); + std::vector& vec = fusion::at_c<1> ((*this) [e]); global_edge_iterator begin = boost::make_transform_iterator(vec.begin(), global_extractor()); global_edge_iterator end = boost::make_transform_iterator(vec.end(), global_extractor()); setChanged(); - return std::pair(begin, end); + return std::pair (begin, end); }; /** @@ -672,7 +1012,7 @@ public: **/ int getGlobalEdgeCount(LocalEdge e) { - return fusion::at_c<1>((*this)[e]).size(); + return fusion::at_c<1> ((*this) [e]).size(); }; /** @@ -709,7 +1049,7 @@ public: * @return GlobalVertex **/ GlobalVertex getGlobalVertex(LocalVertex v) const { - return fusion::at_c<0>((*this)[v]); + return fusion::at_c<0> ((*this) [v]); }; /** @@ -723,7 +1063,7 @@ public: * @return GlobalVertex which was assigned **/ GlobalVertex setGlobalVertex(LocalVertex lv, GlobalVertex gv) { - fusion::at_c<0>((*this)[lv]) = gv; + fusion::at_c<0> ((*this) [lv]) = gv; return gv; }; @@ -733,11 +1073,11 @@ public: * The GlobalVertex has to be in this cluster or any of it's subclusters. If its in a subcluster, the returned * LocalVertex will represent this cluster. If the GlobalVertex is not in this clusters scope the function fails. * - * @param GlobalVertex + * @param vertex GlobalVertex for which the local one shall be returned * @return std::pair< LocalVertex, bool > The LocalVertex containing the global one and an success indicator **/ - std::pair getLocalVertex(GlobalVertex e) { - return getContainingVertex(e); + std::pair getLocalVertex(GlobalVertex vertex) { + return getContainingVertex(vertex); }; /** @@ -770,15 +1110,16 @@ private: apply_remove_prediacte(Functor& f, GlobalEdge e) : func(f), edge(e), vert(0), isEdge(true) {}; bool operator()(edge_bundle_single& e) { bool res; + if(isEdge) - res = (edge==fusion::at_c<1>(e)); + res = (edge == fusion::at_c<1> (e)); else - res = (vert==fusion::at_c<1>(e).source) || (vert==fusion::at_c<1>(e).target); + res = (vert == fusion::at_c<1> (e).source) || (vert == fusion::at_c<1> (e).target); - if(res || vert<0) - func(fusion::at_c<1>(e)); + if(res || vert < 0) + func(fusion::at_c<1> (e)); - return res || vert<0; + return res || vert < 0; } }; @@ -791,24 +1132,27 @@ private: void downstreamRemoveVertex(GlobalVertex v, Functor& f) { std::pair res = getContainingVertex(v); + if(!res.second) return; //TODO:throw //iterate over every edge that connects to the global vertex or the cluster in which it is in std::vector re; //remove edges std::pair it = boost::out_edges(res.first, *this); + for(; it.first != it.second; it.first++) { - std::vector& vec = fusion::at_c<1>((*this)[*(it.first)]); - vec.erase(std::remove_if(vec.begin(), vec.end(), apply_remove_prediacte(f,v)), vec.end()); + std::vector& vec = fusion::at_c<1> ((*this) [* (it.first)]); + vec.erase(std::remove_if(vec.begin(), vec.end(), apply_remove_prediacte (f, v)), vec.end()); + if(vec.empty()) - re.push_back(*(it.first)); + re.push_back(* (it.first)); }; std::for_each(re.begin(), re.end(), boost::bind(&ClusterGraph::simpleRemoveEdge, this, _1)); //if we have the real vertex here and not only a containing cluster we can delete it if(!isCluster(res.first)) { - boost::clear_vertex(res.first, *this); //just to make sure, should be done already + boost::clear_vertex(res.first, *this); //just to make sure, should be done already boost::remove_vertex(res.first, *this); }; @@ -820,7 +1164,7 @@ private: void simpleRemoveEdge(LocalEdge e) { boost::remove_edge(e, *this); }; - + public: /** @@ -832,6 +1176,7 @@ public: * need to make sure it's not, as removing a clustervertex will not delete the coresponding cluster. * * @param id Local Vertex which should be removed from the graph + * @param f functor whose operator(GlobalEdge) is called for every removed edge **/ template void removeVertex(LocalVertex id, Functor& f) { @@ -851,6 +1196,7 @@ public: * needs to implement operato()(LocalEdge edge). * * @param id Global Vertex which should be removed from the graph + * @param f functor whose operator(LocalEdge) is called on every removed edge **/ template void removeVertex(GlobalVertex id, Functor& f) { @@ -873,15 +1219,16 @@ public: **/ void removeEdge(GlobalEdge id) { fusion::vector res = getContainingEdgeGraph(id); - if(!fusion::at_c<2>(res)) + + if(!fusion::at_c<2> (res)) return; //TODO:throw placehoder p; - std::vector& vec = fusion::at_c<1>((*fusion::at_c<1>(res))[fusion::at_c<0>(res)]); - vec.erase(std::remove_if(vec.begin(), vec.end(), apply_remove_prediacte(p,id)), vec.end()); + std::vector& vec = fusion::at_c<1> ((*fusion::at_c<1> (res)) [fusion::at_c<0> (res)]); + vec.erase(std::remove_if(vec.begin(), vec.end(), apply_remove_prediacte (p, id)), vec.end()); if(vec.empty()) - boost::remove_edge(fusion::at_c<0>(res), *fusion::at_c<1>(res)); + boost::remove_edge(fusion::at_c<0> (res), *fusion::at_c<1> (res)); }; /** @@ -891,13 +1238,14 @@ public: * operator()(GlobalEdge). If no functor is needed just use boost::remove_edge. * * @param id Global Edge which should be removed from the graph + * @param f functor whoms operator(GlobalEdge) is called * @return bool indicates if the global id could be removed **/ template void removeEdge(LocalEdge id, Functor& f) { - std::vector& vec = fusion::at_c<1>((*this)[id]); - std::for_each(vec.begin(), vec.end(), boost::bind(boost::ref(apply_remove_prediacte(f,-1)),_1)); + std::vector& vec = fusion::at_c<1> ((*this) [id]); + std::for_each(vec.begin(), vec.end(), boost::bind (boost::ref(apply_remove_prediacte (f, -1)), _1)); boost::remove_edge(id, *this); }; @@ -920,37 +1268,42 @@ protected: //used with vertex bundle type template - typename boost::enable_if::type>, + 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); } //used with edge bundle type and global edge descriptor template - typename boost::enable_if::type>, - boost::is_same >, result_type>::type operator()(bundle& p) { + typename boost::enable_if < mpl::and_ < boost::is_same::type>, + boost::is_same > , result_type >::type operator()(bundle& p) { edge_single_iterator e; //need to search the edge_bundle for the global descriptor - std::vector& ebsv = fusion::at_c<1>(p); - for(edge_single_iterator it= ebsv.begin(); it != ebsv.end(); it++) { + std::vector& ebsv = fusion::at_c<1> (p); + + 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; } } + return object_extractor()(*e); } //used with edge bundle type and local edge descriptor template - typename boost::enable_if::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()); - return object_extractor()(fusion::at_c<1>(p).front()); + 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()); + + return object_extractor()(fusion::at_c<1> (p).front()); } key m_key; @@ -979,12 +1332,13 @@ public: * case, as it can hold many global edges, each with it's own objetcs. Using a LocalEdge as key will * always return the object for the first GlobalEdge. * - * @param local or global Vertex/Edge descriptor for which the object is desired + * @tparam Obj the object type which shall be returned + * @param k local or global Vertex/Edge descriptor for which the object is desired * @return shared_ptr< Obj > the pointer to the desired object **/ template boost::shared_ptr getObject(key k) { - return apply_to_bundle(k, obj_helper(k)); + return apply_to_bundle(k, obj_helper (k)); }; /** @@ -995,13 +1349,14 @@ public: * case, as it can hold many global edges, each with it's own objects. Using a LocalEdge as key will * always set the object for the first GlobalEdge. * + * @tparam Obj the object type which shall be set * @param k local or global Vertex/Edge descriptor for which the object should be set * @param val the object which should be stored * @return void **/ template void setObject(key k, boost::shared_ptr val) { - apply_to_bundle(k, obj_helper(k)) = val; + apply_to_bundle(k, obj_helper (k)) = val; setChanged(); }; @@ -1012,16 +1367,17 @@ public: * LocalEdge's can hold multiple global ones and the iterators can be used to access a specific object type in * all global edges hold by this local edge. * + * @tparam Obj the object type over which it shall be iterated * @param k the LocalEdge over which all Objects should be iterated. * @return pair< begin, end > the iterator rang from begin (first element) to end (first undefined element) **/ template std::pair< object_iterator, object_iterator > getObjects(LocalEdge k) { - std::vector& vec = fusion::at_c<1>((*this)[k]); + std::vector& vec = fusion::at_c<1> ((*this) [k]); object_iterator begin(vec.begin(), object_extractor()); object_iterator end(vec.end(), object_extractor()); - return std::pair< object_iterator, object_iterator >(begin, end); + return std::pair< object_iterator, object_iterator > (begin, end); }; /** @@ -1032,6 +1388,7 @@ public: * search is specified, all subclusters are searched too, but the cluster is passt to the Functor * first. So make sure a function overload for clusters exist in this case. * + * @tparam Obj the object type for which the functor shall be used * @param f the functor to which all valid objects get passed to. * @param recursive specifies if the subclusters should be searched for objects too **/ @@ -1039,15 +1396,19 @@ public: void for_each(Functor& f, bool recursive = false) { std::pair it = boost::vertices(*this); + for(; it.first != it.second; it.first++) { - boost::shared_ptr ptr = getObject(*(it.first)) ; + boost::shared_ptr ptr = getObject (* (it.first)) ; + if(ptr) f(ptr); } std::pair eit = boost::edges(*this); + for(; eit.first != eit.second; eit.first++) { - std::pair< object_iterator< Obj >, object_iterator< Obj > > goit = getObjects(*(eit.first)); + std::pair< object_iterator< Obj >, object_iterator< Obj > > goit = getObjects (* (eit.first)); + for(; goit.first != goit.second; goit.first++) { if(*goit.first) f(*goit.first); @@ -1056,9 +1417,10 @@ public: if(recursive) { cluster_iterator cit; - for(cit=m_clusters.begin(); cit != m_clusters.end(); cit++) { + + for(cit = m_clusters.begin(); cit != m_clusters.end(); cit++) { f((*cit).second); - (*cit).second->template for_each(f, recursive); + (*cit).second->template for_each (f, recursive); } } }; @@ -1080,24 +1442,28 @@ public: valid_ptr_apply func(f); std::pair it = boost::vertices(*this); + for(; it.first != it.second; it.first++) { - typename details::sps::type& seq = fusion::at_c<2>((*this)[*it.first]); + typename details::sps::type& seq = fusion::at_c<2> ((*this) [*it.first]); fusion::for_each(seq, func); } typedef typename std::vector::iterator iter; std::pair eit = boost::edges(*this); + for(; eit.first != eit.second; eit.first++) { - std::vector& vec = fusion::at_c<1>((*this)[*eit.first]); + std::vector& vec = fusion::at_c<1> ((*this) [*eit.first]); + for(iter git = vec.begin(); git != vec.end(); git++) { - typename details::sps::type& seq = fusion::at_c<0>(*git); + typename details::sps::type& seq = fusion::at_c<0> (*git); fusion::for_each(seq, func); } } if(recursive) { cluster_iterator cit; - for(cit=m_clusters.begin(); cit != m_clusters.end(); cit++) { + + for(cit = m_clusters.begin(); cit != m_clusters.end(); cit++) { f((*cit).second); (*cit).second->for_each_object(f, recursive); } @@ -1119,21 +1485,21 @@ protected: typedef base_type& result_type; typedef typename mpl::find::type vertex_iterator; typedef typename mpl::find::type edge_iterator; - typedef typename mpl::if_::type >, - edge_iterator, vertex_iterator>::type iterator; + typedef typename mpl::if_ < boost::is_same::type >, + edge_iterator, vertex_iterator >::type iterator; BOOST_MPL_ASSERT((mpl::not_::type > >)); //used with vertex bundle type template - typename boost::enable_if::type>, - result_type>::type operator()(bundle& p) { + typename boost::enable_if < boost::is_same::type>, + result_type >::type operator()(bundle& p) { return property_extractor()(p); } //used with edge bundle type template - typename boost::enable_if::type>, - result_type>::type operator()(bundle& p) { + typename boost::enable_if < boost::is_same::type>, + result_type >::type operator()(bundle& p) { return property_extractor()(p); } @@ -1148,12 +1514,13 @@ public: * was set before, a default construced will be returned. Accessing the property at a global edge will return * the property of the holding local edge. * - * @param local or global Vertex/Edge descriptor for which the property is desired + * @tparam property the property type which shall be returned + * @param k local or global Vertex/Edge descriptor for which the property is desired * @return property::type& the reference to the desired property **/ template typename property::type& getProperty(key k) { - return apply_to_bundle(k, get_prop_helper(k)); + return apply_to_bundle(k, get_prop_helper (k)); }; /** @@ -1163,36 +1530,39 @@ public: * to objects. Setting the property at a local edge is a special case, as it can hold many global edges, * each with it's own propertys. Using a LocalEdge as key will always set the property for the first GlobalEdge. * + * @tparam property the property type which shall be set * @param k local or global Vertex/Edge descriptor for which the property should be set * @param val the property value which should be stored * @return void **/ template void setProperty(key k, typename property::type val) { - apply_to_bundle(k, get_prop_helper(k)) = val; + apply_to_bundle(k, get_prop_helper (k)) = val; setChanged(); }; - + /** * @brief recreate the internal index maps for edges and vertices * * Quite many boost graph algorithms need the indices for vertices and edges which are provided by property - * maps. As we use list, and not vector, as underlaying storage we don't get that property for free and + * maps. As we use list, and not vector, as underlaying storage we don't get that property for free and * need to create it ourself. To ease that procedure the internal property vertex_index_prop and edge_index_prop * can be used as property maps and can be initialized by calling this function. * * @return void **/ void initIndexMaps() { - - //just iterate over all edges and vertices and give them all a unique index + + //just iterate over all edges and vertices and give them all a unique index std::pair vit = boost::vertices(*this); - for(int c=0; vit.first != vit.second; vit.first++, c++) + + for(int c = 0; vit.first != vit.second; vit.first++, c++) setProperty(*vit.first, c); - - std::pair eit = boost::edges(*this); - for(int c=0; eit.first != eit.second; eit.first++, c++) + + std::pair eit = boost::edges(*this); + + for(int c = 0; eit.first != eit.second; eit.first++, c++) setProperty(*eit.first, c); }; @@ -1256,27 +1626,31 @@ public: /* add the later removed edges to the coressponding existing edges * (or create new edges between adjacent vertices of moved vertex and cluster). * also get the edge between cluster and vertex while iterating */ - for(; it.first!=it.second; it.first++) { + for(; it.first != it.second; it.first++) { LocalVertex target = boost::target(*it.first, *this); + if(target != Cluster) { //get or create the edge between the old edge target and the cluster LocalEdge e; bool done; - boost::tie(e,done) = boost::edge(target, Cluster, *this); - if(!done) boost::tie(e,done) = boost::add_edge(target, Cluster, *this); + boost::tie(e, done) = boost::edge(target, Cluster, *this); + + if(!done) boost::tie(e, done) = boost::add_edge(target, Cluster, *this); + //if(!done) TODO: throw - std::vector& ep = fusion::at_c<1>((*this)[*it.first]); - std::vector& nep = fusion::at_c<1>((*this)[e]); + std::vector& ep = fusion::at_c<1> ((*this) [*it.first]); + std::vector& nep = fusion::at_c<1> ((*this) [e]); nep.insert(nep.end(), ep.begin(), ep.end()); } } /* Create new Vertex in Cluster and map the edge to vertices and clusters in the cluster * if a connection existed */ - LocalVertex nv= boost::add_vertex((*this)[v], *cg); + LocalVertex nv = boost::add_vertex((*this) [v], *cg); + //resort cluster parentship if needed if(isCluster(v)) { @@ -1286,8 +1660,10 @@ public: } std::pair moveedge = boost::edge(v, Cluster, *this); + if(moveedge.second) { - std::vector& vec = fusion::at_c<1>((*this)[moveedge.first]); + std::vector& vec = fusion::at_c<1> ((*this) [moveedge.first]); + for(edge_single_iterator i = vec.begin(); i != vec.end(); i++) { //get the global vertex to which the global edge points and find the local vertex holding this @@ -1302,12 +1678,14 @@ public: //get or create the edge between the new vertex and the target LocalEdge e; 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); + 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) TODO: throw //push the global edge to the local edge - fusion::at_c<1>((*cg)[e]).push_back(*i); + fusion::at_c<1> ((*cg) [e]).push_back(*i); }; } @@ -1341,8 +1719,9 @@ public: //if(isRoot()) TODO:throw //create new vertex - vertex_bundle& vb = (*this)[v]; + vertex_bundle& vb = (*this) [v]; LocalVertex nv = boost::add_vertex(vb, *parent()); + //regrouping if needed if(isCluster(v)) { parent()->m_clusters[nv] = m_clusters[v]; @@ -1350,20 +1729,23 @@ public: m_clusters.erase(v); } - GlobalVertex gv= fusion::at_c<0>(vb); + GlobalVertex gv = fusion::at_c<0> (vb); //get all out_edges of this cluster in the parentcluster (because only they can hold relevant global_Edgs) std::vector edge_vec; LocalVertex this_v = parent()->getClusterVertex(sp_base::shared_from_this()); std::pair it = boost::out_edges(this_v, *parent()); + for(; it.first != it.second; it.first++) { //iterate all global edges and find relevant ones - std::vector& vec = fusion::at_c<1>((*parent())[*it.first]); + std::vector& vec = fusion::at_c<1> ((*parent()) [*it.first]); edge_single_iterator i = vec.begin(); + while(i != vec.end()) { GlobalEdge global = global_extractor()(*i); 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; @@ -1377,14 +1759,17 @@ public: //get or create the edge between the new vertex and the target LocalEdge e; 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()); + 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) TODO: throw //push the global edge bundle to the new local edge and erase it in the old - fusion::at_c<1>((*parent())[e]).push_back(*i); + fusion::at_c<1> ((*parent()) [e]).push_back(*i); i = vec.erase(i); } + //see if we should destroy this edge (no global edges remain in local one) if(vec.empty()) edge_vec.push_back(*it.first); } @@ -1392,10 +1777,12 @@ public: //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; + for(; it.first != it.second; it.first++) { - std::vector& ep = fusion::at_c<1>((*this)[*it.first]); - std::vector& nep = fusion::at_c<1>((*parent())[e]); + std::vector& ep = fusion::at_c<1> ((*this) [*it.first]); + std::vector& nep = fusion::at_c<1> ((*parent()) [e]); nep.insert(nep.end(), ep.begin(), ep.end()); } @@ -1405,7 +1792,7 @@ public: boost::remove_vertex(v, *this); //it's possible that some local edges in the parent are empty now, let's destroy them - for(std::vector::iterator it=edge_vec.begin(); it!=edge_vec.end(); it++) + for(std::vector::iterator it = edge_vec.begin(); it != edge_vec.end(); it++) boost::remove_edge(*it, *parent()); setChanged(); @@ -1424,7 +1811,7 @@ protected: boost::weak_ptr m_parent; details::IDpointer m_id; bool copy_mode; //no changing itself when copying - + /* Searches the global vertex in all local vertices of this graph, and returns the local * one which holds the global vertex. If not successfull the local vertex returned will be @@ -1436,8 +1823,9 @@ protected: //check all vertices if they are the id std::pair it = boost::vertices(*this); + for(; it.first != it.second; it.first++) { - if(id == fusion::at_c<0>((*this)[*it.first])) + if(id == fusion::at_c<0> ((*this) [*it.first])) return std::make_pair(*it.first, true); } @@ -1445,11 +1833,12 @@ protected: if(recursive) { 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); } } - return std::make_pair((LocalVertex)NULL, false); + return std::make_pair((LocalVertex) NULL, false); }; /* Searches the local vertex holding the specified global one in this and all it's subclusters. @@ -1460,27 +1849,28 @@ protected: LocalVertex v; bool done; boost::tie(v, done) = getContainingVertex(id); + 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 * one which holds the global edge. If not successfull the local edge returned will be * invalid and the bool parameter will be false. * */ std::pair getContainingEdge(GlobalEdge id) { - LocalVertex v1,v2; - bool d1,d2; - boost::tie(v1,d1) = getContainingVertex(id.source, true); - boost::tie(v2,d2) = getContainingVertex(id.target, true); + LocalVertex v1, v2; + bool d1, d2; + 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); + return boost::edge(v1, v2, *this); }; /* Searches the local edge holding the specified global one in this and all it's subclusters. @@ -1488,25 +1878,26 @@ protected: * */ fusion::vector getContainingEdgeGraph(GlobalEdge id) { - LocalVertex v1,v2; - bool d1,d2; - boost::tie(v1,d1) = getContainingVertex(id.source, true); - boost::tie(v2,d2) = getContainingVertex(id.target, true); + LocalVertex v1, v2; + bool d1, d2; + 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(v1==v2) return m_clusters[v1]->getContainingEdgeGraph(id); + if(!(d1 && d2)) return fusion::make_vector(LocalEdge(), (ClusterGraph*) NULL, false); - return fusion::make_vector(boost::edge(v1,v2,*this).first, this, true); + if(v1 == v2) return m_clusters[v1]->getContainingEdgeGraph(id); + + return fusion::make_vector(boost::edge(v1, v2, *this).first, this, true); }; template typename functor::result_type apply_to_bundle(LocalVertex k, functor f) { - return f((*this)[k]); + return f((*this) [k]); }; template typename functor::result_type apply_to_bundle(LocalEdge k, functor f) { - return f((*this)[k]); + return f((*this) [k]); }; template @@ -1514,51 +1905,58 @@ protected: //check all vertices if they are the id std::pair it = boost::vertices(*this); + for(; it.first != it.second; it.first++) { - vertex_bundle& p = (*this)[*it.first]; - if(k == fusion::at_c<0>(p)) + vertex_bundle& p = (*this) [*it.first]; + + if(k == fusion::at_c<0> (p)) return f(p); } //check all clusters if they have the object fusion::vector, bool> res = getContainingVertexGraph(k); - if(!fusion::at_c<2>(res)) { + + if(!fusion::at_c<2> (res)) { //TODO: Throw (propeties return reference, but cant init a reference temporarily) } - return fusion::at_c<1>(res)->template apply_to_bundle(k, f); + return fusion::at_c<1> (res)->template apply_to_bundle (k, f); }; template typename functor::result_type apply_to_bundle(GlobalEdge k, functor f) { - LocalVertex v1,v2; - bool d1,d2; - boost::tie(v1,d1) = getContainingVertex(k.source); - boost::tie(v2,d2) = getContainingVertex(k.target); + LocalVertex v1, v2; + bool d1, d2; + boost::tie(v1, d1) = getContainingVertex(k.source); + boost::tie(v2, d2) = getContainingVertex(k.target); - if(!(d1&&d2)) { + if(!(d1 && d2)) { //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; - boost::tie(e, done) = boost::edge(v1,v2,*this); + boost::tie(e, done) = boost::edge(v1, v2, *this); //if(!done) TODO: throw, as there has to be a edge! - return f((*this)[e]); + return f((*this) [e]); }; }; public: - //may hold cluster properties which have Eigen3 objects and therefore need alignment - EIGEN_MAKE_ALIGNED_OPERATOR_NEW + //may hold cluster properties which have Eigen3 objects and therefore need alignment + EIGEN_MAKE_ALIGNED_OPERATOR_NEW }; -} //namespace solver +/** @} */ +/** @} */ + +} //namespace dcm + #endif // CLUSTERGRAPH_HPP diff --git a/src/Mod/Assembly/App/opendcm/core/constraint.hpp b/src/Mod/Assembly/App/opendcm/core/constraint.hpp index 961b6a3cb..7d162823b 100644 --- a/src/Mod/Assembly/App/opendcm/core/constraint.hpp +++ b/src/Mod/Assembly/App/opendcm/core/constraint.hpp @@ -44,10 +44,12 @@ #include #include +#include + #include "traits.hpp" #include "object.hpp" #include "equations.hpp" -#include +#include "geometry.hpp" class T; namespace mpl = boost::mpl; @@ -58,30 +60,59 @@ namespace dcm { namespace detail { //type erasure container for constraints -template -class Constraint : public Object { +template +class Constraint { - typedef typename system_traits::Kernel Kernel; + typedef typename Sys::Kernel Kernel; typedef typename Kernel::number_type Scalar; typedef typename Kernel::DynStride DS; + typedef typename Kernel::MappedEquationSystem MES; - typedef boost::shared_ptr geom_ptr; + typedef boost::shared_ptr > geom_ptr; typedef std::vector > Vec; + //metafunction to create equation from consraint and tags + template + struct equation { + typedef typename C::template type type; + }; + public: - Constraint(Sys& system, geom_ptr f, geom_ptr s); + Constraint(geom_ptr f, geom_ptr s); ~Constraint(); - virtual boost::shared_ptr clone(Sys& newSys); + //workaround until better analysing class is created + // TODO: remove diasable once analyser is available + void disable() { + content->disable(); + }; + std::vector getGenericEquations(); std::vector getGenericConstraints(); std::vector getEquationTypes(); std::vector getConstraintTypes(); + template + void initializeFromTags(ConstraintVector& obj); template void initialize(ConstraintVector& obj); protected: + //initialising from geometry functions + template + void initializeFirstGeometry(ConstraintVector& cv, boost::mpl::false_); + template + void initializeFirstGeometry(ConstraintVector& cv, boost::mpl::true_); + template + void initializeSecondGeometry(ConstraintVector& cv, boost::mpl::false_); + template + void initializeSecondGeometry(ConstraintVector& cv, boost::mpl::true_); + template + inline void intitalizeFinalize(ConstraintVector& cv, boost::mpl::false_); + template + inline void intitalizeFinalize(ConstraintVector& cv, boost::mpl::true_); + + int equationCount(); template< typename creator_type> @@ -105,14 +136,14 @@ protected: struct EquationSet { EquationSet() : m_diff_first(NULL,0,DS(0,0)), m_diff_first_rot(NULL,0,DS(0,0)), m_diff_second(NULL,0,DS(0,0)), m_diff_second_rot(NULL,0,DS(0,0)), - m_residual(NULL,0,DS(0,0)) {}; + m_residual(NULL,0,DS(0,0)), enabled(true) {}; Equation m_eq; typename Kernel::VectorMap m_diff_first, m_diff_first_rot; //first geometry diff typename Kernel::VectorMap m_diff_second, m_diff_second_rot; //second geometry diff typename Kernel::VectorMap m_residual; - bool pure_rotation; + bool pure_rotation, enabled; typedef Equation eq_type; }; @@ -125,6 +156,7 @@ protected: virtual int equationCount() = 0; virtual void setMaps(MES& mes, geom_ptr first, geom_ptr second) = 0; virtual void collectPseudoPoints(geom_ptr first, geom_ptr second, Vec& vec1, Vec& vec2) = 0; + virtual void disable() = 0; virtual placeholder* clone() = 0; //some runtime type infos are needed, as we cant access the contents with arbitrary functors @@ -133,6 +165,7 @@ protected: virtual std::vector getEquationTypes() = 0; virtual std::vector getConstraintTypes() = 0; }; + int value; public: template< typename ConstraintVector, typename EquationVector> @@ -215,6 +248,27 @@ public: void operator()(T& val) const; }; + + struct EquationCounter { + int& count; + + EquationCounter(int& c) : count(c) {}; + + template< typename T > + void operator()(T& val) const { + if(val.enabled) + count++; + }; + }; + + //workaround until we have a better analyser class + struct disabler { + template + void operator()(T& val) const { + val.enabled = false; + }; + }; + struct GenericEquations { std::vector& vec; GenericEquations(std::vector& v); @@ -248,8 +302,9 @@ public: virtual void setMaps(MES& mes, geom_ptr first, geom_ptr second); virtual void collectPseudoPoints(geom_ptr f, geom_ptr s, Vec& vec1, Vec& vec2); virtual placeholder* clone(); - virtual int equationCount() { - return mpl::size::value; + virtual int equationCount(); + virtual void disable() { + fusion::for_each(m_sets, disabler()); }; virtual std::vector getGenericEquations(); @@ -259,27 +314,8 @@ public: EquationSets m_sets; Objects m_objects; - }; - -protected: - template< typename ConstraintVector > - struct creator : public boost::static_visitor { - - typedef ConstraintVector Objects; - Objects& objects; - - creator(Objects& obj); - - template - struct equation { - typedef typename C::template type type; - }; - - template - void operator()(const T1&, const T2&); - - placeholder* p; - bool need_swap; + protected: + void for_each(EquationSets m_sets, Calculater Calculater); }; placeholder* content; @@ -295,121 +331,111 @@ public: /*****************************************************************************************************************/ -template -Constraint::Constraint(Sys& system, geom_ptr f, geom_ptr s) +template +Constraint::Constraint(geom_ptr f, geom_ptr s) : first(f), second(s), content(0) { - this->m_system = &system; //cf = first->template connectSignal (boost::bind(&Constraint::geometryReset, this, _1)); //cs = second->template connectSignal (boost::bind(&Constraint::geometryReset, this, _1)); }; -template -Constraint::~Constraint() { +template +Constraint::~Constraint() { delete content; //first->template disconnectSignal(cf); //second->template disconnectSignal(cs); }; -template -boost::shared_ptr Constraint::clone(Sys& newSys) { +template +template +void Constraint::initializeFromTags(ConstraintVector& v) { - //copy the standart stuff - boost::shared_ptr np = boost::shared_ptr(new Derived(*static_cast(this))); - np->m_system = &newSys; - //copy the internals - np->content = content->clone(); - //and get the geometry pointers right - if(first) { - GlobalVertex v = first->template getProperty(); - np->first = newSys.m_cluster->template getObject(v); - } - if(second) { - GlobalVertex v = second->template getProperty(); - np->second = newSys.m_cluster->template getObject(v); - } - return np; -}; + typedef tag_order< tag1, tag2 > order; -template -template -void Constraint::initialize(ConstraintVector& obj) { + //transform the constraints into eqautions with the now known types + typedef typename mpl::fold< ConstraintVector, mpl::vector<>, + mpl::push_back > >::type EquationVector; - //first create the new placeholder - creator c(obj); - boost::apply_visitor(c, first->m_geometry, second->m_geometry); + //and build the placeholder + content = new holder(v); - //and now store it - content = c.p; //geometry order needs to be the one needed by equations - if(c.need_swap) + if(order::swapt::value) first.swap(second); - }; -template -int Constraint::equationCount() { +template +template +void Constraint::initialize(ConstraintVector& cv) { + + //use the compile time unrolling to retrieve the geometry tags + initializeFirstGeometry, ConstraintVector>(cv, mpl::true_()); +}; + +template +int Constraint::equationCount() { return content->equationCount(); }; -template +template template< typename creator_type> -void Constraint::resetType(creator_type& c) { +void Constraint::resetType(creator_type& c) { boost::apply_visitor(c, first->m_geometry, second->m_geometry); content = c.p; if(c.need_swap) first.swap(second); }; -template -void Constraint::calculate(Scalar scale, bool rotation_only) { +template +void Constraint::calculate(Scalar scale, bool rotation_only) { content->calculate(first, second, scale, rotation_only); }; -template -void Constraint::treatLGZ() { +template +void Constraint::treatLGZ() { content->treatLGZ(first, second); }; -template -void Constraint::setMaps(MES& mes) { +template +void Constraint::setMaps(MES& mes) { content->setMaps(mes, first, second); }; -template -void Constraint::collectPseudoPoints(Vec& vec1, Vec& vec2) { +template +void Constraint::collectPseudoPoints(Vec& vec1, Vec& vec2) { content->collectPseudoPoints(first, second, vec1, vec2); }; -template -std::vector Constraint::getGenericEquations() { +template +std::vector Constraint::getGenericEquations() { return content->getGenericEquations(); }; -template -std::vector Constraint::getGenericConstraints() { +template +std::vector Constraint::getGenericConstraints() { return content->getGenericConstraints(); }; -template -std::vector Constraint::getEquationTypes() { +template +std::vector Constraint::getEquationTypes() { return content->getEquationTypes(); }; -template -std::vector Constraint::getConstraintTypes() { +template +std::vector Constraint::getConstraintTypes() { return content->getConstraintTypes(); }; -template +template template -Constraint::holder::OptionSetter::OptionSetter(Objects& val) : objects(val) {}; +Constraint::holder::OptionSetter::OptionSetter(Objects& val) : objects(val) {}; -template +template template template -typename boost::enable_if::template holder::template has_option::type, void>::type -Constraint::holder::OptionSetter::operator()(EquationSet& val) const { +typename boost::enable_if::template holder::template has_option::type, void>::type +Constraint::holder::OptionSetter::operator()(EquationSet& val) const { //get the index of the corresbonding equation typedef typename mpl::find::type iterator; @@ -419,25 +445,29 @@ Constraint::holder(objects).pure_rotation; }; -template +template template template -typename boost::enable_if::template holder::template has_option::type>, void>::type -Constraint::holder::OptionSetter::operator()(EquationSet& val) const { +typename boost::enable_if::template holder::template has_option::type>, void>::type +Constraint::holder::OptionSetter::operator()(EquationSet& val) const { }; -template +template template -Constraint::holder::Calculater::Calculater(geom_ptr f, geom_ptr s, Scalar sc, bool rotation_only) +Constraint::holder::Calculater::Calculater(geom_ptr f, geom_ptr s, Scalar sc, bool rotation_only) : first(f), second(s), scale(sc), rot_only(rotation_only) { }; -template +template template template< typename T > -void Constraint::holder::Calculater::operator()(T& val) const { +void Constraint::holder::Calculater::operator()(T& val) const { + + //if the equation is disabled we don't have anything mapped so avoid accessing it + if(!val.enabled) + return; //if we only need pure rotational functions and we are not such a nice thing, everything becomes 0 if(rot_only && !val.pure_rotation) { @@ -520,17 +550,20 @@ void Constraint::holder +template template -Constraint::holder::MapSetter::MapSetter(MES& m, geom_ptr f, geom_ptr s) +Constraint::holder::MapSetter::MapSetter(MES& m, geom_ptr f, geom_ptr s) : mes(m), first(f), second(s) { }; -template +template template template< typename T > -void Constraint::holder::MapSetter::operator()(T& val) const { +void Constraint::holder::MapSetter::operator()(T& val) const { + + if(!val.enabled) + return; //when in cluster, there are 6 clusterparameter we differentiat for, if not we differentiat //for every parameter in the geometry; @@ -555,17 +588,21 @@ void Constraint::holderm_offset, second->m_parameterCount, val.m_diff_second); }; -template +template template -Constraint::holder::PseudoCollector::PseudoCollector(geom_ptr f, geom_ptr s, Vec& vec1, Vec& vec2) +Constraint::holder::PseudoCollector::PseudoCollector(geom_ptr f, geom_ptr s, Vec& vec1, Vec& vec2) : first(f), second(s), points1(vec1), points2(vec2) { }; -template +template template template< typename T > -void Constraint::holder::PseudoCollector::operator()(T& val) const { +void Constraint::holder::PseudoCollector::operator()(T& val) const { + + if(!val.enabled) + return; + if(first->m_isInCluster && second->m_isInCluster) { val.m_eq.calculatePseudo(first->m_rotated, points1, second->m_rotated, points2); } @@ -581,21 +618,23 @@ void Constraint::holder +template template -Constraint::holder::LGZ::LGZ(geom_ptr f, geom_ptr s) +Constraint::holder::LGZ::LGZ(geom_ptr f, geom_ptr s) : first(f), second(s) { }; -template +template template template< typename T > -void Constraint::holder::LGZ::operator()(T& val) const { +void Constraint::holder::LGZ::operator()(T& val) const { + if(!val.enabled) + return; + //to treat local gradient zeros we calculate a approximate second derivative of the equations //only do that if neseccary: residual is not zero - Base::Console().Message("res: %f\n", val.m_residual(0)); if(val.m_residual(0) > 1e-7) { //TODO: use exact precission and scale value //rotations exist only in cluster @@ -604,19 +643,19 @@ void Constraint::holderm_parameter + first->m_diffparam.col(i)*1e-3; + const typename Kernel::Vector p_old = first->m_parameter; + first->m_parameter += first->m_diffparam.col(i)*1e-3; + first->normalize(); //with this changed geometrie we test if a gradient exist now typename Kernel::VectorMap block(&first->m_diffparam(0,i),first->m_parameterCount,1, DS(1,1)); - typename Kernel::VectorMap block2(&incr(0),first->m_parameterCount,1, DS(1,1)); - typename Kernel::number_type res = val.m_eq.calculateGradientFirst(block2, + typename Kernel::number_type res = val.m_eq.calculateGradientFirst(first->m_parameter, second->m_parameter, block); - + first->m_parameter = p_old; + //let's see if the initial LGZ was a real one - Base::Console().Message("approx second: %f\n", res); if(std::abs(res) > 1e-7) { //is a fake zero, let's correct it @@ -631,19 +670,19 @@ void Constraint::holderm_parameter + second->m_diffparam.col(i)*1e-3; + const typename Kernel::Vector p_old = second->m_parameter; + second->m_parameter += second->m_diffparam.col(i)*1e-3; + second->normalize(); //with this changed geometrie we test if a gradient exist now typename Kernel::VectorMap block(&second->m_diffparam(0,i),second->m_parameterCount,1, DS(1,1)); - typename Kernel::VectorMap block2(&incr(0),second->m_parameterCount,1, DS(1,1)); - typename Kernel::number_type res = val.m_eq.calculateGradientFirst(block2, + typename Kernel::number_type res = val.m_eq.calculateGradientFirst(first->m_parameter, second->m_parameter, block); + second->m_parameter = p_old; //let's see if the initial LGZ was a real one - Base::Console().Message("approx second: %f\n", res); if(std::abs(res) > 1e-7) { //is a fake zero, let's correct it @@ -655,155 +694,226 @@ void Constraint::holder +template template -Constraint::holder::GenericEquations::GenericEquations(std::vector& v) +Constraint::holder::GenericEquations::GenericEquations(std::vector& v) : vec(v) { }; -template +template template template< typename T > -void Constraint::holder::GenericEquations::operator()(T& val) const { +void Constraint::holder::GenericEquations::operator()(T& val) const { vec.push_back(val.m_eq); }; -template +template template -Constraint::holder::GenericConstraints::GenericConstraints(std::vector& v) +Constraint::holder::GenericConstraints::GenericConstraints(std::vector& v) : vec(v) { }; -template +template template template< typename T > -void Constraint::holder::GenericConstraints::operator()(T& val) const { +void Constraint::holder::GenericConstraints::operator()(T& val) const { vec.push_back(val); }; -template +template template -Constraint::holder::Types::Types(std::vector& v) +Constraint::holder::Types::Types(std::vector& v) : vec(v) { }; -template +template template template< typename T > -void Constraint::holder::Types::operator()(T& val) const { +void Constraint::holder::Types::operator()(T& val) const { vec.push_back(&typeid(T)); }; -template +template template -Constraint::holder::holder(Objects& obj) : m_objects(obj) { +Constraint::holder::holder(Objects& obj) : m_objects(obj) { //set the initial values in the equations fusion::for_each(m_sets, OptionSetter(obj)); }; -template +template template -void Constraint::holder::calculate(geom_ptr first, geom_ptr second, +void Constraint::holder::calculate(geom_ptr first, geom_ptr second, Scalar scale, bool rotation_only) { fusion::for_each(m_sets, Calculater(first, second, scale, rotation_only)); }; -template +template template -void Constraint::holder::treatLGZ(geom_ptr first, geom_ptr second) { +void Constraint::holder::treatLGZ(geom_ptr first, geom_ptr second) { fusion::for_each(m_sets, LGZ(first, second)); }; -template +template template -typename Constraint::placeholder* -Constraint::holder::resetConstraint(geom_ptr first, geom_ptr second) const { +typename Constraint::placeholder* +Constraint::holder::resetConstraint(geom_ptr first, geom_ptr second) const { //boost::apply_visitor(creator, first->m_geometry, second->m_geometry); //if(creator.need_swap) first.swap(second); return NULL; }; -template +template template -void Constraint::holder::setMaps(MES& mes, geom_ptr first, geom_ptr second) { +void Constraint::holder::setMaps(MES& mes, geom_ptr first, geom_ptr second) { fusion::for_each(m_sets, MapSetter(mes, first, second)); }; -template +template template -void Constraint::holder::collectPseudoPoints(geom_ptr f, geom_ptr s, Vec& vec1, Vec& vec2) { +void Constraint::holder::collectPseudoPoints(geom_ptr f, geom_ptr s, Vec& vec1, Vec& vec2) { fusion::for_each(m_sets, PseudoCollector(f, s, vec1, vec2)); }; -template +template template -typename Constraint::placeholder* -Constraint::holder::clone() { +typename Constraint::placeholder* +Constraint::holder::clone() { return new holder(*this); }; -template +template +template +int Constraint::holder::equationCount() { + int count = 0; + EquationCounter counter(count); + fusion::for_each(m_sets, counter); + return count; +}; + +template template std::vector -Constraint::holder::getGenericEquations() { +Constraint::holder::getGenericEquations() { std::vector vec; fusion::for_each(m_sets, GenericEquations(vec)); return vec; }; -template +template template std::vector -Constraint::holder::getGenericConstraints() { +Constraint::holder::getGenericConstraints() { std::vector vec; fusion::for_each(m_objects, GenericConstraints(vec)); return vec; }; -template +template template std::vector -Constraint::holder::getEquationTypes() { +Constraint::holder::getEquationTypes() { std::vector vec; mpl::for_each< EquationVector >(Types(vec)); return vec; }; -template +template template std::vector -Constraint::holder::getConstraintTypes() { +Constraint::holder::getConstraintTypes() { std::vector vec; mpl::for_each< ConstraintVector >(Types(vec)); return vec; }; -template -template< typename ConstraintVector > -Constraint::creator::creator(Objects& obj) : objects(obj) { +/****************************************************************/ +/** compiletime unrolled geometry initialising */ +/****************************************************************/ +template +template +void Constraint::initializeFirstGeometry(ConstraintVector& cv, boost::mpl::false_ /*unrolled*/) { + //this function is only for breaking the compilation loop, it should never be called + BOOST_ASSERT(false); //Should never assert here; only meant to stop recursion at the end of the typelist }; -template -template< typename ConstraintVector > -template -void Constraint::creator::operator()(const T1&, const T2&) { +template +template +void Constraint::initializeFirstGeometry(ConstraintVector& cv, boost::mpl::true_ /*unrolled*/) { - typedef tag_order< typename geometry_traits::tag, typename geometry_traits::tag > order; + typedef typename Sys::geometries geometries; + + switch(first->getExactType()) { - //transform the constraints into eqautions with the now known types - typedef typename mpl::fold< ConstraintVector, mpl::vector<>, - mpl::push_back > >::type EquationVector; - - //and build the placeholder - p = new holder(objects); - need_swap = order::swapt::value; +#ifdef BOOST_PP_LOCAL_ITERATE +#define BOOST_PP_LOCAL_MACRO(n) \ + case (WhichType::value + n): \ + return initializeSecondGeometry,\ + typename mpl::at_c::type,\ + ConstraintVector>(cv, typename boost::mpl::less, boost::mpl::size >::type()); \ + break; +#define BOOST_PP_LOCAL_LIMITS (0, 10) +#include BOOST_PP_LOCAL_ITERATE() +#endif //BOOST_PP_LOCAL_ITERATE + default: + typedef typename mpl::int_ next_which_t; + return initializeFirstGeometry (cv, + typename mpl::less< next_which_t, typename mpl::size::type >::type()); + } }; +template +template +void Constraint::initializeSecondGeometry(ConstraintVector& cv, boost::mpl::false_ /*unrolled*/) { + //this function is only for breaking the compilation loop, it should never be called + BOOST_ASSERT(false); //Should never assert here; only meant to stop recursion at the end of the typelist +}; + +template +template +void Constraint::initializeSecondGeometry(ConstraintVector& cv, boost::mpl::true_ /*unrolled*/) { + + typedef typename Sys::geometries geometries; + switch(second->getExactType()) { + +#ifdef BOOST_PP_LOCAL_ITERATE +#define BOOST_PP_LOCAL_MACRO(n) \ + case (WhichType::value + n): \ + return intitalizeFinalize::type,\ + ConstraintVector>(cv, typename boost::mpl::less, boost::mpl::size >::type()); \ + break; +#define BOOST_PP_LOCAL_LIMITS (0, 10) +#include BOOST_PP_LOCAL_ITERATE() +#endif //BOOST_PP_LOCAL_ITERATE + default: + typedef typename mpl::int_ next_which_t; + return initializeSecondGeometry + (cv, typename mpl::less + < next_which_t + , typename mpl::size::type>::type() + ); + } +}; + +template +template +inline void Constraint::intitalizeFinalize(ConstraintVector& cv, boost::mpl::true_ /*is_unrolled_t*/) { + + initializeFromTags(cv); +}; + +template +template +inline void Constraint::intitalizeFinalize(ConstraintVector& cv, boost::mpl::false_ /*is_unrolled_t*/) { + //Should never be here at runtime; only required to block code generation that deref's the sequence out of bounds + BOOST_ASSERT(false); +} + + };//detail @@ -811,3 +921,5 @@ void Constraint::creator #endif //GCM_CONSTRAINT_H + + diff --git a/src/Mod/Assembly/App/opendcm/core/equations.hpp b/src/Mod/Assembly/App/opendcm/core/equations.hpp index 09c12d0b7..6484b67b3 100644 --- a/src/Mod/Assembly/App/opendcm/core/equations.hpp +++ b/src/Mod/Assembly/App/opendcm/core/equations.hpp @@ -44,11 +44,6 @@ namespace mpl = boost::mpl; namespace dcm { -//a few exceptions to handle unsupported combinations -struct constraint_error : virtual boost::exception { }; -typedef boost::error_info error_type_first_geometry; -typedef boost::error_info error_type_second_geometry; - struct no_option {}; template diff --git a/src/Mod/Assembly/App/opendcm/core/geometry.hpp b/src/Mod/Assembly/App/opendcm/core/geometry.hpp index a8c5d6746..4a145cfce 100644 --- a/src/Mod/Assembly/App/opendcm/core/geometry.hpp +++ b/src/Mod/Assembly/App/opendcm/core/geometry.hpp @@ -33,7 +33,9 @@ #include #include #include -#include +#include +#include +#include #include #include @@ -43,7 +45,6 @@ #include -#include "object.hpp" #include "traits.hpp" #include "logging.hpp" #include "transformation.hpp" @@ -53,6 +54,9 @@ namespace fusion = boost::fusion; namespace dcm { +//signal we use for recalculation +struct recalculated {}; + namespace tag { struct undefined { @@ -62,13 +66,73 @@ struct undefined { //we need to order tags, this values make it easy for module tags namespace weight { -struct direction : mpl::int_<0> {}; -struct point : mpl::int_<1> {}; -struct line : mpl::int_<2> {}; -struct plane : mpl::int_<3> {}; -struct cylinder : mpl::int_<4> {}; -} +struct parameter : mpl::int_<0> {}; +struct direction : mpl::int_<1> {}; +struct point : mpl::int_<2> {}; +struct line : mpl::int_<3> {}; +struct segment : mpl::int_<4> {}; +struct circle : mpl::int_<5> {}; +struct arc : mpl::int_<6> {}; +struct ellipse : mpl::int_<7> {}; +struct elliptical_arc : mpl::int_<8> {}; +struct plane : mpl::int_<9> {}; +struct cylinder : mpl::int_<10> {}; } +} // tag + +namespace details { + +struct bg {}; //struct to allow test for basic geometry + +template< typename weight_type, int params, bool rotatable, bool translatable> +struct basic_geometry : public bg { + + typedef mpl::int_ parameters; + typedef typename mpl::if_c, mpl::int_<0> >::type translations; + typedef typename mpl::if_c, mpl::int_<0> >::type rotations; + typedef weight_type weight; + typedef mpl::vector0<> sub_stack; +}; + +//build up stacked geometry. these are geometrys which can be splitted into multiple basic geometries. For +//example lines can be splittet into a point and a direction. Make sure you order the basic geometry in a +//sensible rotation/translation manner. Remember: geometrie is first rotated, than translated. Therefore +//everything that gets rotated and translated needs to be first, than the rotation only stuff, then the +//untransformed. For a line this would be +template +struct stacked2_geometry { + + //be sure we only stack base geometrys + BOOST_MPL_ASSERT((boost::is_base_of< bg, T1 >)); + BOOST_MPL_ASSERT((boost::is_base_of< bg, T2 >)); + + typedef typename mpl::plus::type parameters; + typedef typename mpl::plus::type rotations; + typedef typename mpl::plus::type translations; + typedef weight_type weight; + typedef mpl::vector2 sub_stack; +}; + +template +struct stacked3_geometry { + + //be sure we only stack base geometrys + BOOST_MPL_ASSERT((boost::is_base_of< bg, T1 >)); + BOOST_MPL_ASSERT((boost::is_base_of< bg, T2 >)); + BOOST_MPL_ASSERT((boost::is_base_of< bg, T3 >)); + + typedef typename mpl::plus::type parameters; + typedef typename mpl::plus::type rotations; + typedef typename mpl::plus::type translations; + typedef weight_type weight; + typedef mpl::vector3 sub_stack; +}; +} //details + +namespace tag { +//a parameter is universal, so let's define it here +struct parameter : details::basic_geometry {}; +} //tag struct orderd_bracket_accessor { @@ -124,41 +188,26 @@ struct geometry_clone_traits { }; }; -struct reset {}; //signal namespace +namespace details { -namespace detail { +// the parameter a geometr needs in a mapped equation system need to be managed seperate, as +// we may want to access the same parameter space from different geometries (if they are linked) +// this is done by the parameter space class +template +struct parameter_space { -template< typename Sys, typename Derived, typename GeometrieTypeList, int Dim> -class Geometry : public Object) > >, - mpl::pair) > > , - mpl::pair)> > > > { + void init(typename Kernel::MappedEquationSystem* mes); - typedef mpl::map3< mpl::pair) > >, - mpl::pair) > >, - mpl::pair)> > > Signals; +}; + +template > +class Geometry { - typedef typename boost::make_variant_over< GeometrieTypeList >::type Variant; - typedef Object Base; - typedef typename system_traits::Kernel Kernel; - typedef typename system_traits::Cluster Cluster; typedef typename Kernel::number_type Scalar; typedef typename Kernel::DynStride DS; typedef typename Kernel::template transform_type::type Transform; typedef typename Kernel::template transform_type::diff_type DiffTransform; - struct cloner : boost::static_visitor { - typedef typename boost::make_variant_over< GeometrieTypeList >::type Variant; - - Variant variant; - cloner(Variant& v) : variant(v) {}; - - template - void operator()(T& t) { - variant = geometry_clone_traits()(t); - }; - }; - #ifdef USE_LOGGING protected: src::logger log; @@ -167,23 +216,26 @@ protected: public: typedef mpl::int_ Dimension; - Geometry(Sys& system); - - template - Geometry(const T& geometry, Sys& system); + Geometry(); - template - void set(const T& geometry); - - template - typename Visitor::result_type apply(Visitor& vis) { - return boost::apply_visitor(vis, m_geometry); + //basic ations + template + void setValue(const Eigen::MatrixBase& t) { + init(); + m_global = t; + }; + typename Kernel::Vector& getValue() { + return m_global; }; - - //basic ation void transform(const Transform& t); - virtual boost::shared_ptr clone(Sys& newSys); + int getGeneralType() { + return m_general_type; + }; + + int getExactType() { + return m_exact_type; + }; //allow accessing the internal values in unittests without making them public, //so that access control of the internal classes is not changed and can be tested @@ -212,12 +264,19 @@ public: int parameterCount() { return m_parameterCount; }; + template + void test_linkTo(boost::shared_ptr< Geometry< Kernel, Dim > > geom, int offset) { + linkTo(geom, offset); + }; + bool test_isLinked() { + return isLinked(); + }; #endif //protected would be the right way, however, visual studio 10 does not find a way to access them even when constraint::holder structs //are declared friend //protected: - Variant m_geometry; //Variant holding the real geometry type + int m_general_type, m_exact_type; //hold the type numbers for easy identification int m_BaseParameterCount; //count of the parameters the variant geometry type needs int m_parameterCount; //count of the used parameters (when in cluster:6, else m_BaseParameterCount) int m_offset, m_offset_rot; //the starting point of our parameters in the math system parameter vector @@ -230,13 +289,16 @@ public: typename Kernel::Matrix m_diffparam; //gradient vectors combined as matrix when in cluster typename Kernel::VectorMap m_parameter; //map to the parameters in the solver - template - void init(const T& t); + template + void init(); void normalize(); - typename Sys::Kernel::VectorMap& getParameterMap(); - void initMap(); + typename Kernel::VectorMap& getParameterMap(); + void initMap(typename Kernel::MappedEquationSystem* mes); + bool isInitialised() { + return m_init; + }; void setClusterMode(bool iscluster, bool isFixed); bool getClusterMode() { @@ -246,30 +308,32 @@ public: return m_clusterFixed; }; + int m_link_offset; + boost::shared_ptr > m_link; + + template + void linkTo(boost::shared_ptr< Geometry< Kernel, Dim, TagList > > geom, int offset); + bool isLinked() { + return m_link!=0; + }; + void recalculate(DiffTransform& trans); typename Kernel::Vector3 getPoint() { return m_toplocal.template segment(0); }; - //visitor to write the calculated value into the variant - struct apply_visitor : public boost::static_visitor { - - apply_visitor(typename Kernel::Vector& v) : value(v) {}; - template - void operator()(T& t) const { - (typename geometry_traits::modell()).template inject::accessor >(t, value); - } - typename Kernel::Vector& value; - }; - //use m_value or parametermap as new value, dependend on the solving mode void finishCalculation(); template void transform(const Transform& t, VectorType& vec); void scale(Scalar value); + + //let the derived class decide what happens on significant events + virtual void reset() = 0; + virtual void recalculated() = 0; + virtual void removed() = 0; }; @@ -279,71 +343,37 @@ public: /*****************************************************************************************************************/ /*****************************************************************************************************************/ -template< typename Sys, typename Derived, typename GeometrieTypeList, int Dim> -Geometry::Geometry(Sys& system) +template< typename Kernel, int Dim, typename TagList> +Geometry::Geometry() : m_isInCluster(false), m_parameter(NULL,0,DS(0,0)), m_clusterFixed(false), m_init(false) { #ifdef USE_LOGGING - log.add_attribute("Tag", attrs::constant< std::string >("Geometry3D")); + log.add_attribute("Tag", attrs::constant< std::string >("Geometry")); #endif - this->m_system = &system; }; -template< typename Sys, typename Derived, typename GeometrieTypeList, int Dim> -template -Geometry::Geometry(const T& geometry, Sys& system) - : m_isInCluster(false), m_geometry(geometry), m_parameter(NULL,0,DS(0,0)), - m_clusterFixed(false), m_init(false) { - -#ifdef USE_LOGGING - log.add_attribute("Tag", attrs::constant< std::string >("Geometry3D")); -#endif - - this->m_system = &system; - init(geometry); -}; - -template< typename Sys, typename Derived, typename GeometrieTypeList, int Dim> -template -void Geometry::set(const T& geometry) { - m_geometry = geometry; - init(geometry); - //Base::template emitSignal( ((Derived*)this)->shared_from_this() ); -}; - -template< typename Sys, typename Derived, typename GeometrieTypeList, int Dim> -void Geometry::transform(const Transform& t) { +template< typename Kernel, int Dim, typename TagList> +void Geometry::transform(const Transform& t) { if(m_isInCluster) transform(t, m_toplocal); - else if(m_init) - transform(t, m_rotated); else - transform(t, m_global); + if(m_init) + transform(t, m_rotated); + else + transform(t, m_global); }; -template -boost::shared_ptr Geometry::clone(Sys& newSys) { +template< typename Kernel, int Dim, typename TagList> +template +void Geometry::init() { - //copy the standart stuff - boost::shared_ptr np = boost::shared_ptr(new Derived(*static_cast(this))); - np->m_system = &newSys; - //it's possible that the variant contains pointers, so we need to clone them - cloner clone_fnc(np->m_geometry); - boost::apply_visitor(clone_fnc, m_geometry); - return np; -}; - -template< typename Sys, typename Derived, typename GeometrieTypeList, int Dim> -template -void Geometry::init(const T& t) { - - m_BaseParameterCount = geometry_traits::tag::parameters::value; + m_BaseParameterCount = tag::parameters::value; m_parameterCount = m_BaseParameterCount; - m_rotations = geometry_traits::tag::rotations::value; - m_translations = geometry_traits::tag::translations::value; + m_rotations = tag::rotations::value; + m_translations = tag::translations::value; m_toplocal.setZero(m_parameterCount); m_global.resize(m_parameterCount); @@ -353,8 +383,9 @@ void Geometry::init(const T& t) { m_diffparam.resize(m_parameterCount,6); m_diffparam.setZero(); - (typename geometry_traits::modell()).template extract::accessor >(t, m_global); + m_general_type = tag::weight::value; + m_exact_type = mpl::find::type::pos::value; + normalize(); //new value which is not set into parameter, so init is false @@ -366,45 +397,73 @@ void Geometry::init(const T& t) { }; -template< typename Sys, typename Derived, typename GeometrieTypeList, int Dim> -void Geometry::normalize() { +template< typename Kernel, int Dim, typename TagList> +void Geometry::normalize() { //directions are not nessessarily normalized, but we need to ensure this in cluster mode for(int i=m_translations; i!=m_rotations; i++) m_global.template segment(i*Dim).normalize(); }; -template< typename Sys, typename Derived, typename GeometrieTypeList, int Dim> -typename Sys::Kernel::VectorMap& Geometry::getParameterMap() { +template< typename Kernel, int Dim, typename TagList> +typename Kernel::VectorMap& Geometry::getParameterMap() { m_isInCluster = false; m_parameterCount = m_BaseParameterCount; return m_parameter; }; -template< typename Sys, typename Derived, typename GeometrieTypeList, int Dim> -void Geometry::initMap() { - //when direct parameter solving the global value is wanted (as it's the initial rotation*toplocal) - m_parameter = m_global; - m_init = true; +template< typename Kernel, int Dim, typename TagList> +template +void Geometry::linkTo(boost::shared_ptr > geom, int offset) { + + init(); + m_link = geom; + m_link_offset = offset; + m_global = geom->m_global.segment(offset, m_BaseParameterCount); }; -template< typename Sys, typename Derived, typename GeometrieTypeList, int Dim> -void Geometry::setClusterMode(bool iscluster, bool isFixed) { +template< typename Kernel, int Dim, typename TagList> +void Geometry::initMap(typename Kernel::MappedEquationSystem* mes) { + + //check should not be needed, but how knows... + if(!m_init) { + + if(!isLinked()) { + m_offset = mes->setParameterMap(m_parameterCount, getParameterMap()); + m_parameter = m_global; + m_init = true; + } + else { + //it's important that the linked geometry is initialised, as we going to access its parameter map + if(!m_link->isInitialised()) + m_link->initMap(mes); + + m_offset = m_link->m_offset + m_link_offset; + new(&getParameterMap()) typename Kernel::VectorMap(&m_link->getParameterMap()(m_link_offset), m_parameterCount, typename Kernel::DynStride(1,1)); + } + } +}; + +template< typename Kernel, int Dim, typename TagList> +void Geometry::setClusterMode(bool iscluster, bool isFixed) { m_isInCluster = iscluster; m_clusterFixed = isFixed; if(iscluster) { //we are in cluster, therfore the parameter map should not point to a solver value but to //the rotated original value; - new(&m_parameter) typename Sys::Kernel::VectorMap(&m_rotated(0), m_parameterCount, DS(1,1)); + new(&m_parameter) typename Kernel::VectorMap(&m_rotated(0), m_parameterCount, DS(1,1)); //the local value is the global one as no transformation was applied yet m_toplocal = m_global; m_rotated = m_global; - } else new(&m_parameter) typename Sys::Kernel::VectorMap(&m_global(0), m_parameterCount, DS(1,1)); + } + else + new(&m_parameter) typename Kernel::VectorMap(&m_global(0), m_parameterCount, DS(1,1)); }; -template< typename Sys, typename Derived, typename GeometrieTypeList, int Dim> -void Geometry::recalculate(DiffTransform& trans) { - if(!m_isInCluster) return; +template< typename Kernel, int Dim, typename TagList> +void Geometry::recalculate(DiffTransform& trans) { + if(!m_isInCluster) + return; for(int i=0; i!=m_rotations; i++) { //first rotate the original to the transformed value @@ -432,8 +491,8 @@ void Geometry::recalculate(DiffTransform& }; -template< typename Sys, typename Derived, typename GeometrieTypeList, int Dim> -void Geometry::finishCalculation() { +template< typename Kernel, int Dim, typename TagList> +void Geometry::finishCalculation() { //if fixed nothing needs to be changed if(m_isInCluster) { //recalculate(1.); //remove scaling to get right global value @@ -450,18 +509,16 @@ void Geometry::finishCalculation() { BOOST_LOG(log) << "Finish calculation"; #endif }; - apply_visitor v(m_global); - apply(v); + m_init = false; m_isInCluster = false; - - //emit the signal for recalculation - Base::template emitSignal( ((Derived*)this)->shared_from_this() ); + + recalculated(); }; -template< typename Sys, typename Derived, typename GeometrieTypeList, int Dim> +template< typename Kernel, int Dim, typename TagList> template -void Geometry::transform(const Transform& t, VectorType& vec) { +void Geometry::transform(const Transform& t, VectorType& vec) { //everything that needs to be translated needs to be fully transformed for(int i=0; i!=m_translations; i++) { @@ -480,8 +537,8 @@ void Geometry::transform(const Transform& #endif } -template< typename Sys, typename Derived, typename GeometrieTypeList, int Dim> -void Geometry::scale(Scalar value) { +template< typename Kernel, int Dim, typename TagList> +void Geometry::scale(Scalar value) { for(int i=0; i!=m_translations; i++) m_parameter.template segment(i*Dim) *= 1./value; diff --git a/src/Mod/Assembly/App/opendcm/core/kernel.hpp b/src/Mod/Assembly/App/opendcm/core/kernel.hpp index 1e738ad82..2e788f8de 100644 --- a/src/Mod/Assembly/App/opendcm/core/kernel.hpp +++ b/src/Mod/Assembly/App/opendcm/core/kernel.hpp @@ -35,6 +35,8 @@ #include "transformation.hpp" #include "logging.hpp" +#include "defines.hpp" +#include "multimap.hpp" namespace dcm { @@ -47,15 +49,11 @@ struct nothing { //the parameter types enum ParameterType { - general, - rotation, - complete + general, //every non-rotation parameter, therefore every translation and non transformed parameter + rotation, //all rotation parameters + complete //all parameter }; -//all solving related errors -typedef boost::error_info error_message; -struct solving_error : virtual boost::exception { }; - template struct Dogleg { @@ -219,7 +217,6 @@ struct Dogleg { number_type dF=0, dL=0; number_type rho; - //handle possible lgz's if(iter==0) sys.removeLocalGradientZeros(); @@ -492,7 +489,7 @@ struct Kernel { }; virtual void recalculate() = 0; - virtual void removeLocalGradientZeros() = 0; + virtual void removeLocalGradientZeros() = 0; }; @@ -530,3 +527,4 @@ struct Kernel { + diff --git a/src/Mod/Assembly/App/opendcm/core/object.hpp b/src/Mod/Assembly/App/opendcm/core/object.hpp index 3218602d8..29c70663a 100644 --- a/src/Mod/Assembly/App/opendcm/core/object.hpp +++ b/src/Mod/Assembly/App/opendcm/core/object.hpp @@ -52,6 +52,10 @@ namespace mpl = boost::mpl; 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 + * */ #define EMIT_ARGUMENTS(z, n, data) \ BOOST_PP_CAT(data, n) @@ -63,16 +67,16 @@ namespace fusion = boost::fusion; void emitSignal( \ BOOST_PP_ENUM_BINARY_PARAMS(n, Arg, const& arg) \ ); - + #define EMIT_CALL_DEC(z, n, data) \ - template \ + template \ template < \ typename S \ BOOST_PP_ENUM_TRAILING_PARAMS(n, typename Arg) \ > \ - void Object::emitSignal( \ - BOOST_PP_ENUM_BINARY_PARAMS(n, Arg, const& arg) \ - ) \ + void SignalOwner::emitSignal( \ + BOOST_PP_ENUM_BINARY_PARAMS(n, Arg, const& arg) \ + ) \ { \ typedef typename mpl::find::type iterator; \ typedef typename mpl::distance::type, iterator>::type distance; \ @@ -84,12 +88,68 @@ namespace fusion = boost::fusion; namespace dcm { +/** @defgroup Objects Objects + * + * @brief Concept and functionality of the dcm objects + * + * + **/ + //few standart signal names struct remove {}; -struct recalculated {}; typedef boost::any Connection; +template +struct SignalOwner { + + /** + * @brief Connects a slot to a specified signal. + * + * Slots are boost::functions which get called when the signal is emitted. Any valid boost::function + * which ressembles the signal tyes signature can be registert. It is important that the signal type + * was registerd to this object on creation by the appropriate template parameter. + * + * @tparam S the signal which should be intercepted + * @param function boost::function which resembles the signal type's signature + * @return void + **/ + template + Connection connectSignal(typename mpl::at::type function); + + /** + * @brief Disconnects a slot for a specific signal. + * + * Disconnects a slot so that it dosn't get called at signal emittion. It's important to + * disconnect the slot by the same boost:function it was connected with. + * + * @tparam S the signal type of interest + * @param c connection with which the slot was initialy connected + * @return void + **/ + template + void disconnectSignal(Connection c); + + //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 + * signatures are supported for multiple signals). Create std::vectors to allow multiple slots per signal + * and store these vectors in a fusion::vector for easy access. + * */ + typedef typename mpl::fold < SigMap, mpl::vector<>, + mpl::push_back > >::type sig_name; + 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; + typedef typename fusion::result_of::as_vector::type Signals; + + Signals m_signals; +}; + /** * @brief Base class for all object types * @@ -103,7 +163,9 @@ typedef boost::any Connection; * \tparam Sig a mpl::map specifing the object's signals by (type - boost::function) pairs **/ template -struct Object : public boost::enable_shared_from_this { +struct Object : public PropertyOwner::type>, + public SignalOwner, + boost::enable_shared_from_this { Object() {}; Object(Sys& system); @@ -120,87 +182,7 @@ struct Object : public boost::enable_shared_from_this { **/ virtual boost::shared_ptr clone(Sys& newSys); - /** - * @brief Access properties - * - * Returns a reference to the propertys actual value. The property type has to be registerd to the - * System type which was given as template parameter to this object. - * @tparam Prop property type which should be accessed - * @return Prop::type& a reference to the properties actual value. - **/ - template - typename Prop::type& getProperty(); - - /** - * @brief Set properties - * - * Set'S the value of a specified property. The property type has to be registerd to the - * System type which was given as template parameter to this object. Note that setProperty(value) - * is equivalent to getProperty() = value. - * @tparam Prop property type which should be setProperty - * @param value value of type Prop::type which should be set in this object - **/ - template - void setProperty(typename Prop::type value); - - /** - * @brief Connects a slot to a specified signal. - * - * Slots are boost::functions which get called when the signal is emitted. Any valid boost::function - * which ressembles the signal tyes signature can be registert. It is important that the signal type - * was registerd to this object on creation by the appropriate template parameter. - * - * @tparam S the signal which should be intercepted - * @param function boost::function which resembles the signal type's signature - * @return void - **/ - template - Connection connectSignal(typename mpl::at::type function); - - /** - * @brief Disconnects a slot for a specific signal. - * - * Disconnects a slot so that it dosn't get called at signal emittion. It's important to - * disconnect the slot by the same boost:function it was connected with. - * - * @tparam S the signal type of interest - * @param function boost::function with which the slot was connected - * @return void - **/ - template - void disconnectSignal(Connection c); - - /*properties - * search the property map of the system class and get the mpl::vector of properties for the - * derived type. It's imortant to not store the properties but their types. These types are - * stored and accessed as fusion vector. - * */ - typedef typename mpl::at::type Mapped; - typedef typename mpl::if_< boost::is_same, mpl::vector0<>, Mapped>::type Sequence; - typedef typename details::pts::type Properties; - - Properties m_properties; Sys* m_system; - -protected: - /*signal handling - * extract all signal types to allow index search (inex search on signal functions would fail as same - * signatures are supported for multiple signals). Create std::vectors to allow multiple slots per signal - * and store these vectors in a fusion::vector for easy access. - * */ - typedef typename mpl::fold< Sig, mpl::vector<>, - mpl::push_back > >::type sig_name; - typedef typename mpl::fold< Sig, mpl::vector<>, - mpl::push_back > >::type sig_functions; - typedef typename mpl::fold< sig_functions, mpl::vector<>, - mpl::push_back > >::type sig_vectors; - typedef typename fusion::result_of::as_vector::type Signals; - - Signals m_signals; - -public: - //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, ~) }; @@ -214,44 +196,29 @@ template Object::Object(Sys& system) : m_system(&system) {}; template -boost::shared_ptr Object::clone(Sys& newSys) { +boost::shared_ptr Object::clone(Sys& newSys) +{ boost::shared_ptr np = boost::shared_ptr(new Derived(*static_cast(this))); np->m_system = &newSys; return np; }; -template -template -typename Prop::type& Object::getProperty() { - typedef typename mpl::find::type iterator; - typedef typename mpl::distance::type, iterator>::type distance; - BOOST_MPL_ASSERT((mpl::not_::type > >)); - return fusion::at(m_properties); -}; - -template -template -void Object::setProperty(typename Prop::type value) { - typedef typename mpl::find::type iterator; - typedef typename mpl::distance::type, iterator>::type distance; - BOOST_MPL_ASSERT((mpl::not_::type > >)); - fusion::at(m_properties) = value; -}; - -template +template template -Connection Object::connectSignal(typename mpl::at::type function) { +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); + return list.insert(list.begin(), function); }; -template +template template -void Object::disconnectSignal(Connection c) { +void SignalOwner::disconnectSignal(Connection c) +{ typedef typename mpl::find::type iterator; typedef typename mpl::distance::type, iterator>::type distance; diff --git a/src/Mod/Assembly/App/opendcm/core/property.hpp b/src/Mod/Assembly/App/opendcm/core/property.hpp index b42b1f018..1c3e63d36 100644 --- a/src/Mod/Assembly/App/opendcm/core/property.hpp +++ b/src/Mod/Assembly/App/opendcm/core/property.hpp @@ -27,21 +27,150 @@ #include #include +#include +#include +#include + #include #include +#include "kernel.hpp" namespace mpl = boost::mpl; namespace fusion = boost::fusion; namespace dcm { +/** @addtogroup Core + * @{ */ + +/** @defgroup Property Properties + * + * @brief Concept and handling of properties for generic data storage and type extension. + * + * Properties are a basic building block of the dcm and fullfill two essential tasks: First, build a + * infrastructure for storing data in any kind of object and second, make this data universally accessible. + * Universally accessible means in this context, that it shall be possible to retrieve data only by + * knowing some kind of identifier. No data type specific get/set functions or access to class members + * should be needed to access the stored values. The usage of identifiers allows to design interfaces + * for properties in a type interchangable way. Therefore no restrictions are imposed on the interface, + * no matter what or how much data is stored. + * + * The connection of data type and identifier is achieved through the property structs, which all follow + * the same concept: Identifier is the struct type, the stored data is exposed as 'type' typedef. The data + * type can be every c++ type (including classes and structs) which is default constructable. They don't need + * to be assignable or copyable by default, thats only nesseccary if you want to change the hole stored + * object by assigning. If not, the data object can be uncopyable and it should be used by + * retrieving it's reference with get-methods. + * + * Propertys are further designed to fit in the concept of compile-time modularisation. To allow the extension + * of all data-holding entitys with new data types, propertys store their own purpose. Thats + * done by extending the property struct with a second typedef which is named kind and which specifies of which + * kind the property is. That means, that this typedef defines when the property shall be used and for which + * context it is designed for. Dependend on the propertys kind, it will be added to diffrent places inside the dcm. + * A property of kind @ref vertex_property will added to vertices, a property of kind @ref object_property to all + * objects and so on. + * + * If the property type is a standart c++ type like int or bool, the defualt value can't be set by using its + * constructor. Therefore a interface for setting default values is added to the property. If you want + * to assign a default value you just need to add a struct default_value which returns the wanted default + * value with the operator(). If you don't want a default value, just don't add the struct. The implementation + * assignes the default value to the property, therefore it should only be used with assignalble types. + * + * + * A property implementation for storing integers at a graph edge with the identifier + * 'test'property' may look like that: + * @code + * struct test_property { + * typedef int type; + * typedef edge_property kind; + * } + * @endcode + * + * The same property with a default value would be implemented like this: + * @code + * struct test_property { + * typedef int type; + * typedef edge_property kind; + * struct default_value { + * int operator()() { + * return 3; + * }; + * }; + * } + * @endcode + * + * + * If you want to use properties in your class you should derive from PropertyOwner class, as it doas all the + * hanling needed and gives you get and set functions which work with the designed identifiers. + * + * @{ */ + +/** + * @brief Exeption for property errors + * + * This exception is thrown when a property related error is detected, for example if a objects is ask for a + * property which it does not own. This exceptions own the error-code range from 300-399. + **/ +struct property_error : virtual boost::exception { }; + +/** + * @brief Identifier for vertex properties + * + * This is a identifier structure for vertex properties. Every property with this struct as 'kind' type + * will be added to all vertices of a cluster. It is accessible through global and local vertex + * descriptors. These properties are intended for use in boost algorithms in combination with + * \ref property_map . + */ struct vertex_property {}; +/** + * @brief Identifier for edge properties + * + * This is a identifier structure for edge properties. Every property with this struct as 'kind' type + * will be added to all local edges of a cluster. It is accessible through local edge + * descriptors, or global one by getting it's holding local edge first. Note that global edges don't + * have properties, as the properties are intended for use inside boost graph algorithms and therefore + * only needed in local edges. @see property_map + */ struct edge_property {}; + +/** + * @brief Identifier for cluster properties + * + * A ClusterGraph has it's own properties, and ever property with this identifier as 'kind' type will be + * added to it. This is intended for internal dcm usage, its possible to give the abstract cluster a meaning + * by adding special properties to it. It can be accessed by special ClusterGraph functions designed for this + * purpose. + **/ struct cluster_property {}; + +/** + *@brief Identifier for general object properties + * + * Aproperty with this struct as 'kind' type will be added to all existing objects, no matter of individual + * type. Use this only for general, sharable properties. To add a property to a single object, use it's + * type as 'kind'. + **/ struct object_property {}; +/** + *@brief Identifier for system setting properties + * + * Aproperty with this struct as 'kind' type will be added to the system class. Use this for user settings, + * which are just properties which are accessed horugh "setting" functions. + **/ +struct setting_property {}; + namespace details { +/** @addtogroup Metafunctions + * @{ + * @brief Get vertex property information + * + * This traits struct is used to get property information regarding ClusterGraph vertices. It + * allows access to the local descriptor, the mpl property sequence and the position, at which the + * fusion property sequence is stored inside the bundle. It's used to allow generic property + * selection in combination with @ref property_selector + **/ template struct vertex_selector { typedef typename boost::graph_traits::vertex_descriptor key_type; @@ -49,6 +178,13 @@ struct vertex_selector { typedef mpl::int_<1> property_distance; }; +/** @brief Get edge property information + * + * This traits struct is used to get property information regarding ClusterGraph edges. It + * allows access to the local descriptor, the mpl property sequence and the position, at which the + * fusion property sequence is stored inside the bundle. It's used to allow generic property + * selection in combination with @ref property_selector + **/ template struct edge_selector { typedef typename boost::graph_traits::edge_descriptor key_type; @@ -56,145 +192,421 @@ struct edge_selector { typedef mpl::int_<0> property_distance; }; +/** + * @brief Select property information trait depending on property type + * + * Allows generic access to property information like descriptor or property sequence by exposing + * a specific selector type ( @ref vertex_selector or @ref edge_selector ) dependend on the supplied + * property. + **/ template< typename Kind, typename Graph> -struct property_selector : public mpl::if_, +struct property_selector : public mpl::if_ < boost::is_same, vertex_selector, edge_selector >::type {}; +/** + * @brief Metafunction to expose the property storage type + **/ template struct property_type { typedef typename T::type type; }; +/** + * @brief Metafunction to expose which kid of property this is + **/ template struct property_kind { typedef typename T::kind type; }; -//property vector to a fusion sequence of the propety types +/** + * @brief Metafunction to get all properties for a given kind from a property sequence + **/ +template +struct properties_by_kind { + + typedef typename mpl::fold, + mpl::if_< + boost::is_same >, + mpl::push_back, + mpl::_1 + > + >::type type; +}; + +/** + * @brief Metafunction to get all properties for a given object from a property sequence. This includes + * the properties with the object types and all general object properties + **/ +template +struct properties_by_object { + + typedef typename properties_by_kind::type object_props; + typedef typename properties_by_kind::type general_props; + typedef typename mpl::fold< object_props, general_props, mpl::push_back >::type type; +}; + +/** + * @brief Metafunction to ensures that a property is in a lists + * + * Checks for the existence of a given Property in the mpl::vector supplied and adds the property if it is not found. + * @tparam List mpl::vector with property types + * @tparam Prop the property which should be in the supplied list + **/ +template +struct ensure_property { + + typedef typename mpl::if_ < + boost::is_same < + typename mpl::find::type, + typename mpl::end::type > , + typename mpl::push_back::type, + List >::type type; +}; + +/** + * @brief Metafunction to ensures that multiple properties are in the lists + * + * Checks for the existence of all Property's given in the mpl::vector supplied and adds the properties if it is not found. + * @tparam List mpl::vector with property types + * @tparam PropList mpl::vector with properties which should be in the supplied list + **/ +template +struct ensure_properties { + + typedef typename mpl::fold < PropList, List, + mpl::if_ < + boost::is_same< mpl::find, mpl::end >, + mpl::push_back, + mpl::_1 + > >::type type; +}; + +/** + * @brief Property vector to a fusion sequence of the propety storage types + * + * Properties are passed around as mpl sequences, mostly vectors. To store actual values, they need to + * be transformed into fusion sequences. However, only the storage type needs to be in the vector, not + * the 'kind' information (as this is only used as meta information for type creation). This struct + * exposes a fusion vector which can hold all property storage types. + **/ template struct pts { //property type sequence typedef typename mpl::transform >::type ptv; typedef typename fusion::result_of::as_vector< ptv >::type type; }; + +/** + * @brief Type traits to detect if the property has a default value + * + * If the user want to provide a default value for a property than he adds a default_value static function. + * To check if the this function is available we add a type traits which searches for this special function. + */ +BOOST_MPL_HAS_XXX_TRAIT_DEF(default_value) + +/**@}*/ + +/** + * @brief Functor to assign default values to property + * + * This functor holds a pointer to the PropertyOwner in question. The operator() get the properties which + * hold a default value and assigns this value to the property the owner holds. + */ +template +struct apply_default { + + PropertyOwner* owner; + apply_default(PropertyOwner* o) : owner(o) {}; + template + void operator()(const T& t) { + owner->template getProperty() = typename T::default_value()(); + }; +}; } +/** @addtogroup Metafunctions + * @{*/ +/** + * @brief Expose if this is a edge property + **/ template -struct is_edge_property : boost::is_same {}; - +struct is_edge_property : boost::is_same {}; +/** + * @brief Expose if this is a vertex property + **/ template -struct is_vertex_property : boost::is_same {}; - +struct is_vertex_property : boost::is_same {}; +/** + * @brief Expose if this is a cluster property + **/ template -struct is_cluster_property : boost::is_same {}; - +struct is_cluster_property : boost::is_same {}; +/** + * @brief Expose if this is a general object property + **/ template -struct is_object_property : boost::is_same {}; +struct is_object_property : boost::is_same {}; +/**@}*/ +/** + * @brief Adapter to use dcm vertex and edge properties as boost property_maps in bgl algorithms + * + * Boost graph algorithms use property maps as generic storage for process data. In most cases the user + * needs to provide these maps. The simplest way is to create them on the stack right before their + * usage. If, however, the stored information is of use and one wants to store it permanently, this way + * is not practical. Therefor vertex and edge properties were introduced, they allow to store arbitrary + * information at their entity. To use this in combination with boost graph algorithms, this class can + * be used to expose vertex and edge properties as propertie maps to the boost algorithms. All process + * information is then stored permanently at the relevant position. + **/ template class property_map { public: + //expose boost property map interface types typedef typename dcm::details::property_selector::key_type key_type; typedef typename Property::type value_type; typedef typename Property::type& reference; typedef boost::lvalue_property_map_tag category; + //expose cutom types for easy access typedef Property property; typedef typename dcm::details::property_selector::sequence_type sequence; typedef typename dcm::details::property_selector::property_distance distance; + /** + * @brief Links property map with the ClusterGraph which shall be accessed + * + * As boost graph algorithms work with local descriptors, the property map needs to know in which + * graph they are valid. this graph has to be passed to the map. Of course this has to be the one + * on which the algorithm is used on + * + * @param g shared ptr of the cluster graph on which the algorithm is used + **/ property_map(boost::shared_ptr g) : m_graph(g) { } boost::shared_ptr m_graph; }; +/** + * @brief Parent class for all property holding classes in the dcm + * + * To ease the work with properties this class is provided. It receives all the properties, which shall be + * handled, in a mpl::vector typelist as its template argument. Than easy access to all properties by get + * and set functions is achieved. + * + **/ +template +struct PropertyOwner { + + /** + * @brief Constructor assigning default values + * + * It's important to initialise the property fusion sequences with this constructor + * as much handling has to be done to ensure the users default values are added correctly + **/ + PropertyOwner(); + + /** + * @brief Access properties + * + * Returns a reference to the propertys actual value. The property type has to be owned by this class, + * which means it needs to be in the typelist that was given as template parameter to this class. + * @tparam Prop property type which should be accessed + * @return Prop::type& a reference to the properties actual value. + **/ + template + typename Prop::type& getProperty(); + + /** + * @brief Set properties + * + * Sets the value of a specified property. The property type has to be owned by this class, + * which means it needs to be in the typelist that was given as template parameter to this class. + * Note that setProperty(value) is equivalent to getProperty() = value. + * @tparam Prop property type which should be setProperty + * @param value value of type Prop::type which should be set in this object + **/ + template + void setProperty(typename Prop::type value); + + /* It's imortant to not store the properties but their types. These types are + * stored and accessed as fusion vector. + * */ + typedef PropertyList PropertySequence; + typedef typename details::pts::type Properties; + + Properties m_properties; +}; + +template +void pretty(T t) { + std::cout<<__PRETTY_FUNCTION__< +PropertyOwner::PropertyOwner() { + + //get a vies of all types which have a default value + typedef typename mpl::filter_view >::type view; + //set the default value + details::apply_default func(this); + mpl::for_each(func); + +#if defined(BOOST_MPL_CFG_NO_HAS_XXX) + throw property_error() << boost::errinfo_errno(301) << error_message("no default values supported"); +#endif +}; + +/** + * @brief Convienience spezialisation to ease interaction with system class + * + * Normaly property lists are retrieved from the system class, however, there are no empty lists. If no + * property is supplied for a PropertyOwner derived class, a mpl::void_ type will be retrieved. To + * remove the burdon of checking for that type in the class definition this spezialisation is supplied. + **/ +template<> +struct PropertyOwner { + template + typename Prop::type& getProperty() { + throw property_error() << boost::errinfo_errno(300) << error_message("unknown property type"); + }; + + template + void setProperty(typename Prop::type value) { + throw property_error() << boost::errinfo_errno(300) << error_message("unknown property type"); + }; +}; + +template +template +typename Prop::type& PropertyOwner::getProperty() { + + typedef typename mpl::find::type iterator; + typedef typename mpl::distance::type, iterator>::type distance; + BOOST_MPL_ASSERT((mpl::not_::type > >)); + return fusion::at (m_properties); +}; + +template +template +void PropertyOwner::setProperty(typename Prop::type value) { + + typedef typename mpl::find::type iterator; + typedef typename mpl::distance::type, iterator>::type distance; + BOOST_MPL_ASSERT((mpl::not_::type > >)); + fusion::at (m_properties) = value; +}; + + //now create some standart properties //*********************************** +/** + * @brief Dummy property + **/ struct empty_prop { - typedef int kind; - typedef int type; + typedef int kind; + typedef int type; }; //type of a graph cluster +/** + * @brief Add a type to clusters + * + * Allows to specify special types to ClusterGraphs and make a it possibe to distuingish between + * diffrent purposes. The cluster types need to be int. + **/ struct type_prop { //states the type of a cluster typedef cluster_property kind; typedef int type; }; //cluster in graph changed? +/** + * @brief Was the cluster changed? + * + * Adds a boolean to the cluster which indicates if the cluster was changedsince the last + * processing. It should be set to true if vertices and edges were added or removed, Subclusters + * created or deleted and so on. + **/ struct changed_prop { typedef cluster_property kind; typedef bool type; }; -//vertex index for bgl algorithms +/** + * @brief Add an index to vertices + * + * Most boost graph algorithms need a index for vertices, ranging from 0 to vertex count. As this can + * be useful for many other things it is added as vertex property. + **/ struct vertex_index_prop { typedef vertex_property kind; typedef int type; }; -//edge index for bgl algorithms +/** + * @brief Add an index to edges + * + * Most boost graph algorithms need a index for edges, ranging from 0 to edge count. As this can + * be useful for many other things it is added as edge property. + **/ struct edge_index_prop { typedef edge_property kind; typedef int type; }; -//vertex color for bgl algorithms -struct vertex_color_prop { - typedef vertex_property kind; - typedef boost::default_color_type type; -}; -//edge color for bgl algorithms -struct edge_color_prop { - typedef edge_property kind; - typedef boost::default_color_type type; -}; - - -//object id's +/** + * @brief Add an ID to objects + * + * It may be wanted to add identification markers to objects, this property can be used for that. It + * is special, as it takes its storage type as template parameter. This property can therefore not be + * directly accessed with this struct, the template parameter has to be known. + * @tparam T the identifier type + **/ template struct id_prop { typedef object_property kind; typedef T type; }; +/**@}*/ //Property +/**@}*/ //Core } -template -void pretty(T t) { - std::cout<<__PRETTY_FUNCTION__< -typename dcm::property_map::value_type get(const dcm::property_map& map, - typename dcm::property_map::key_type key) { +typename dcm::property_map::value_type get(const dcm::property_map& map, + typename dcm::property_map::key_type key) +{ - typedef dcm::property_map map_t; + typedef dcm::property_map map_t; typedef typename mpl::find::type iterator; typedef typename mpl::distance::type, iterator>::type distance; - return fusion::at(fusion::at::distance>(map.m_graph->operator[](key))); + return fusion::at (fusion::at::distance> (map.m_graph->operator[](key))); }; template -void put(const dcm::property_map& map, - typename dcm::property_map::key_type key, - const typename dcm::property_map::value_type& value) { +void put(const dcm::property_map& map, + typename dcm::property_map::key_type key, + const typename dcm::property_map::value_type& value) +{ - typedef dcm::property_map map_t; + typedef dcm::property_map map_t; typedef typename mpl::find::type iterator; typedef typename mpl::distance::type, iterator>::type distance; - fusion::at(fusion::at::distance>(map.m_graph->operator[](key))) = value; + fusion::at (fusion::at::distance> (map.m_graph->operator[](key))) = value; }; template -typename dcm::property_map::reference at(const dcm::property_map& map, - typename dcm::property_map::key_type key) { - typedef dcm::property_map map_t; +typename dcm::property_map::reference at(const dcm::property_map& map, + typename dcm::property_map::key_type key) +{ + typedef dcm::property_map map_t; typedef typename mpl::find::type iterator; typedef typename mpl::distance::type, iterator>::type distance; - return fusion::at(fusion::at::distance>(map.m_graph->operator[](key))); + return fusion::at (fusion::at::distance> (map.m_graph->operator[](key))); } } diff --git a/src/Mod/Assembly/App/opendcm/core/system.hpp b/src/Mod/Assembly/App/opendcm/core/system.hpp index 2b0ac11be..371ddbcc4 100644 --- a/src/Mod/Assembly/App/opendcm/core/system.hpp +++ b/src/Mod/Assembly/App/opendcm/core/system.hpp @@ -76,12 +76,6 @@ struct obj_fold : mpl::fold< seq, state, boost::is_same< details::property_kind, obj>, is_object_property >, mpl::push_back, mpl::_1 > > {}; -template -struct property_map_fold { - typedef typename mpl::fold< - objects, mpl::map<>, mpl::insert< mpl::_1, mpl::pair< - mpl::_2, details::obj_fold, mpl::_2 > > > >::type type; -}; template struct get_identifier { typedef typename T::Identifier type; @@ -100,6 +94,7 @@ struct EmptyModule { struct inheriter {}; typedef mpl::vector<> properties; typedef mpl::vector<> objects; + typedef mpl::vector<> geometries; typedef Unspecified_Identifier Identifier; static void system_init(T& sys) {}; @@ -153,14 +148,20 @@ public: typename details::vector_fold > >::type >::type>::type properties; + + //get all geometries we support + typedef typename details::vector_fold >::type >::type>::type geometries; //make the subcomponent lists of objects and properties - typedef typename details::edge_fold< properties, mpl::vector<> >::type edge_properties; - typedef typename details::vertex_fold< properties, mpl::vector<> >::type vertex_properties; + typedef typename details::edge_fold< properties, + mpl::vector1 >::type edge_properties; + typedef typename details::vertex_fold< properties, + mpl::vector1 >::type vertex_properties; typedef typename details::cluster_fold< properties, - mpl::vector >::type cluster_properties; - - typedef typename details::property_map_fold::type object_properties; + mpl::vector2 >::type cluster_properties; protected: //object storage @@ -178,6 +179,11 @@ protected: vector.clear(); }; }; + + //we hold our own PropertyOwner which we use for system settings. Don't inherit it as the user + //should not access the settings via the proeprty getter and setter functions. + typedef PropertyOwner::type> SettingOwner; + SettingOwner m_settings; #ifdef USE_LOGGING boost::shared_ptr< sink_t > sink; @@ -267,9 +273,19 @@ public: System* s = new System(); s->m_cluster = m_cluster->createCluster().first; s->m_storage = m_storage; - s->m_cluster->template setClusterProperty(details::subcluster); + s->m_cluster->template setProperty(details::subcluster); return s; }; + + template + typename Setting::type& getSetting() { + return m_settings.template getProperty(); + }; + + template + void setSetting(typename Setting::type value){ + m_settings.template setProperty(value); + }; private: struct cloner { @@ -321,3 +337,10 @@ public: + + + + + + + diff --git a/src/Mod/Assembly/App/opendcm/core/traits.hpp b/src/Mod/Assembly/App/opendcm/core/traits.hpp index 1d296f820..e53bebf79 100644 --- a/src/Mod/Assembly/App/opendcm/core/traits.hpp +++ b/src/Mod/Assembly/App/opendcm/core/traits.hpp @@ -23,6 +23,7 @@ #include #include #include +#include #include #include @@ -36,8 +37,8 @@ namespace dcm { template< typename T > struct system_traits { - typedef typename T::Kernel Kernel; - typedef typename T::Cluster Cluster; + //typedef typename T::Kernel Kernel; + //typedef typename T::Cluster Cluster; template struct getModule { @@ -46,7 +47,7 @@ struct system_traits { typedef typename mpl::if_< boost::is_base_of, test1, typename T::Type3 >::type test2; typedef typename mpl::if_< boost::is_base_of, test2, mpl::void_ >::type type; - typedef boost::is_same has_module; + typedef mpl::not_ > has_module; }; }; diff --git a/src/Mod/Assembly/App/opendcm/module3d.hpp b/src/Mod/Assembly/App/opendcm/module3d.hpp index 92206745f..13c3b2396 100644 --- a/src/Mod/Assembly/App/opendcm/module3d.hpp +++ b/src/Mod/Assembly/App/opendcm/module3d.hpp @@ -33,6 +33,7 @@ #include "module3d/parallel.hpp" #include "module3d/angle.hpp" #include "module3d/coincident.hpp" +#include "module3d/alignment.hpp" #include "module3d/module.hpp" #ifdef DCM_USE_MODULESTATE diff --git a/src/Mod/Assembly/App/opendcm/module3d/angle.hpp b/src/Mod/Assembly/App/opendcm/module3d/angle.hpp index 4c9d78850..46067fadb 100644 --- a/src/Mod/Assembly/App/opendcm/module3d/angle.hpp +++ b/src/Mod/Assembly/App/opendcm/module3d/angle.hpp @@ -61,7 +61,7 @@ inline void calcGradFirstComp(const T& d1, const T& grad) { typename Kernel::number_type norm = d1.norm()*d2.norm(); - const_cast< T& >(grad) = d2/norm - (d1.dot(d2)/std::pow(norm,2))*d1/d1.norm(); + const_cast< T& >(grad) = d2/norm - d1.dot(d2)*d1/(std::pow(d1.norm(),3)*d2.norm()); }; template @@ -70,7 +70,7 @@ inline void calcGradSecondComp(const T& d1, const T& grad) { typename Kernel::number_type norm = d1.norm()*d2.norm(); - const_cast< T& >(grad) = d1/norm - (d1.dot(d2)/std::pow(norm,2))*d2/d2.norm(); + const_cast< T& >(grad) = d1/norm - d1.dot(d2)*d2/(std::pow(d2.norm(),3)*d1.norm()); }; } diff --git a/src/Mod/Assembly/App/opendcm/module3d/clustermath.hpp b/src/Mod/Assembly/App/opendcm/module3d/clustermath.hpp index 97592cc00..1d3be6e6d 100644 --- a/src/Mod/Assembly/App/opendcm/module3d/clustermath.hpp +++ b/src/Mod/Assembly/App/opendcm/module3d/clustermath.hpp @@ -29,8 +29,6 @@ #include #include "defines.hpp" -#include "Base/Console.h" - #define MAXFAKTOR 1.2 //the maximal distance allowd by a point normed to the cluster size #define MINFAKTOR 0.8 //the minimal distance allowd by a point normed to the cluster size #define SKALEFAKTOR 1. //the faktor by which the biggest size is multiplied to get the scale value @@ -52,8 +50,8 @@ template struct ClusterMath { public: - typedef typename system_traits::Kernel Kernel; - typedef typename system_traits::Cluster Cluster; + typedef typename Sys::Kernel Kernel; + typedef typename Sys::Cluster Cluster; typedef typename system_traits::template getModule::type module3d; typedef typename module3d::Geometry3D Geometry3D; typedef boost::shared_ptr Geom; @@ -154,7 +152,7 @@ public: template ClusterMath::ClusterMath() : m_normQ(NULL), m_translation(NULL), init(false) { - m_resetTransform = typename Kernel::Quaternion(1,1,1,1); + m_resetTransform = Eigen::AngleAxisd(M_PI*2./3., Eigen::Vector3d(1,1,1).normalized()); m_shift.setZero(); #ifdef USE_LOGGING @@ -453,8 +451,8 @@ void ClusterMath::mapClusterDownstreamGeometry(boost::shared_ptr c BOOST_LOG(log) << "Map downstream geometry"; #endif - map_downstream down(cluster->template getClusterProperty(), - cluster->template getClusterProperty()); + map_downstream down(cluster->template getProperty(), + cluster->template getProperty()); cluster->template for_each(down, true); //TODO: if one subcluster is fixed the hole cluster should be too, as there are no // dof's remaining between parts and so nothing can be moved when one part is fixed. diff --git a/src/Mod/Assembly/App/opendcm/module3d/coincident.hpp b/src/Mod/Assembly/App/opendcm/module3d/coincident.hpp index fd45c6b69..7bc899094 100644 --- a/src/Mod/Assembly/App/opendcm/module3d/coincident.hpp +++ b/src/Mod/Assembly/App/opendcm/module3d/coincident.hpp @@ -38,7 +38,7 @@ struct ci_orientation : public Equation { struct type : public PseudoScale { type() { - throw constraint_error() << boost::errinfo_errno(103) << error_message("unsupported geometry in coincidence/alignment orientation constraint") + throw constraint_error() << boost::errinfo_errno(103) << error_message("unsupported geometry in coincidence orientation constraint") << error_type_first_geometry(typeid(Tag1).name()) << error_type_second_geometry(typeid(Tag2).name()); }; @@ -113,9 +113,6 @@ struct ci_orientation::type< Kernel, tag::line3D, tag::cylinder3D > : public dcm template< typename Kernel > struct ci_orientation::type< Kernel, tag::plane3D, tag::plane3D > : public dcm::Orientation::type< Kernel, tag::plane3D, tag::plane3D > {}; -template< typename Kernel > -struct ci_orientation::type< Kernel, tag::plane3D, tag::cylinder3D > : public dcm::Orientation::type< Kernel, tag::plane3D, tag::cylinder3D > {}; - template< typename Kernel > struct ci_orientation::type< Kernel, tag::cylinder3D, tag::cylinder3D > : public dcm::Orientation::type< Kernel, tag::cylinder3D, tag::cylinder3D > {}; @@ -132,7 +129,7 @@ struct ci_distance : public Equation { struct type : public PseudoScale { type() { - throw constraint_error() << boost::errinfo_errno(104) << error_message("unsupported geometry in coincidence/alignment distance constraint") + throw constraint_error() << boost::errinfo_errno(104) << error_message("unsupported geometry in coincidence distance constraint") << error_type_first_geometry(typeid(Tag1).name()) << error_type_second_geometry(typeid(Tag2).name()); }; @@ -172,22 +169,19 @@ template< typename Kernel > struct ci_distance::type< Kernel, tag::point3D, tag::plane3D > : public dcm::Distance::type< Kernel, tag::point3D, tag::plane3D > {}; template< typename Kernel > -struct ci_distance::type< Kernel, tag::point3D, tag::cylinder3D > : public dcm::Distance::type< Kernel, tag::point3D, tag::cylinder3D > {}; +struct ci_distance::type< Kernel, tag::point3D, tag::cylinder3D > : public dcm::Distance::type< Kernel, tag::point3D, tag::line3D > {}; template< typename Kernel > struct ci_distance::type< Kernel, tag::line3D, tag::line3D > : public dcm::Distance::type< Kernel, tag::point3D, tag::line3D > {}; template< typename Kernel > -struct ci_distance::type< Kernel, tag::line3D, tag::plane3D > : public dcm::Distance::type< Kernel, tag::point3D, tag::plane3D > {}; +struct ci_distance::type< Kernel, tag::line3D, tag::plane3D > : public dcm::Distance::type< Kernel, tag::line3D, tag::plane3D > {}; template< typename Kernel > -struct ci_distance::type< Kernel, tag::line3D, tag::cylinder3D > : public dcm::Distance::type< Kernel, tag::point3D, tag::cylinder3D > {}; +struct ci_distance::type< Kernel, tag::line3D, tag::cylinder3D > : public dcm::Distance::type< Kernel, tag::point3D, tag::line3D > {}; template< typename Kernel > -struct ci_distance::type< Kernel, tag::plane3D, tag::plane3D > : public dcm::Distance::type< Kernel, tag::point3D, tag::plane3D > {}; - -template< typename Kernel > -struct ci_distance::type< Kernel, tag::plane3D, tag::cylinder3D > : public dcm::Distance::type< Kernel, tag::point3D, tag::cylinder3D > {}; +struct ci_distance::type< Kernel, tag::plane3D, tag::plane3D > : public dcm::Distance::type< Kernel, tag::plane3D, tag::plane3D > {}; template< typename Kernel > struct ci_distance::type< Kernel, tag::cylinder3D, tag::cylinder3D > : public dcm::Distance::type< Kernel, tag::point3D, tag::line3D > {}; @@ -207,39 +201,8 @@ struct Coincidence : public dcm::constraint_sequence< fusion::vector2< details:: }; }; -struct Alignment : public dcm::constraint_sequence< fusion::vector2< details::ci_distance, details::ci_orientation > > { - //allow to set the distance - Alignment& operator()(Direction val) { - fusion::at_c<1>(*this) = val; - return *this; - }; - Alignment& operator()(double val) { - fusion::at_c<0>(*this) = val; - return *this; - }; - Alignment& operator()(double val1, Direction val2) { - fusion::at_c<0>(*this) = val1; - fusion::at_c<1>(*this) = val2; - return *this; - }; - Alignment& operator()(Direction val1, double val2) { - fusion::at_c<0>(*this) = val2; - fusion::at_c<1>(*this) = val1; - return *this; - }; - Alignment& operator=(Direction val) { - fusion::at_c<1>(*this) = val; - return *this; - }; - Alignment& operator=(double val) { - fusion::at_c<0>(*this) = val; - return *this; - }; -}; - //no standart equation, create our own object static Coincidence coincidence; -static Alignment alignment; }//dcm diff --git a/src/Mod/Assembly/App/opendcm/module3d/defines.hpp b/src/Mod/Assembly/App/opendcm/module3d/defines.hpp index fb49f2cd3..60549e18c 100644 --- a/src/Mod/Assembly/App/opendcm/module3d/defines.hpp +++ b/src/Mod/Assembly/App/opendcm/module3d/defines.hpp @@ -20,8 +20,6 @@ #ifndef GCM_DEFINES_3D_H #define GCM_DEFINES_3D_H -#include - namespace dcm { namespace details { @@ -30,11 +28,6 @@ enum { cluster3D = 100}; struct m3d {}; //base of module3d::type to allow other modules check for it } - -//exception codes are needed by the user -//typedef boost::error_info solver_failure_type; -struct creation_error : virtual boost::exception {}; - } #endif diff --git a/src/Mod/Assembly/App/opendcm/module3d/distance.hpp b/src/Mod/Assembly/App/opendcm/module3d/distance.hpp index 273efc7aa..08d4bc67a 100644 --- a/src/Mod/Assembly/App/opendcm/module3d/distance.hpp +++ b/src/Mod/Assembly/App/opendcm/module3d/distance.hpp @@ -411,8 +411,9 @@ struct Distance::type< Kernel, tag::line3D, tag::plane3D > : public Distance::ty #endif typedef typename Kernel::VectorMap Vector; void calculateGradientFirstComplete(Vector& p1, Vector& p2, Vector& g) { - Distance::type< Kernel, tag::point3D, tag::plane3D >::calculateGradientFirstComplete(p1,p2,g); - g.segment(3,3).setZero(); + typename Kernel::VectorMap grad(&g(0), 3, typename Kernel::DynStride(1,1)); + Distance::type< Kernel, tag::point3D, tag::plane3D >::calculateGradientFirstComplete(p1,p2,grad); + g.segment(3,3).setZero(); }; }; @@ -451,7 +452,8 @@ struct Distance::type< Kernel, tag::plane3D, tag::plane3D > : public Distance::t #endif typedef typename Kernel::VectorMap Vector; void calculateGradientFirstComplete(Vector& p1, Vector& p2, Vector& g) { - Distance::type< Kernel, tag::point3D, tag::plane3D >::calculateGradientFirstComplete(p1,p2,g); + typename Kernel::VectorMap grad(&g(0), 3, typename Kernel::DynStride(1,1)); + Distance::type< Kernel, tag::point3D, tag::plane3D >::calculateGradientFirstComplete(p1,p2,grad); g.segment(3,3).setZero(); }; }; @@ -488,7 +490,8 @@ struct Distance::type< Kernel, tag::plane3D, tag::cylinder3D > : public Distance }; void calculateGradientSecondComplete(Vector& p1, Vector& p2, Vector& g) { - Distance::type< Kernel, tag::point3D, tag::plane3D >::calculateGradientFirstComplete(p2,p1,g); + typename Kernel::VectorMap grad(&g(0), 3, typename Kernel::DynStride(1,1)); + Distance::type< Kernel, tag::point3D, tag::plane3D >::calculateGradientFirstComplete(p2,p1,grad); g.segment(3,3).setZero(); g(6) = -1; }; diff --git a/src/Mod/Assembly/App/opendcm/module3d/geometry.hpp b/src/Mod/Assembly/App/opendcm/module3d/geometry.hpp index 9fedadc8e..6a3531fb5 100644 --- a/src/Mod/Assembly/App/opendcm/module3d/geometry.hpp +++ b/src/Mod/Assembly/App/opendcm/module3d/geometry.hpp @@ -25,41 +25,13 @@ namespace dcm { namespace tag { -struct point3D { - typedef mpl::int_<3> parameters; - typedef mpl::int_<1> rotations; - typedef mpl::int_<1> translations; - typedef weight::point weight; -}; +struct point3D : details::basic_geometry {}; +struct direction3D : details::basic_geometry {}; +struct line3D : details::stacked2_geometry {}; +struct plane3D : details::stacked2_geometry {}; +struct cylinder3D : details::stacked3_geometry {}; -struct direction3D { - typedef mpl::int_<3> parameters; - typedef mpl::int_<1> rotations; - typedef mpl::int_<0> translations; - typedef weight::direction weight; -}; - -struct line3D { - typedef mpl::int_<6> parameters; - typedef mpl::int_<2> rotations; - typedef mpl::int_<1> translations; - typedef weight::line weight; -}; - -struct plane3D { - typedef mpl::int_<6> parameters; - typedef mpl::int_<2> rotations; - typedef mpl::int_<1> translations; - typedef weight::plane weight; -}; - -struct cylinder3D { - typedef mpl::int_<7> parameters; - typedef mpl::int_<2> rotations; - typedef mpl::int_<1> translations; - typedef weight::cylinder weight; -}; -} +} //tag namespace modell { @@ -155,6 +127,27 @@ namespace modell { } +//dummy accessor +struct dummy_accessor { + + template + Scalar get(T& t) { + return 1; + }; + template + void set(Scalar value, T& t) { + //TODO: throw + }; +}; + +//dummy geometry traits for boost blank, wil bever be used +template<> +struct geometry_traits { + typedef tag::direction3D tag; + typedef modell::XYZ modell; + typedef dummy_accessor accessor; +}; + } #endif //GCM_GEOMETRY_3D_H diff --git a/src/Mod/Assembly/App/opendcm/module3d/module.hpp b/src/Mod/Assembly/App/opendcm/module3d/module.hpp index a511dbb1e..b30fedb5c 100644 --- a/src/Mod/Assembly/App/opendcm/module3d/module.hpp +++ b/src/Mod/Assembly/App/opendcm/module3d/module.hpp @@ -40,10 +40,10 @@ #include "opendcm/core.hpp" #include "opendcm/core/object.hpp" +#include "opendcm/core/geometry.hpp" #include "opendcm/core/clustergraph.hpp" #include "opendcm/core/sheduler.hpp" #include "opendcm/core/traits.hpp" -#include "opendcm/core/geometry.hpp" #include "geometry.hpp" #include "distance.hpp" #include "parallel.hpp" @@ -52,6 +52,7 @@ #include "defines.hpp" #include "clustermath.hpp" + namespace mpl = boost::mpl; namespace dcm { @@ -69,6 +70,8 @@ struct distance { namespace dcm { +struct reset {}; //signal name + template struct Module3D { @@ -82,25 +85,106 @@ struct Module3D { typedef boost::shared_ptr Geom; typedef boost::shared_ptr Cons; + typedef mpl::map3< mpl::pair >, + mpl::pair > , + mpl::pair > > GeomSig; typedef mpl::map1< mpl::pair > > ConsSignal; typedef ID Identifier; - typedef Typelist geometry_types; + typedef Typelist geometry_types; typedef details::MES MES; typedef details::SystemSolver SystemSolver; template - class Geometry3D_id : public detail::Geometry { + class Geometry3D_base : public details::Geometry, + public Object { - typedef detail::Geometry Base; + typedef details::Geometry Base; + typedef Object ObjBase; + typedef typename Sys::Kernel Kernel; + typedef typename Kernel::number_type Scalar; + + public: + Geometry3D_base(Sys& system); + + template + Geometry3D_base(const T& geometry, Sys& system); + + template + void set(const T& geometry); + + bool holdsType() { + return m_geometry.which()!=0; + }; + int whichType() { + return m_geometry.which()-1; + }; + + template + typename Visitor::result_type apply(Visitor& vis) { + return boost::apply_visitor(vis, m_geometry); + }; + + template + T convertTo() { + T t; + (typename geometry_traits::modell()).template inject::accessor >(t, Base::m_global); + return t; + }; + + virtual boost::shared_ptr clone(Sys& newSys); + + protected: + typedef typename mpl::push_front::type ExtTypeList; + typedef typename boost::make_variant_over< ExtTypeList >::type Variant; + + struct cloner : boost::static_visitor { + typedef typename boost::make_variant_over< ExtTypeList >::type Variant; + + Variant variant; + cloner(Variant& v) : variant(v) {}; + + template + void operator()(T& t) { + variant = geometry_clone_traits()(t); + }; + }; + + //visitor to write the calculated value into the variant + struct apply_visitor : public boost::static_visitor { + + apply_visitor(typename Kernel::Vector& v) : value(v) {}; + template + void operator()(T& t) const { + (typename geometry_traits::modell()).template inject::accessor >(t, value); + } + typename Kernel::Vector& value; + }; + + Variant m_geometry; //Variant holding the real geometry type + + //override protected event functions to emit signals + void reset(); + void recalculated(); + void removed(); + + friend class Constraint3D; + }; + + template + class Geometry3D_id : public Geometry3D_base { + + typedef Geometry3D_base Base; #ifdef USE_LOGGING attrs::mutable_constant< std::string > log_id; #endif public: - Geometry3D_id(Sys& system); - + Geometry3D_id(Sys& system); + template Geometry3D_id(const T& geometry, Sys& system); @@ -115,12 +199,12 @@ struct Module3D { }; struct Geometry3D : public mpl::if_, - detail::Geometry, Geometry3D_id >::type { + Geometry3D_base, Geometry3D_id >::type { typedef vertex_prop vertex_propertie; Geometry3D(Sys& system); - + template Geometry3D(const T& geometry, Sys& system); @@ -129,17 +213,28 @@ struct Module3D { friend struct details::ClusterMath::map_downstream; friend struct details::SystemSolver; friend struct details::SystemSolver::Rescaler; - friend class detail::Constraint; + friend class inheriter_base; - public: - //the geometry class itself does not hold an aligned eigen object, but maybe the variant - EIGEN_MAKE_ALIGNED_OPERATOR_NEW + public: + //the geometry class itself does not hold an aligned eigen object, but maybe the variant + EIGEN_MAKE_ALIGNED_OPERATOR_NEW }; template - class Constraint3D_id : public detail::Constraint { + class Constraint3D_base : public detail::Constraint, public Object { - typedef detail::Constraint base; + typedef detail::Constraint CBase; + public: + Constraint3D_base(Sys& system, Geom f, Geom s) : detail::Constraint(f,s), + Object(system) {}; + + virtual boost::shared_ptr clone(Sys& newSys); + }; + + template + class Constraint3D_id : public Constraint3D_base { + + typedef Constraint3D_base base; public: Constraint3D_id(Sys& system, Geom f, Geom s); @@ -148,7 +243,7 @@ struct Module3D { }; struct Constraint3D : public mpl::if_, - detail::Constraint, + Constraint3D_base, Constraint3D_id >::type { Constraint3D(Sys& system, Geom first, Geom second); @@ -168,15 +263,28 @@ struct Module3D { T, fusion::vector >::type type; }; + template + struct initalizer : public boost::static_visitor { + + Cons constraint; + covec& cov; + initalizer(Cons c, covec& co) : constraint(c), cov(co) {}; + template + void operator()(const T1& t1, const T2& t2) { + constraint->template initialize< typename geometry_traits::tag, + typename geometry_traits::tag, covec>(cov); + }; + }; + struct set_constraint_option { template - typename boost::enable_if, typename fusion_vec::type >::type + typename boost::enable_if, typename fusion_vec::type >::type operator()(T& val) { return val; }; template - typename boost::disable_if, typename fusion_vec::type >::type + typename boost::disable_if, typename fusion_vec::type >::type operator()(T& val) { typename fusion_vec::type vec; fusion::at_c<0>(vec) = val; @@ -188,6 +296,7 @@ struct Module3D { template Geom createGeometry3D(T geom); + Geom createGeometry3D(); void removeGeometry3D(Geom g); template @@ -207,13 +316,14 @@ struct Module3D { public: template Geom createGeometry3D(T geom, Identifier id); + Geom createGeometry3D(Identifier id); template Cons createConstraint3D(Identifier id, Geom first, Geom second, T constraint1); void removeGeometry3D(Identifier id); void removeConstraint3D(Identifier id); - using inheriter_base::removeGeometry3D; - using inheriter_base::removeConstraint3D; + using inheriter_base::removeGeometry3D; + using inheriter_base::removeConstraint3D; bool hasGeometry3D(Identifier id); Geom getGeometry3D(Identifier id); @@ -241,7 +351,8 @@ struct Module3D { }; typedef mpl::vector4 properties; - typedef mpl::vector objects; + typedef mpl::vector2 objects; + typedef mpl::vector5 geometries; static void system_init(Sys& sys) { sys.m_sheduler.addProcessJob(new SystemSolver()); @@ -298,10 +409,97 @@ typename boost::add_reference::type get(G geom) { template template template -Module3D::type::Geometry3D_id::Geometry3D_id(Sys& system) - : detail::Geometry(system) +Module3D::type::Geometry3D_base::Geometry3D_base(Sys& system) + : Object(system) { + #ifdef USE_LOGGING - , log_id("No ID") + log.add_attribute("Tag", attrs::constant< std::string >("Geometry3D")); +#endif +}; + +template +template +template +template +Module3D::type::Geometry3D_base::Geometry3D_base(const T& geometry, Sys& system) + : Object(system) { + +#ifdef USE_LOGGING + log.add_attribute("Tag", attrs::constant< std::string >("Geometry3D")); +#endif + + m_geometry = geometry; + //first init, so that the geometry internal vector has the right size + Base::template init< typename geometry_traits::tag >(); + //now write the value; + (typename geometry_traits::modell()).template extract::accessor >(geometry, Base::getValue()); +}; + +template +template +template +template +void Module3D::type::Geometry3D_base::set(const T& geometry) { + + m_geometry = geometry; + //first init, so that the geometry internal vector has the right size + Base::template init< typename geometry_traits::tag >(); + //now write the value; + (typename geometry_traits::modell()).template extract::accessor >(geometry, Base::getValue()); + + reset(); +}; + +template +template +template +boost::shared_ptr Module3D::type::Geometry3D_base::clone(Sys& newSys) { + + //copy the standart stuff + boost::shared_ptr np = boost::shared_ptr(new Derived(*static_cast(this))); + np->m_system = &newSys; + //it's possible that the variant contains pointers, so we need to clone them + cloner clone_fnc(np->m_geometry); + boost::apply_visitor(clone_fnc, m_geometry); + return np; +}; + +template +template +template +void Module3D::type::Geometry3D_base::recalculated() { + + apply_visitor v(Base::getValue()); + apply(v); + + ObjBase::template emitSignal(((Derived*)this)->shared_from_this()); +}; + +template +template +template +void Module3D::type::Geometry3D_base::removed() { + + ObjBase::template emitSignal(((Derived*)this)->shared_from_this()); +}; + +template +template +template +void Module3D::type::Geometry3D_base::reset() { + + ObjBase::template emitSignal(((Derived*)this)->shared_from_this()); +}; + +template +template +template +Module3D::type::Geometry3D_id::Geometry3D_id(Sys& system) + : Module3D::template type::template Geometry3D_base(system) +#ifdef USE_LOGGING +, log_id("No ID") #endif { @@ -315,9 +513,9 @@ template template template Module3D::type::Geometry3D_id::Geometry3D_id(const T& geometry, Sys& system) - : detail::Geometry(geometry, system) + : Module3D::template type::template Geometry3D_base(geometry, system) #ifdef USE_LOGGING - , log_id("No ID") +, log_id("No ID") #endif { @@ -368,7 +566,7 @@ template template Module3D::type::Geometry3D::Geometry3D(Sys& system) : mpl::if_, - detail::Geometry, + Geometry3D_base, Geometry3D_id >::type(system) { }; @@ -378,16 +576,38 @@ template template Module3D::type::Geometry3D::Geometry3D(const T& geometry, Sys& system) : mpl::if_, - detail::Geometry, + Geometry3D_base, Geometry3D_id >::type(geometry, system) { }; +template +template +template +boost::shared_ptr Module3D::type::Constraint3D_base::clone(Sys& newSys) { + + //copy the standart stuff + boost::shared_ptr np = boost::shared_ptr(new Derived(*static_cast(this))); + np->m_system = &newSys; + //copy the internals + np->content = CBase::content->clone(); + //and get the geometry pointers right + if(CBase::first) { + GlobalVertex v = boost::static_pointer_cast(CBase::first)->template getProperty(); + np->first = newSys.m_cluster->template getObject(v); + } + if(CBase::second) { + GlobalVertex v = boost::static_pointer_cast(CBase::second)->template getProperty(); + np->second = newSys.m_cluster->template getObject(v); + } + return np; +}; + template template template Module3D::type::Constraint3D_id::Constraint3D_id(Sys& system, Geom f, Geom s) - : detail::Constraint(system, f, s) { + : Constraint3D_base(system, f, s) { }; @@ -410,7 +630,7 @@ template template Module3D::type::Constraint3D::Constraint3D(Sys& system, Geom first, Geom second) : mpl::if_, - detail::Constraint, + Constraint3D_base, Constraint3D_id >::type(system, first, second) { }; @@ -421,6 +641,19 @@ Module3D::type::inheriter_base::inheriter_base() { m_this = ((Sys*) this); }; +template +template +typename Module3D::template type::Geom +Module3D::type::inheriter_base::createGeometry3D() { + + Geom g(new Geometry3D(* ((Sys*) this))); + fusion::vector res = m_this->m_cluster->addVertex(); + m_this->m_cluster->template setObject (fusion::at_c<0> (res), g); + g->template setProperty(fusion::at_c<1>(res)); + m_this->push_back(g); + return g; +}; + template template template @@ -466,12 +699,12 @@ Module3D::type::inheriter_base::createConstraint3D(Geom first typedef typename fusion_vec::type covec; //set the objects - covec cv = set_constraint_option()( constraint1 ); + covec cv = set_constraint_option()(constraint1); //now create the constraint Cons c(new Constraint3D(*m_this, first, second)); - //set the type and values - c->template initialize(cv); + //initialize constraint + c->initialize(cv); //add it to the clustergraph fusion::vector res; @@ -518,6 +751,15 @@ Module3D::type::inheriter_id::createGeometry3D(T geom, Identi return g; }; +template +template +typename Module3D::template type::Geom +Module3D::type::inheriter_id::createGeometry3D(Identifier id) { + Geom g = inheriter_base::createGeometry3D(); + g->setIdentifier(id); + return g; +}; + template template void Module3D::type::inheriter_id::removeGeometry3D(Identifier id) { @@ -549,7 +791,8 @@ void Module3D::type::inheriter_id::removeConstraint3D(Identif template template bool Module3D::type::inheriter_id::hasGeometry3D(Identifier id) { - if(getGeometry3D(id)) return true; + if(getGeometry3D(id)) + return true; return false; }; @@ -560,7 +803,8 @@ Module3D::type::inheriter_id::getGeometry3D(Identifier id) { std::vector< Geom >& vec = inheriter_base::m_this->template objectVector(); typedef typename std::vector::iterator iter; for(iter it=vec.begin(); it!=vec.end(); it++) { - if(compare_traits::compare((*it)->getIdentifier(), id)) return *it; + if(compare_traits::compare((*it)->getIdentifier(), id)) + return *it; }; return Geom(); }; @@ -568,7 +812,8 @@ Module3D::type::inheriter_id::getGeometry3D(Identifier id) { template template bool Module3D::type::inheriter_id::hasConstraint3D(Identifier id) { - if(getConstraint3D(id)) return true; + if(getConstraint3D(id)) + return true; return false; }; @@ -579,7 +824,8 @@ Module3D::type::inheriter_id::getConstraint3D(Identifier id) std::vector< Cons >& vec = inheriter_base::m_this->template objectVector(); typedef typename std::vector::iterator iter; for(iter it=vec.begin(); it!=vec.end(); it++) { - if(compare_traits::compare((*it)->getIdentifier(), id)) return *it; + if(compare_traits::compare((*it)->getIdentifier(), id)) + return *it; }; return Cons(); }; diff --git a/src/Mod/Assembly/App/opendcm/module3d/solver.hpp b/src/Mod/Assembly/App/opendcm/module3d/solver.hpp index 75fc9ff27..6c347e546 100644 --- a/src/Mod/Assembly/App/opendcm/module3d/solver.hpp +++ b/src/Mod/Assembly/App/opendcm/module3d/solver.hpp @@ -22,6 +22,7 @@ #include "defines.hpp" #include "clustermath.hpp" +#include "opendcm/core/clustergraph.hpp" #include "opendcm/core/sheduler.hpp" #include "opendcm/core/traits.hpp" #include @@ -32,17 +33,14 @@ #include #include -#include "Base/Console.h" -#include - namespace dcm { namespace details { template -struct MES : public system_traits::Kernel::MappedEquationSystem { +struct MES : public Sys::Kernel::MappedEquationSystem { - typedef typename system_traits::Kernel Kernel; - typedef typename system_traits::Cluster Cluster; + typedef typename Sys::Kernel Kernel; + typedef typename Sys::Cluster Cluster; typedef typename system_traits::template getModule::type module3d; typedef typename module3d::Geometry3D Geometry3D; typedef boost::shared_ptr Geom; @@ -51,7 +49,7 @@ struct MES : public system_traits::Kernel::MappedEquationSystem { typedef typename module3d::math_prop math_prop; typedef typename module3d::fix_prop fix_prop; typedef typename Kernel::number_type Scalar; - typedef typename system_traits::Kernel::MappedEquationSystem base; + typedef typename Sys::Kernel::MappedEquationSystem Base; boost::shared_ptr m_cluster; @@ -63,8 +61,8 @@ struct MES : public system_traits::Kernel::MappedEquationSystem { template struct SystemSolver : public Job { - typedef typename system_traits::Cluster Cluster; - typedef typename system_traits::Kernel Kernel; + typedef typename Sys::Cluster Cluster; + typedef typename Sys::Kernel Kernel; typedef typename Kernel::number_type Scalar; typedef typename system_traits::template getModule::type module3d; typedef typename module3d::Geometry3D Geometry3D; @@ -127,7 +125,7 @@ struct SystemSolver : public Job { template -MES::MES(boost::shared_ptr cl, int par, int eqn) : base(par, eqn), m_cluster(cl) { +MES::MES(boost::shared_ptr cl, int par, int eqn) : Base(par, eqn), m_cluster(cl) { }; @@ -139,8 +137,8 @@ void MES::recalculate() { std::pair cit = m_cluster->clusters(); for(; cit.first != cit.second; cit.first++) { - if(!(*cit.first).second->template getClusterProperty()) - (*cit.first).second->template getClusterProperty().recalculate(); + if(!(*cit.first).second->template getProperty()) + (*cit.first).second->template getProperty().recalculate(); }; @@ -154,7 +152,7 @@ void MES::recalculate() { std::pair< oiter, oiter > oit = m_cluster->template getObjects(*eit.first); for(; oit.first != oit.second; oit.first++) { if(*oit.first) - (*oit.first)->calculate(base::Scaling, base::rot_only); + (*oit.first)->calculate(Base::Scaling, Base::rot_only); } } }; @@ -162,7 +160,6 @@ void MES::recalculate() { template void MES::removeLocalGradientZeros() { - Base::Console().Message("remove local gradient zero\n"); //let the constraints treat the local zeros typedef typename Cluster::template object_iterator oiter; typedef typename boost::graph_traits::edge_iterator eiter; @@ -178,6 +175,7 @@ void MES::removeLocalGradientZeros() { } }; + template SystemSolver::Rescaler::Rescaler(boost::shared_ptr c, Mes& m) : cluster(c), mes(m), rescales(0) { @@ -198,11 +196,11 @@ typename SystemSolver::Scalar SystemSolver::Rescaler::scaleClusters() Scalar sc = 0; for(cit = cluster->clusters(); cit.first != cit.second; cit.first++) { //fixed cluster are irrelevant for scaling - if((*cit.first).second->template getClusterProperty()) + if((*cit.first).second->template getProperty()) continue; //get the biggest scale factor - details::ClusterMath& math = (*cit.first).second->template getClusterProperty(); + details::ClusterMath& math = (*cit.first).second->template getProperty(); math.m_pseudo.clear(); collectPseudoPoints(cluster, (*cit.first).first, math.m_pseudo); @@ -219,8 +217,8 @@ typename SystemSolver::Scalar SystemSolver::Rescaler::scaleClusters() if(cluster->isCluster(*it.first)) { boost::shared_ptr c = cluster->getVertexCluster(*it.first); - c->template getClusterProperty().applyClusterScale(sc, - c->template getClusterProperty()); + c->template getProperty().applyClusterScale(sc, + c->template getProperty()); } else { Geom g = cluster->template getObject(*it.first); @@ -238,20 +236,20 @@ void SystemSolver::Rescaler::collectPseudoPoints( Eigen::aligned_allocator::Kernel::Vector3> >& vec) { std::vector > vec2; - typedef typename Cluster::template object_iterator c_iter; + typedef typename Cluster::global_edge_iterator c_iter; typedef typename boost::graph_traits::out_edge_iterator e_iter; std::pair it = boost::out_edges(cluster, *parent); for(; it.first != it.second; it.first++) { - std::pair< c_iter, c_iter > cit = parent->template getObjects(*it.first); + std::pair< c_iter, c_iter > cit = parent->template getGlobalEdges(*it.first); for(; cit.first != cit.second; cit.first++) { - Cons c = *(cit.first); + Cons c = parent->template getObject(*cit.first); if(!c) continue; //get the first global vertex and see if we have it in the wanted cluster or not - GlobalVertex v = c->first->template getProperty(); + GlobalVertex v = cit.first->source; std::pair res = parent->getLocalVertex(v); if(!res.second) return; //means the geometry is in non of the clusters which is not allowed @@ -287,8 +285,8 @@ void SystemSolver::solveCluster(boost::shared_ptr cluster, Sys& sy for(; cit.first != cit.second; cit.first++) { boost::shared_ptr c = (*cit.first).second; - if(c->template getClusterProperty() && - c->template getClusterProperty() == details::cluster3D) + if(c->template getProperty() && + c->template getProperty() == details::cluster3D) solveCluster(c, sys); } @@ -338,9 +336,9 @@ void SystemSolver::solveCluster(boost::shared_ptr cluster, Sys& sy if(cluster->isCluster(*it.first)) { boost::shared_ptr c = cluster->getVertexCluster(*it.first); - details::ClusterMath& cm = c->template getClusterProperty(); + details::ClusterMath& cm = c->template getProperty(); //only get maps and propagate downstream if not fixed - if(!c->template getClusterProperty()) { + if(!c->template getProperty()) { //set norm Quaternion as map to the parameter vector int offset_rot = mes.setParameterMap(cm.getNormQuaternionMap(), rotation); //set translation as map to the parameter vector @@ -363,10 +361,7 @@ void SystemSolver::solveCluster(boost::shared_ptr cluster, Sys& sy } else { Geom g = cluster->template getObject(*it.first); - int offset = mes.setParameterMap(g->m_parameterCount, g->getParameterMap()); - g->m_offset = offset; - //init the parametermap with initial values - g->initMap(); + g->initMap(&mes); } } @@ -404,12 +399,17 @@ void SystemSolver::solveCluster(boost::shared_ptr cluster, Sys& sy // always need the full solver power bool has_cycle; cycle_dedector cd(has_cycle); - //create te needed property map, fill it and run the test + //create te needed property maps and fill it property_map vi_map(cluster); - property_map vc_map(cluster); - property_map ec_map(cluster); cluster->initIndexMaps(); - boost::undirected_dfs(*cluster.get(), boost::visitor(cd).vertex_index_map(vi_map).vertex_color_map(vc_map).edge_color_map(ec_map)); + typedef std::map< LocalVertex, boost::default_color_type> vcmap; + typedef std::map< LocalEdge, boost::default_color_type> ecmap; + vcmap v_cm; + ecmap e_cm; + boost::associative_property_map< vcmap > v_cpm(v_cm); + boost::associative_property_map< ecmap > e_cpm(e_cm); + + boost::undirected_dfs(*cluster.get(), boost::visitor(cd).vertex_index_map(vi_map).vertex_color_map(v_cpm).edge_color_map(e_cpm)); bool done = false; if(!has_cycle) { @@ -419,7 +419,7 @@ void SystemSolver::solveCluster(boost::shared_ptr cluster, Sys& sy //cool, lets do uncylic. first all rotational constraints with rotational parameters mes.setAccess(rotation); mes.setGeneralEquationAccess(false); - //solve can be done without catching exceptions, because this only fails if the system is + //solve can be done without catching exceptions, because this only fails if the system in //unsolvable DummyScaler re; Kernel::solve(mes, re); @@ -465,11 +465,11 @@ void SystemSolver::solveCluster(boost::shared_ptr cluster, Sys& sy if(cluster->isCluster(*it.first)) { boost::shared_ptr c = cluster->getVertexCluster(*it.first); if(!cluster->template getSubclusterProperty(*it.first)) - c->template getClusterProperty().finishCalculation(); + c->template getProperty().finishCalculation(); else - c->template getClusterProperty().finishFixCalculation(); + c->template getProperty().finishFixCalculation(); - std::vector& vec = c->template getClusterProperty().getGeometry(); + std::vector& vec = c->template getProperty().getGeometry(); for(typename std::vector::iterator vit = vec.begin(); vit != vec.end(); vit++) (*vit)->finishCalculation(); @@ -481,7 +481,7 @@ void SystemSolver::solveCluster(boost::shared_ptr cluster, Sys& sy } } //we have solved this cluster - cluster->template setClusterProperty(false); + cluster->template setProperty(false); } catch(boost::exception&) { diff --git a/src/Mod/Assembly/App/opendcm/modulePart/module.hpp b/src/Mod/Assembly/App/opendcm/modulePart/module.hpp index 38457fec1..3cf167a1d 100644 --- a/src/Mod/Assembly/App/opendcm/modulePart/module.hpp +++ b/src/Mod/Assembly/App/opendcm/modulePart/module.hpp @@ -70,8 +70,8 @@ struct ModulePart { typedef typename boost::make_variant_over< Typelist >::type Variant; typedef Object base; - typedef typename system_traits::Kernel Kernel; - typedef typename system_traits::Cluster Cluster; + typedef typename Sys::Kernel Kernel; + typedef typename Sys::Cluster Cluster; typedef typename Kernel::number_type Scalar; typedef typename Kernel::Transform3D Transform; @@ -117,12 +117,9 @@ struct ModulePart { template void set(const T& geometry); - //access the parts transformation template T& get(); - //get the transformation from part local to overall global. In multi layer systems - //this means the successive transformation from this part to the toplevel cluster template T getGlobal(); @@ -187,7 +184,7 @@ struct ModulePart { void setTransformation(const T& geom) { typedef typename system_traits::template getModule::type module3d; - details::ClusterMath& cm = ((Sys*)this)->m_cluster->template getClusterProperty(); + details::ClusterMath& cm = ((Sys*)this)->m_cluster->template getProperty(); (typename geometry_traits::modell()).template extract::accessor >(geom, cm.getTransform()); @@ -204,7 +201,7 @@ struct ModulePart { void getTransformation(T& geom) { typedef typename system_traits::template getModule::type module3d; - details::ClusterMath& cm = ((Sys*)this)->m_cluster->template getClusterProperty(); + details::ClusterMath& cm = ((Sys*)this)->m_cluster->template getProperty(); (typename geometry_traits::modell()).template inject::accessor >(geom, cm.getTransform()); @@ -215,7 +212,7 @@ struct ModulePart { //function object to emit remove signal too al geometry which is deleted by part deletion struct remover { - typedef typename system_traits::Cluster Cluster; + typedef typename Sys::Cluster Cluster; typedef typename system_traits::template getModule::type module3d; typedef typename module3d::Geometry3D Geometry3D; typedef boost::shared_ptr Geom; @@ -244,11 +241,12 @@ struct ModulePart { typedef mpl::vector0<> properties; typedef mpl::vector1 objects; + typedef mpl::vector0<> geometries; struct PrepareCluster : public Job { - typedef typename system_traits::Cluster Cluster; - typedef typename system_traits::Kernel Kernel; + typedef typename Sys::Cluster Cluster; + typedef typename Sys::Kernel Kernel; typedef typename system_traits::template getModule::type module3d; PrepareCluster(); @@ -257,8 +255,8 @@ struct ModulePart { struct EvaljuateCluster : public Job { - typedef typename system_traits::Cluster Cluster; - typedef typename system_traits::Kernel Kernel; + typedef typename Sys::Cluster Cluster; + typedef typename Sys::Kernel Kernel; typedef typename system_traits::template getModule::type module3d; EvaljuateCluster(); @@ -286,10 +284,10 @@ ModulePart::type::Part_base::Part_base(const T& geometry, Sys (typename geometry_traits::modell()).template extract::accessor >(geometry, m_transform); - cluster->template setClusterProperty(false); + cluster->template setProperty(false); //the the clustermath transform - m_cluster->template getClusterProperty().getTransform() = m_transform; + m_cluster->template getProperty().getTransform() = m_transform; #ifdef USE_LOGGING BOOST_LOG(log) << "Init: "< typename ModulePart::template type::Part_base::Geom ModulePart::type::Part_base::addGeometry3D(const T& geom, CoordinateFrame frame) { Geom g(new Geometry3D(geom, *m_system)); - if(frame == Local) { //we need to collect all transforms up to this part! - Transform t; + Transform t;//(m_transform); transform_traverse(t, m_cluster); g->transform(t); @@ -328,10 +325,10 @@ ModulePart::type::Part_base::addGeometry3D(const T& geom, Coo template template -void ModulePart::type::Part_base::transform_traverse(typename ModulePart::template type::Part_base::Transform& t, - boost::shared_ptr::template type::Part_base::Cluster> c) { +void ModulePart::type::Part_base::transform_traverse(ModulePart::type::Part_base::Transform& t, + boost::shared_ptr::type::Part_base::Cluster> c) { - t *= c->template getClusterProperty().m_transform; + t *= c->template getProperty().m_transform; if(c->isRoot()) return; @@ -349,6 +346,7 @@ void ModulePart::type::Part_base::set(const T& geometry) { //set the clustermath transform m_cluster->template getClusterProperty().getTransform() = m_transform; + }; template @@ -419,7 +417,7 @@ void ModulePart::type::Part_base::finishCalculation() { template template void ModulePart::type::Part_base::fix(bool fix_value) { - m_cluster->template setClusterProperty(fix_value); + m_cluster->template setProperty(fix_value); }; template @@ -502,14 +500,14 @@ template typename ModulePart::template type::Partptr ModulePart::type::inheriter_base::createPart(const T& geometry) { - typedef typename system_traits::Cluster Cluster; + typedef typename Sys::Cluster Cluster; std::pair, LocalVertex> res = m_this->m_cluster->createCluster(); Partptr p(new Part(geometry, * ((Sys*) this), res.first)); m_this->m_cluster->template setObject (res.second, p); m_this->push_back(p); - res.first->template setClusterProperty(clusterPart); + res.first->template setProperty(clusterPart); return p; }; @@ -598,7 +596,7 @@ void ModulePart::type::PrepareCluster::execute(Sys& sys) { typedef typename std::vector::iterator iter; for(iter it = sys.template begin(); it != sys.template end(); it++) { - details::ClusterMath& cm = (*it)->m_cluster->template getClusterProperty(); + details::ClusterMath& cm = (*it)->m_cluster->template getProperty(); cm.getTransform() = (*it)->m_transform; }; }; @@ -616,7 +614,7 @@ void ModulePart::type::EvaljuateCluster::execute(Sys& sys) { typedef typename std::vector::iterator iter; for(iter it = sys.template begin(); it != sys.template end(); it++) { - details::ClusterMath& cm = (*it)->m_cluster->template getClusterProperty(); + details::ClusterMath& cm = (*it)->m_cluster->template getProperty(); (*it)->m_transform = cm.getTransform(); (*it)->finishCalculation(); }; @@ -629,5 +627,3 @@ void ModulePart::type::EvaljuateCluster::execute(Sys& sys) { - - diff --git a/src/Mod/Assembly/App/opendcm/moduleState/extractor.hpp b/src/Mod/Assembly/App/opendcm/moduleState/extractor.hpp index ad740c7b7..22485512b 100644 --- a/src/Mod/Assembly/App/opendcm/moduleState/extractor.hpp +++ b/src/Mod/Assembly/App/opendcm/moduleState/extractor.hpp @@ -81,7 +81,7 @@ struct Injector { void setClusterProperties(typename Sys::Cluster* cluster, typename details::pts::type& prop) { - cluster->m_cluster_bundle = prop; + cluster->m_properties = prop; }; void setVertexProperties(typename Sys::Cluster* cluster, LocalVertex v, typename details::pts::type& prop) { @@ -101,13 +101,13 @@ struct Injector { fusion::at_c<1>(cluster->operator[](e)) = bundles; }; void setVertexProperty(typename Sys::Cluster* cluster, int value) { - cluster->template setClusterProperty(value); + cluster->template setProperty(value); }; void addClusters(std::vector& clusters, typename Sys::Cluster* cluster) { typename std::vector::iterator it; for(it = clusters.begin(); it != clusters.end(); it++) { - LocalVertex v = cluster->getLocalVertex((*it)->template getClusterProperty()).first; + LocalVertex v = cluster->getLocalVertex((*it)->template getProperty()).first; cluster->m_clusters[v] = boost::shared_ptr(*it); }; }; diff --git a/src/Mod/Assembly/App/opendcm/moduleState/generator.hpp b/src/Mod/Assembly/App/opendcm/moduleState/generator.hpp index d55d2c83d..8ab4b53df 100644 --- a/src/Mod/Assembly/App/opendcm/moduleState/generator.hpp +++ b/src/Mod/Assembly/App/opendcm/moduleState/generator.hpp @@ -56,7 +56,7 @@ template struct generator : karma::grammar { typedef typename Sys::Cluster graph; - typedef typename graph::cluster_bundle graph_bundle; + typedef typename graph::Properties graph_bundle; typedef typename boost::graph_traits::vertex_iterator viter; typedef typename boost::graph_traits::edge_iterator eiter; diff --git a/src/Mod/Assembly/App/opendcm/moduleState/generator_imp.hpp b/src/Mod/Assembly/App/opendcm/moduleState/generator_imp.hpp index f7bb6bc6b..3dc441ed8 100644 --- a/src/Mod/Assembly/App/opendcm/moduleState/generator_imp.hpp +++ b/src/Mod/Assembly/App/opendcm/moduleState/generator_imp.hpp @@ -32,7 +32,7 @@ BOOST_FUSION_ADAPT_TPL_STRUCT( (T1)(T2)(T3)(T4), (dcm::ClusterGraph) (T1)(T2)(T3)(T4), (int, test) - (typename dcm::details::pts::type, m_cluster_bundle)) + (typename dcm::details::pts::type, m_properties)) namespace boost { namespace spirit { namespace traits diff --git a/src/Mod/Assembly/App/opendcm/moduleState/object_generator.hpp b/src/Mod/Assembly/App/opendcm/moduleState/object_generator.hpp index 9c42fd515..4a18e6691 100644 --- a/src/Mod/Assembly/App/opendcm/moduleState/object_generator.hpp +++ b/src/Mod/Assembly/App/opendcm/moduleState/object_generator.hpp @@ -21,10 +21,10 @@ namespace details { struct obj_grammar : public karma::grammar()> { typename Gen::generator subrule; karma::rule()> start; - details::prop_gen prop; + details::prop_gen prop; obj_grammar(); - static void getProperties(boost::shared_ptr ptr, typename details::pts::type& seq); + static void getProperties(boost::shared_ptr ptr, typename details::pts::type& seq); }; //when objects should not be generated we need to get a empy rule, as obj_rule_init diff --git a/src/Mod/Assembly/App/opendcm/moduleState/object_generator_imp.hpp b/src/Mod/Assembly/App/opendcm/moduleState/object_generator_imp.hpp index df6491e46..a90fc5536 100644 --- a/src/Mod/Assembly/App/opendcm/moduleState/object_generator_imp.hpp +++ b/src/Mod/Assembly/App/opendcm/moduleState/object_generator_imp.hpp @@ -29,7 +29,7 @@ obj_grammar::obj_grammar() : obj_grammar::base }; template -void obj_grammar::getProperties(boost::shared_ptr ptr, typename details::pts::type& seq) { +void obj_grammar::getProperties(boost::shared_ptr ptr, typename details::pts::type& seq) { if(ptr) seq = ptr->m_properties; else { diff --git a/src/Mod/Assembly/App/opendcm/moduleState/object_parser.hpp b/src/Mod/Assembly/App/opendcm/moduleState/object_parser.hpp index a2d669c34..86a5d1096 100644 --- a/src/Mod/Assembly/App/opendcm/moduleState/object_parser.hpp +++ b/src/Mod/Assembly/App/opendcm/moduleState/object_parser.hpp @@ -34,11 +34,11 @@ template struct obj_parser : public qi::grammar::type*, Sys*), qi::space_type> { typename Par::parser subrule; qi::rule::type*, Sys*), qi::space_type> start; - prop_par prop; + prop_par prop; obj_parser(); - static void setProperties(boost::shared_ptr ptr, typename details::pts::type& seq); + static void setProperties(boost::shared_ptr ptr, typename details::pts::type& seq); }; //when objects should not be generated we need to get a empy rule, as obj_rule_init diff --git a/src/Mod/Assembly/App/opendcm/moduleState/object_parser_imp.hpp b/src/Mod/Assembly/App/opendcm/moduleState/object_parser_imp.hpp index 268979c5f..0c7a51b13 100644 --- a/src/Mod/Assembly/App/opendcm/moduleState/object_parser_imp.hpp +++ b/src/Mod/Assembly/App/opendcm/moduleState/object_parser_imp.hpp @@ -57,7 +57,7 @@ obj_parser::obj_parser(): obj_parser::base_type(start }; template -void obj_parser::setProperties(boost::shared_ptr ptr, typename details::pts::type& seq) { +void obj_parser::setProperties(boost::shared_ptr ptr, typename details::pts::type& seq) { if(ptr) ptr->m_properties = seq; }; diff --git a/src/Mod/Assembly/App/opendcm/moduleState/parser_imp.hpp b/src/Mod/Assembly/App/opendcm/moduleState/parser_imp.hpp index 605c50664..22c490dbe 100644 --- a/src/Mod/Assembly/App/opendcm/moduleState/parser_imp.hpp +++ b/src/Mod/Assembly/App/opendcm/moduleState/parser_imp.hpp @@ -31,7 +31,7 @@ BOOST_FUSION_ADAPT_TPL_STRUCT( (T1)(T2)(T3)(T4), (dcm::ClusterGraph) (T1)(T2)(T3)(T4), - (typename dcm::details::pts::type, m_cluster_bundle)) + (typename dcm::details::pts::type, m_properties)) #include "parser.hpp" diff --git a/src/Mod/Assembly/App/opendcm/moduleState/property_parser.hpp b/src/Mod/Assembly/App/opendcm/moduleState/property_parser.hpp index be8956505..3079b04d2 100644 --- a/src/Mod/Assembly/App/opendcm/moduleState/property_parser.hpp +++ b/src/Mod/Assembly/App/opendcm/moduleState/property_parser.hpp @@ -59,7 +59,7 @@ struct prop_parser_fold : mpl::fold< seq, state, mpl::push_back > >, mpl::_1 > > {}; -//grammar for a fusion sequence of properties. currently max. 10 properties are supported +//grammar for a fusion sequence of properties. template struct prop_par : qi::grammar::type(), qi::space_type> {