1 // g2o - General Graph Optimization
2 // Copyright (C) 2011 R. Kuemmerle, G. Grisetti, W. Burgard
3 // All rights reserved.
4 //
5 // Redistribution and use in source and binary forms, with or without
6 // modification, are permitted provided that the following conditions are
7 // met:
8 //
9 // * Redistributions of source code must retain the above copyright notice,
10 //   this list of conditions and the following disclaimer.
11 // * Redistributions in binary form must reproduce the above copyright
12 //   notice, this list of conditions and the following disclaimer in the
13 //   documentation and/or other materials provided with the distribution.
14 //
15 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
16 // IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
17 // TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
18 // PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
19 // HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
21 // TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
22 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
23 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
24 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 
27 #include "hyper_graph_action.h"
28 #include "optimizable_graph.h"
29 #include "cache.h"
30 #include "g2o/stuff/macros.h"
31 
32 
33 #include <iostream>
34 #include <list>
35 
36 namespace g2o {
37   using namespace std;
38 
39   HyperGraphActionLibrary* HyperGraphActionLibrary::actionLibInstance = 0;
40 
~Parameters()41   HyperGraphAction::Parameters::~Parameters()
42   {
43   }
44 
ParametersIteration(int iter)45   HyperGraphAction::ParametersIteration::ParametersIteration(int iter) :
46     HyperGraphAction::Parameters(),
47     iteration(iter)
48   {
49   }
50 
~HyperGraphAction()51   HyperGraphAction::~HyperGraphAction()
52   {
53   }
54 
operator ()(const HyperGraph *,Parameters *)55   HyperGraphAction* HyperGraphAction::operator()(const HyperGraph*, Parameters*)
56   {
57     return nullptr;
58   }
59 
~Parameters()60   HyperGraphElementAction::Parameters::~Parameters()
61   {
62   }
63 
HyperGraphElementAction(const std::string & typeName_)64   HyperGraphElementAction::HyperGraphElementAction(const std::string& typeName_) : _typeName(typeName_) {}
65 
setTypeName(const std::string & typeName_)66   void HyperGraphElementAction::setTypeName(const std::string& typeName_)
67   {
68     _typeName = typeName_;
69   }
70 
71 
operator ()(HyperGraph::HyperGraphElement *,HyperGraphElementAction::Parameters *)72   HyperGraphElementAction* HyperGraphElementAction::operator()(HyperGraph::HyperGraphElement* , HyperGraphElementAction::Parameters* )
73   {
74     return nullptr;
75   }
76 
operator ()(const HyperGraph::HyperGraphElement *,HyperGraphElementAction::Parameters *)77   HyperGraphElementAction* HyperGraphElementAction::operator()(const HyperGraph::HyperGraphElement* , HyperGraphElementAction::Parameters* )
78   {
79     return nullptr;
80   }
81 
~HyperGraphElementAction()82   HyperGraphElementAction::~HyperGraphElementAction()
83   {
84   }
85 
HyperGraphElementActionCollection(const std::string & name_)86   HyperGraphElementActionCollection::HyperGraphElementActionCollection(const std::string& name_)
87   {
88     _name = name_;
89   }
90 
~HyperGraphElementActionCollection()91   HyperGraphElementActionCollection::~HyperGraphElementActionCollection()
92   {
93     for (ActionMap::iterator it = _actionMap.begin(); it != _actionMap.end(); ++it) {
94       delete it->second;
95     }
96   }
97 
operator ()(HyperGraph::HyperGraphElement * element,HyperGraphElementAction::Parameters * params)98   HyperGraphElementAction* HyperGraphElementActionCollection::operator()(HyperGraph::HyperGraphElement* element, HyperGraphElementAction::Parameters* params)
99   {
100     ActionMap::iterator it=_actionMap.find(typeid(*element).name());
101     //cerr << typeid(*element).name() << endl;
102     if (it==_actionMap.end())
103       return nullptr;
104     HyperGraphElementAction* action=it->second;
105     return (*action)(element, params);
106   }
107 
operator ()(const HyperGraph::HyperGraphElement * element,HyperGraphElementAction::Parameters * params)108   HyperGraphElementAction* HyperGraphElementActionCollection::operator()(const HyperGraph::HyperGraphElement* element, HyperGraphElementAction::Parameters* params)
109   {
110     ActionMap::iterator it=_actionMap.find(typeid(*element).name());
111     if (it==_actionMap.end())
112       return nullptr;
113     HyperGraphElementAction* action=it->second;
114     return (*action)(element, params);
115   }
116 
registerAction(HyperGraphElementAction * action)117   bool HyperGraphElementActionCollection::registerAction(HyperGraphElementAction* action)
118   {
119 #  ifdef G2O_DEBUG_ACTIONLIB
120     cerr << __PRETTY_FUNCTION__ << " " << action->name() << " " << action->typeName() << endl;
121 #  endif
122     if (action->name()!=name()){
123       cerr << __PRETTY_FUNCTION__  << ": invalid attempt to register an action in a collection with a different name " <<  name() << " " << action->name() << endl;
124     }
125     _actionMap.insert(make_pair ( action->typeName(), action) );
126     return true;
127   }
128 
unregisterAction(HyperGraphElementAction * action)129   bool HyperGraphElementActionCollection::unregisterAction(HyperGraphElementAction* action)
130   {
131     for (HyperGraphElementAction::ActionMap::iterator it=_actionMap.begin(); it != _actionMap.end(); ++it) {
132       if (it->second == action){
133         _actionMap.erase(it);
134         return true;
135       }
136     }
137     return false;
138   }
139 
HyperGraphActionLibrary()140   HyperGraphActionLibrary::HyperGraphActionLibrary()
141   {
142   }
143 
instance()144   HyperGraphActionLibrary* HyperGraphActionLibrary::instance()
145   {
146     if (actionLibInstance == 0) {
147       actionLibInstance = new HyperGraphActionLibrary;
148     }
149     return actionLibInstance;
150   }
151 
destroy()152   void HyperGraphActionLibrary::destroy()
153   {
154     delete actionLibInstance;
155     actionLibInstance = 0;
156   }
157 
~HyperGraphActionLibrary()158   HyperGraphActionLibrary::~HyperGraphActionLibrary()
159   {
160     // memory is freed by Proxy
161     //for (HyperGraphElementAction::ActionMap::iterator it = _actionMap.begin(); it != _actionMap.end(); ++it) {
162       //delete it->second;
163     //}
164   }
165 
actionByName(const std::string & name)166   HyperGraphElementAction* HyperGraphActionLibrary::actionByName(const std::string& name)
167   {
168     HyperGraphElementAction::ActionMap::iterator it=_actionMap.find(name);
169     if (it!=_actionMap.end())
170       return it->second;
171     return nullptr;
172   }
173 
registerAction(HyperGraphElementAction * action)174   bool HyperGraphActionLibrary::registerAction(HyperGraphElementAction* action)
175   {
176     HyperGraphElementAction* oldAction = actionByName(action->name());
177     HyperGraphElementActionCollection* collection = 0;
178     if (oldAction) {
179       collection = dynamic_cast<HyperGraphElementActionCollection*>(oldAction);
180       if (! collection) {
181         cerr << __PRETTY_FUNCTION__ << ": fatal error, a collection is not at the first level in the library" << endl;
182         return false;
183       }
184     }
185     if (! collection) {
186 #ifdef G2O_DEBUG_ACTIONLIB
187       cerr << __PRETTY_FUNCTION__ << ": creating collection for \"" << action->name() << "\"" << endl;
188 #endif
189       collection = new HyperGraphElementActionCollection(action->name());
190       _actionMap.insert(make_pair(action->name(), collection));
191     }
192     return collection->registerAction(action);
193   }
194 
unregisterAction(HyperGraphElementAction * action)195   bool HyperGraphActionLibrary::unregisterAction(HyperGraphElementAction* action)
196   {
197     list<HyperGraphElementActionCollection*> collectionDeleteList;
198 
199     // Search all the collections and delete the registered actions; if a collection becomes empty, schedule it for deletion; note that we can't delete the collections as we go because this will screw up the state of the iterators
200     for (HyperGraphElementAction::ActionMap::iterator it=_actionMap.begin(); it != _actionMap.end(); ++it) {
201       HyperGraphElementActionCollection* collection = dynamic_cast<HyperGraphElementActionCollection*> (it->second);
202       if (collection != 0) {
203         collection->unregisterAction(action);
204         if (collection->actionMap().size() == 0) {
205           collectionDeleteList.push_back(collection);
206         }
207       }
208     }
209 
210     // Delete any empty action collections
211     for (list<HyperGraphElementActionCollection*>::iterator itc = collectionDeleteList.begin(); itc != collectionDeleteList.end(); ++itc) {
212       //cout << "Deleting collection " << (*itc)->name() << endl;
213       _actionMap.erase((*itc)->name());
214     }
215 
216     return true;
217   }
218 
219 
WriteGnuplotAction(const std::string & typeName_)220   WriteGnuplotAction::WriteGnuplotAction(const std::string& typeName_)
221     : HyperGraphElementAction(typeName_)
222   {
223     _name="writeGnuplot";
224   }
225 
Parameters()226   DrawAction::Parameters::Parameters(){
227   }
228 
DrawAction(const std::string & typeName_)229   DrawAction::DrawAction(const std::string& typeName_)
230     : HyperGraphElementAction(typeName_)
231   {
232     _name="draw";
233     _previousParams = (Parameters*)0x42;
234     refreshPropertyPtrs(0);
235     _cacheDrawActions = 0;
236   }
237 
refreshPropertyPtrs(HyperGraphElementAction::Parameters * params_)238   bool DrawAction::refreshPropertyPtrs(HyperGraphElementAction::Parameters* params_){
239     if (_previousParams == params_)
240       return false;
241     DrawAction::Parameters* p=dynamic_cast<DrawAction::Parameters*>(params_);
242     if (! p){
243       _previousParams = 0;
244       _show = 0;
245       _showId = 0;
246     } else {
247       _previousParams = p;
248       _show = p->makeProperty<BoolProperty>(_typeName+"::SHOW", true);
249       _showId = p->makeProperty<BoolProperty>(_typeName+"::SHOW_ID", false);
250     }
251     return true;
252   }
253 
initializeDrawActionsCache()254   void DrawAction::initializeDrawActionsCache() {
255     if (! _cacheDrawActions){
256       _cacheDrawActions = HyperGraphActionLibrary::instance()->actionByName("draw");
257     }
258   }
259 
drawCache(CacheContainer * caches,HyperGraphElementAction::Parameters * params_)260   void DrawAction::drawCache(CacheContainer* caches, HyperGraphElementAction::Parameters* params_) {
261     if (caches){
262       for (CacheContainer::iterator it=caches->begin(); it!=caches->end(); ++it){
263         Cache* c = it->second;
264         (*_cacheDrawActions)(c, params_);
265       }
266     }
267   }
268 
drawUserData(HyperGraph::Data * data,HyperGraphElementAction::Parameters * params_)269   void DrawAction::drawUserData(HyperGraph::Data* data, HyperGraphElementAction::Parameters* params_){
270     while (data && _cacheDrawActions ){
271       (*_cacheDrawActions)(data, params_);
272       data=data->next();
273     }
274   }
275 
applyAction(HyperGraph * graph,HyperGraphElementAction * action,HyperGraphElementAction::Parameters * params,const std::string & typeName)276   void applyAction(HyperGraph* graph, HyperGraphElementAction* action, HyperGraphElementAction::Parameters* params, const std::string& typeName)
277   {
278     for (HyperGraph::VertexIDMap::iterator it=graph->vertices().begin();
279         it!=graph->vertices().end(); ++it){
280       auto& aux = *it->second;
281       if ( typeName.empty() || typeid(aux).name()==typeName){
282         (*action)(it->second, params);
283       }
284     }
285     for (HyperGraph::EdgeSet::iterator it=graph->edges().begin();
286         it!=graph->edges().end(); ++it){
287       auto& aux = **it;
288       if ( typeName.empty() || typeid(aux).name()==typeName)
289         (*action)(*it, params);
290     }
291   }
292 
293 } // end namespace
294