1 /****************************************************************************
2  *
3  * ViSP, open source Visual Servoing Platform software.
4  * Copyright (C) 2005 - 2019 by Inria. All rights reserved.
5  *
6  * This software is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  * See the file LICENSE.txt at the root directory of this source
11  * distribution for additional information about the GNU GPL.
12  *
13  * For using ViSP with software that can not be combined with the GNU
14  * GPL, please contact Inria about acquiring a ViSP Professional
15  * Edition License.
16  *
17  * See http://visp.inria.fr for more information.
18  *
19  * This software was developed at:
20  * Inria Rennes - Bretagne Atlantique
21  * Campus Universitaire de Beaulieu
22  * 35042 Rennes Cedex
23  * France
24  *
25  * If you have questions regarding the use of this file, please contact
26  * Inria at visp@inria.fr
27  *
28  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
29  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
30  *
31  * Description:
32  * Pseudo-database used to handle dependencies between moments
33  *
34  * Authors:
35  * Filip Novotny
36  *
37  *****************************************************************************/
38 /*!
39   \file vpMomentDatabase.h
40   \brief Pseudo-database used to handle dependencies between moments.
41 */
42 #ifndef _vpMomentDatabase_h_
43 #define _vpMomentDatabase_h_
44 
45 #include <visp3/core/vpImage.h>
46 
47 #include <cstring>
48 #include <iostream>
49 #include <map>
50 
51 class vpMoment;
52 class vpMomentObject;
53 
54 /*!
55   \class vpMomentDatabase
56 
57   \ingroup group_core_moments
58 
59   \brief This class allows to register all vpMoments so they can access each
60 other according to their dependencies.
61 
62   Sometimes, a moment needs to have access to other moment's values to be
63 computed. For example vpMomentCentered needs additionnal information about the
64 gravity center vpMomentGravityCenter in order to compute the moment's value
65 from a vpMomentObject. This gravity center should be stored in a
66 vpMomentDatabase where it can be accessed.
67 
68   All moments in a database can access each other freely at any time. They can
69 also verify if a moment is present in the database or not. Here is a example
70 of a dependency between two moments using a vpMomentDatabase:
71 
72 \code
73 #include <visp3/core/vpMomentObject.h>
74 #include <visp3/core/vpPoint.h>
75 #include <visp3/core/vpMomentGravityCenter.h>
76 #include <visp3/core/vpMomentDatabase.h>
77 #include <visp3/core/vpMomentCentered.h>
78 #include <iostream>
79 
80 int main()
81 {
82   vpPoint p;
83   std::vector<vpPoint> vec_p; // vector that contains the vertices of the contour polygon
84 
85   p.set_x(1); p.set_y(1); // coordinates in meters in the image plane (vertex 1)
86   vec_p.push_back(p);
87   p.set_x(2); p.set_y(2); // coordinates in meters in the image plane (vertex 2)
88   vec_p.push_back(p);
89   vpMomentObject obj(1); // Create an image moment object with 1 as
90        // maximum order (sufficient for gravity center)
91   obj.setType(vpMomentObject::DISCRETE); // The object is defined by
92            // two discrete points
93   obj.fromVector(vec_p); // Init the dense object with the polygon
94 
95   vpMomentDatabase db;
96   vpMomentGravityCenter g; // declaration of gravity center
97   vpMomentCentered mc; // mc containts centered moments
98 
99   g.linkTo(db); //add gravity center to database
100   mc.linkTo(db); //centered moments depend on gravity, add them to the
101      //database to grant access
102 
103   db.updateAll(obj); // All of the moments must be updated, not just mc
104 
105   //There is no global compute method since the order of compute calls
106   //depends on the implementation
107   g.compute(); // compute the moment
108   mc.compute(); //compute centered moments AFTER gravity center
109 
110   std::cout << "Gravity center: " << g << std:: endl; // print gravity center moment
111   std::cout << "Centered moments: " << mc << std:: endl; // print centered moment
112 
113   return 0;
114 }
115   \endcode
116 
117   The following code outputs:
118   \code
119 Gravity center:
120 Xg=1.5, Yg=1.5
121 Centered moments:
122 2	0
123 0	x
124   \endcode
125 
126   A moment is identified in the database by it's vpMoment::name method.
127 Consequently, a database can contain at most one moment of each type. Often it
128 is useful to update all moments with the same object. Shortcuts
129 (vpMomentDatabase::updateAll) are provided for that matter.
130 */
131 class VISP_EXPORT vpMomentDatabase
132 {
133 private:
134 #ifndef DOXYGEN_SHOULD_SKIP_THIS
135   struct cmp_str {
operatorcmp_str136     bool operator()(char const *a, char const *b) const { return std::strcmp(a, b) < 0; }
137   };
138 #endif
139   std::map<const char *, vpMoment *, cmp_str> moments;
140   void add(vpMoment &moment, const char *name);
141 
142 public:
vpMomentDatabase()143   vpMomentDatabase() : moments() {}
~vpMomentDatabase()144   virtual ~vpMomentDatabase() {}
145 
146   /** @name Inherited functionalities from vpMomentDatabase */
147   //@{
148   const vpMoment &get(const char *type, bool &found) const;
149   /*!
150     Get the first element in the database.
151     May be useful in case an unnamed object is present but is the only element
152     in the database. \return the first element in the database.
153     */
get_first()154   vpMoment &get_first() { return *(moments.begin()->second); }
155 
156   virtual void updateAll(vpMomentObject &object);
157   //@}
158 
159   friend class vpMoment;
160   friend VISP_EXPORT std::ostream &operator<<(std::ostream &os, const vpMomentDatabase &v);
161 };
162 
163 #endif
164