ACloudViewer  3.9.4
A Modern Library for 3D Data Processing
ecvInnerRect2DFinder.cpp
Go to the documentation of this file.
1 // ----------------------------------------------------------------------------
2 // - CloudViewer: www.cloudViewer.org -
3 // ----------------------------------------------------------------------------
4 // Copyright (c) 2018-2024 www.cloudViewer.org
5 // SPDX-License-Identifier: MIT
6 // ----------------------------------------------------------------------------
7 
8 #include "ecvInnerRect2DFinder.h"
9 
10 // CV_DB_LIB
11 #include <CVLog.h>
12 
13 // system
14 #include <assert.h>
15 
17  : m_maxArea(0), m_cloud(0), m_X(0), m_Y(1) {}
18 
20  unsigned char zDim /*=2*/) {
21  if (!init(cloud, zDim)) return 0;
22 
23  // Find the 'biggest' rectangle
24  m_maxRect = Rect();
25  m_maxArea = 0;
27 
28  ccBox* resultBox = 0;
29  if (m_maxArea > 0) {
30  ccBBox bbox = cloud->getOwnBB();
31  assert(bbox.isValid());
32 
33  // box size
34  CCVector3 boxDim = bbox.getDiagVec();
35  boxDim.u[m_X] = static_cast<PointCoordinateType>(m_maxRect.width());
36  boxDim.u[m_Y] = static_cast<PointCoordinateType>(m_maxRect.height());
37 
38  CCVector3 boxCenter = bbox.getCenter();
39  boxCenter.u[m_X] = static_cast<PointCoordinateType>(
40  (m_maxRect.x0 + m_maxRect.x1) / 2);
41  boxCenter.u[m_Y] = static_cast<PointCoordinateType>(
42  (m_maxRect.y0 + m_maxRect.y1) / 2);
43 
44  ccGLMatrix shiftMat;
45  shiftMat.setTranslation(boxCenter);
46  resultBox = new ccBox(boxDim, &shiftMat, "Biggest rect");
47  }
48 
49  return resultBox;
50 }
51 
52 bool ccInnerRect2DFinder::init(ccGenericPointCloud* cloud, unsigned char zDim) {
53  if (!cloud || cloud->size() == 0) {
54  CVLog::Error("[ccInnerRect2DFinder] Invalid input cloud");
55  return false;
56  }
57 
58  ccBBox bbox = cloud->getOwnBB();
59  if (!bbox.isValid()) {
60  CVLog::Error("[ccInnerRect2DFinder] Invalid input cloud");
61  return false;
62  }
63 
64  if (zDim > 2) {
65  CVLog::Error("[ccInnerRect2DFinder] Invalid input parameter (zDim)");
66  return false;
67  }
68 
69  unsigned char Z = zDim;
70  unsigned char X = ((Z + 1) % 3);
71  unsigned char Y = ((X + 1) % 3);
72 
73  m_cloud = cloud;
74  m_X = X;
75  m_Y = Y;
76 
77  // init bounding rectangle
78  {
79  const CCVector3* P0 = m_cloud->getPoint(0);
80  m_boundingRect = Rect(P0->u[m_X], P0->u[m_Y], P0->u[m_X], P0->u[m_Y]);
81 
82  unsigned pointCloud = m_cloud->size();
83  for (unsigned i = 1; i < pointCloud; ++i) {
84  const CCVector3* P = m_cloud->getPoint(i);
85  if (P->u[m_X] < m_boundingRect.x0)
86  m_boundingRect.x0 = P->u[m_X];
87  else if (P->u[m_X] > m_boundingRect.x1)
88  m_boundingRect.x1 = P->u[m_X];
89 
90  if (P->u[m_Y] < m_boundingRect.y0)
91  m_boundingRect.y0 = P->u[m_Y];
92  else if (P->u[m_Y] > m_boundingRect.y1)
93  m_boundingRect.y1 = P->u[m_Y];
94  }
95  }
96 
97  return true;
98 }
99 
101  unsigned startIndex) {
102  assert(m_cloud);
103 
104  // test if at least one point falls inside the input rectangle
105  const CCVector3* Pinside = 0;
106  {
107  unsigned pointCount = m_cloud->size();
108  double minSquareDistToCenter = -1.0;
109  double xc = (rect.x0 + rect.x1) / 2;
110  double yc = (rect.y0 + rect.y1) / 2;
111  for (unsigned i = startIndex; i < pointCount; ++i) {
112  const CCVector3* P = m_cloud->getPoint(i);
113  if (P->u[m_X] > rect.x0 &&
114  P->u[m_X] < rect.x1 // strict inequalities!
115  && P->u[m_Y] > rect.y0 && P->u[m_Y] < rect.y1) {
116  double dist2 = (xc - P->u[m_X]) * (xc - P->u[m_X]) +
117  (yc - P->u[m_Y]) * (yc - P->u[m_Y]);
118  if (minSquareDistToCenter < 0) {
119  Pinside = P;
120  minSquareDistToCenter = dist2;
121  startIndex = i;
122  } else if (dist2 < minSquareDistToCenter) {
123  Pinside = P;
124  minSquareDistToCenter = dist2;
125  }
126  // break;
127  }
128  }
129  }
130 
131  // do we have an empty rectangle?
132  if (!Pinside) {
133  // we remember it only if its size is bigger
134  double surf = rect.area();
135  if (surf > m_maxArea) {
136  m_maxArea = surf;
137  m_maxRect = rect;
138  }
139  } else // otherwise we test the 4 sub-rectangles
140  {
141  // left sub-rectangle
142  Rect r(rect.x0, rect.y0, Pinside->u[m_X], rect.y1);
143  if (r.area() > m_maxArea) findBiggestRect(r, startIndex);
144  // right sub-rectangle
145  r = Rect(Pinside->u[m_X], rect.y0, rect.x1, rect.y1);
146  if (r.area() > m_maxArea) findBiggestRect(r, startIndex);
147  // upper sub-rectangle
148  r = Rect(rect.x0, rect.y0, rect.x1, Pinside->u[m_Y]);
149  if (r.area() > m_maxArea) findBiggestRect(r, startIndex);
150  // lower sub-rectangle
151  r = Rect(rect.x0, Pinside->u[m_Y], rect.x1, rect.y1);
152  if (r.area() > m_maxArea) findBiggestRect(r, startIndex);
153  }
154 }
float PointCoordinateType
Type of the coordinates of a (N-D) point.
Definition: CVTypes.h:16
void * X
Definition: SmallVector.cpp:45
static bool Error(const char *format,...)
Display an error dialog with formatted message.
Definition: CVLog.cpp:143
Type u[3]
Definition: CVGeom.h:139
Bounding box structure.
Definition: ecvBBox.h:25
Box (primitive)
Definition: ecvBox.h:16
void setTranslation(const Vector3Tpl< float > &Tr)
Sets translation (float version)
Float version of ccGLMatrixTpl.
Definition: ecvGLMatrix.h:19
A 3D cloud interface with associated features (color, normals, octree, etc.)
ccBBox getOwnBB(bool withGLFeatures=false) override
Returns the entity's own bounding-box.
Rect m_boundingRect
Global rectangle.
unsigned char m_X
X dimension.
ccInnerRect2DFinder()
Default constructor.
double m_maxArea
Inner rectangle max area.
ccGenericPointCloud * m_cloud
Associated cloud.
Rect m_maxRect
Inner rectangle.
bool init(ccGenericPointCloud *cloud, unsigned char zDim)
Initializes internal structures.
ccBox * process(ccGenericPointCloud *cloud, unsigned char zDim=2)
Finds the biggest enclosed rectangle.
void findBiggestRect(const Rect &rect, unsigned startIndex)
Internal processs.
unsigned char m_Y
Y dimension.
Vector3Tpl< T > getDiagVec() const
Returns diagonal vector.
Definition: BoundingBox.h:169
Vector3Tpl< T > getCenter() const
Returns center.
Definition: BoundingBox.h:164
bool isValid() const
Returns whether bounding box is valid or not.
Definition: BoundingBox.h:203
virtual unsigned size() const =0
Returns the number of points.
virtual const CCVector3 * getPoint(unsigned index) const =0
Returns the ith point.
Definition: lsd.c:1170
double x1
Definition: lsd.c:1171
double y1
Definition: lsd.c:1171