Visual Servoing Platform  version 3.6.1 under development (2024-11-15)
vpRectOriented.cpp
1 /*
2  * ViSP, open source Visual Servoing Platform software.
3  * Copyright (C) 2005 - 2024 by Inria. All rights reserved.
4  *
5  * This software is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  * See the file LICENSE.txt at the root directory of this source
10  * distribution for additional information about the GNU GPL.
11  *
12  * For using ViSP with software that can not be combined with the GNU
13  * GPL, please contact Inria about acquiring a ViSP Professional
14  * Edition License.
15  *
16  * See https://visp.inria.fr for more information.
17  *
18  * This software was developed at:
19  * Inria Rennes - Bretagne Atlantique
20  * Campus Universitaire de Beaulieu
21  * 35042 Rennes Cedex
22  * France
23  *
24  * If you have questions regarding the use of this file, please contact
25  * Inria at visp@inria.fr
26  *
27  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
28  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
29  *
30  * Description:
31  * Defines a (possibly oriented) rectangle in the plane.
32  */
33 #include <visp3/core/vpRectOriented.h>
34 
35 #include <cmath>
36 
37 BEGIN_VISP_NAMESPACE
40  : m_center(), m_width(), m_height(), m_theta(), m_topLeft(), m_topRight(), m_bottomLeft(), m_bottomRight()
41 { }
42 
49 vpRectOriented::vpRectOriented(const vpImagePoint &center, double width, double height, double theta)
50 {
51  m_center = center;
52  m_width = width;
53  m_height = height;
54  m_theta = theta;
55  m_topLeft.set_i(m_center.get_i() - ((m_height * cos(m_theta)) / 2.0) - ((m_width * sin(m_theta)) / 2.0));
56  m_topLeft.set_j((m_center.get_j() + ((m_height * sin(m_theta)) / 2.0)) - ((m_width * cos(m_theta)) / 2.0));
57  m_bottomLeft.set_i((m_center.get_i() + ((m_height * cos(m_theta)) / 2.0)) - ((m_width * sin(m_theta)) / 2.0));
58  m_bottomLeft.set_j(m_center.get_j() - ((m_height * sin(m_theta)) / 2.0) - ((m_width * cos(m_theta)) / 2.0));
59  m_bottomRight.set_i(m_center.get_i() + ((m_height * cos(m_theta)) / 2.0) + ((m_width * sin(m_theta)) / 2.0));
60  m_bottomRight.set_j((m_center.get_j() - ((m_height * sin(m_theta)) / 2.0)) + ((m_width * cos(m_theta)) / 2.0));
61  m_topRight.set_i((m_center.get_i() - ((m_height * cos(m_theta)) / 2.0)) + ((m_width * sin(m_theta)) / 2.0));
62  m_topRight.set_j(m_center.get_j() + ((m_height * sin(m_theta)) / 2.0) + ((m_width * cos(m_theta)) / 2.0));
63 }
64 
69 {
70  m_center = rect.getCenter();
71  m_width = rect.getWidth();
72  m_height = rect.getHeight();
73  m_theta = .0;
74  m_topLeft.set_i(m_center.get_i() - (m_height / 2.0));
75  m_topLeft.set_j(m_center.get_j() - (m_width / 2.0));
76  m_bottomLeft.set_i(m_center.get_i() + (m_height / 2.0));
77  m_bottomLeft.set_j(m_center.get_j() - (m_width / 2.0));
78  m_bottomRight.set_i(m_center.get_i() + (m_height / 2.0));
79  m_bottomRight.set_j(m_center.get_j() + (m_width / 2.0));
80  m_topRight.set_i(m_center.get_i() - (m_height / 2.0));
81  m_topRight.set_j(m_center.get_j() + (m_width / 2.0));
82 }
83 
84 #if (VISP_CXX_STANDARD == VISP_CXX_STANDARD_98)
88 vpRectOriented::vpRectOriented(const vpRectOriented &rectOriented) { *this = rectOriented; }
89 
94 {
95  m_center = rectOriented.getCenter();
96  m_width = rectOriented.getWidth();
97  m_height = rectOriented.getHeight();
98  m_theta = rectOriented.getOrientation();
99  m_topLeft = rectOriented.getTopLeft();
100  m_bottomLeft = rectOriented.getBottomLeft();
101  m_bottomRight = rectOriented.getBottomRight();
102  m_topRight = rectOriented.getTopRight();
103  return *this;
104 }
105 #endif
106 
111 {
112  m_center = rect.getCenter();
113  m_width = rect.getWidth();
114  m_height = rect.getHeight();
115  m_theta = .0;
116  m_topLeft.set_i(m_center.get_i() - (m_height / 2.0));
117  m_topLeft.set_j(m_center.get_j() - (m_width / 2.0));
118  m_bottomLeft.set_i(m_center.get_i() + (m_height / 2.0));
119  m_bottomLeft.set_j(m_center.get_j() - (m_width / 2.0));
120  m_bottomRight.set_i(m_center.get_i() + (m_height / 2.0));
121  m_bottomRight.set_j(m_center.get_j() + (m_width / 2.0));
122  m_topRight.set_i(m_center.get_i() - (m_height / 2.0));
123  m_topRight.set_j(m_center.get_j() + (m_width / 2.0));
124  return *this;
125 }
126 
127 #if (VISP_CXX_STANDARD >= VISP_CXX_STANDARD_11)
131 vpRectOriented::operator vpRect()
132 {
133  if (std::fabs(m_theta) > std::numeric_limits<double>::epsilon()) {
134  throw(vpException(vpException::badValue, "Cannot convert a vpRectOriented with non-zero orientation to a vpRect"));
135  }
136 
137  return vpRect(m_topLeft, m_bottomRight);
138 }
139 #endif
140 
145 void vpRectOriented::setPoints(const vpImagePoint &topLeft, const vpImagePoint &topRight,
146  const vpImagePoint &bottomLeft, const vpImagePoint &bottomRight)
147 {
148  m_topLeft = topLeft;
149  m_bottomLeft = bottomLeft;
150  m_bottomRight = bottomRight;
151  m_topRight = topRight;
152  m_center.set_i((m_topLeft.get_i() + m_bottomLeft.get_i() + m_bottomRight.get_i() + m_topRight.get_i()) / 4.0);
153  m_center.set_j((m_topLeft.get_j() + m_bottomLeft.get_j() + m_bottomRight.get_j() + m_topRight.get_j()) / 4.0);
154  m_width = sqrt(((m_topRight.get_i() - m_topLeft.get_i()) * (m_topRight.get_i() - m_topLeft.get_i())) +
155  ((m_topRight.get_j() - m_topLeft.get_j()) * (m_topRight.get_j() - m_topLeft.get_j())));
156  m_height = sqrt(((m_bottomLeft.get_i() - m_topLeft.get_i()) * (m_bottomLeft.get_i() - m_topLeft.get_i())) +
157  ((m_bottomLeft.get_j() - m_topLeft.get_j()) * (m_bottomLeft.get_j() - m_topLeft.get_j())));
158  m_theta = atan2(m_topRight.get_i() - m_topLeft.get_i(), m_topRight.get_j() - m_topLeft.get_j());
159 }
160 
163 {
164  m_topLeft += center - m_center;
165  m_bottomLeft += center - m_center;
166  m_bottomRight += center - m_center;
167  m_topRight += center - m_center;
168  m_center = center;
169 }
170 
172 vpImagePoint vpRectOriented::getCenter() const { return m_center; }
173 
175 vpImagePoint vpRectOriented::getTopLeft() const { return m_topLeft; }
176 
178 vpImagePoint vpRectOriented::getTopRight() const { return m_topRight; }
179 
181 vpImagePoint vpRectOriented::getBottomLeft() const { return m_bottomLeft; }
182 
184 vpImagePoint vpRectOriented::getBottomRight() const { return m_bottomRight; }
185 
187 void vpRectOriented::setSize(double width, double height)
188 {
189  m_width = width;
190  m_height = height;
191  m_topLeft.set_i(m_center.get_i() - ((m_height * cos(m_theta)) / 2.0) - ((m_width * sin(m_theta)) / 2));
192  m_topLeft.set_j((m_center.get_j() + ((m_height * sin(m_theta)) / 2.0)) - ((m_width * cos(m_theta)) / 2));
193  m_bottomLeft.set_i((m_center.get_i() + ((m_height * cos(m_theta)) / 2.0)) - ((m_width * sin(m_theta)) / 2));
194  m_bottomLeft.set_j(m_center.get_j() - ((m_height * sin(m_theta)) / 2.0) - ((m_width * cos(m_theta)) / 2));
195  m_bottomRight.set_i(m_center.get_i() + ((m_height * cos(m_theta)) / 2.0) + ((m_width * sin(m_theta)) / 2));
196  m_bottomRight.set_j((m_center.get_j() - ((m_height * sin(m_theta)) / 2.0)) + ((m_width * cos(m_theta)) / 2));
197  m_topRight.set_i((m_center.get_i() - ((m_height * cos(m_theta)) / 2.0)) + ((m_width * sin(m_theta)) / 2));
198  m_topRight.set_j(m_center.get_j() + ((m_height * sin(m_theta)) / 2.0) + ((m_width * cos(m_theta)) / 2));
199 }
200 
202 double vpRectOriented::getWidth() const { return m_width; }
203 
205 double vpRectOriented::getHeight() const { return m_height; }
206 
209 {
210  m_theta = theta;
211  m_topLeft.set_i(m_center.get_i() - ((m_height * cos(m_theta)) / 2.0) - ((m_width * sin(m_theta)) / 2));
212  m_topLeft.set_j((m_center.get_j() + ((m_height * sin(m_theta)) / 2.0)) - ((m_width * cos(m_theta)) / 2));
213  m_bottomLeft.set_i((m_center.get_i() + ((m_height * cos(m_theta)) / 2.0)) - ((m_width * sin(m_theta)) / 2));
214  m_bottomLeft.set_j(m_center.get_j() - ((m_height * sin(m_theta)) / 2.0) - ((m_width * cos(m_theta)) / 2));
215  m_bottomRight.set_i(m_center.get_i() + ((m_height * cos(m_theta)) / 2.0) + ((m_width * sin(m_theta)) / 2));
216  m_bottomRight.set_j((m_center.get_j() - ((m_height * sin(m_theta)) / 2.0)) + ((m_width * cos(m_theta)) / 2));
217  m_topRight.set_i((m_center.get_i() - ((m_height * cos(m_theta)) / 2.0)) + ((m_width * sin(m_theta)) / 2));
218  m_topRight.set_j(m_center.get_j() + ((m_height * sin(m_theta)) / 2.0) + ((m_width * cos(m_theta)) / 2));
219 }
220 
222 double vpRectOriented::getOrientation() const { return m_theta; }
223 
225 bool vpRectOriented::isInside(const vpImagePoint &point) const
226 {
227  if (!isLeft(point, m_topLeft, m_bottomLeft)) {
228  return false;
229  }
230  if (!isLeft(point, m_bottomLeft, m_bottomRight)) {
231  return false;
232  }
233  if (!isLeft(point, m_bottomRight, m_topRight)) {
234  return false;
235  }
236  if (!isLeft(point, m_topRight, m_topLeft)) {
237  return false;
238  }
239  return true;
240 }
241 
242 bool vpRectOriented::isLeft(const vpImagePoint &pointToTest, const vpImagePoint &point1,
243  const vpImagePoint &point2) const
244 {
245  double a = point1.get_j() - point2.get_j();
246  double b = point2.get_i() - point1.get_i();
247  double c = -((a * point1.get_i()) + (b * point1.get_j()));
248  double d = (a * pointToTest.get_i()) + (b * pointToTest.get_j()) + c;
249  return (d > 0);
250 }
251 END_VISP_NAMESPACE
error that can be emitted by ViSP classes.
Definition: vpException.h:60
@ badValue
Used to indicate that a value is not in the allowed range.
Definition: vpException.h:73
Class that defines a 2D point in an image. This class is useful for image processing and stores only ...
Definition: vpImagePoint.h:82
void set_j(double jj)
Definition: vpImagePoint.h:309
double get_j() const
Definition: vpImagePoint.h:125
void set_i(double ii)
Definition: vpImagePoint.h:298
double get_i() const
Definition: vpImagePoint.h:114
Defines an oriented rectangle in the plane.
double getHeight() const
Get the rectangle height.
vpImagePoint getBottomLeft() const
Get the bottom-left corner.
double getOrientation() const
Get the rectangle orientation (rad).
vpImagePoint getBottomRight() const
Get the bottom-right corner.
void setPoints(const vpImagePoint &topLeft, const vpImagePoint &topRight, const vpImagePoint &bottomLeft, const vpImagePoint &bottomRight)
void setCenter(const vpImagePoint &center)
Set the center of the rectangle.
vpRectOriented()
Default constructor.
double getWidth() const
Get the rectangle width.
bool isInside(const vpImagePoint &point) const
Check whether the point is inside the rectangle.
void setSize(double width, double height)
Set the size of the rectangle : performs a homothety relatively to the rectangle center.
vpImagePoint getTopRight() const
Get the top-right corner.
vpRectOriented & operator=(const vpRectOriented &)=default
vpImagePoint getTopLeft() const
Get the top-left corner.
vpImagePoint getCenter() const
Get the rectangle center point.
void setOrientation(double theta)
Set the rectangle orientation (rad).
Defines a rectangle in the plane.
Definition: vpRect.h:79
void getCenter(double &x, double &y) const
Definition: vpRect.h:136
double getWidth() const
Definition: vpRect.h:227
double getHeight() const
Definition: vpRect.h:166