ACloudViewer  3.9.4
A Modern Library for 3D Data Processing
CurveFitting.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 "CurveFitting.h"
9 
10 #include <Utils/vtk2cc.h>
11 
12 // CV_DB_LIB
13 #include <ecvPointCloud.h>
14 #include <ecvPolyline.h>
15 
16 // VTK
17 #include <vtkParametricFunctionSource.h>
18 #include <vtkParametricSpline.h>
19 #include <vtkPolyData.h>
20 #include <vtkSCurveSpline.h>
21 #include <vtkSmartPointer.h>
22 
23 // PCL COMMON
24 #include <pcl/Vertices.h>
25 #include <pcl/common/common.h>
26 #include <vtkPolyLine.h>
27 
28 using namespace std;
29 using namespace pcl;
30 using namespace Eigen;
31 
32 namespace CurveFittingTool {
33 
34 CurveFitting::CurveFitting() {}
35 
36 CurveFitting::~CurveFitting() { cloud->clear(); }
37 
38 ccPolyline *CurveFitting::BsplineFitting(const ccPointCloud &cloud) {
40  for (const CCVector3 &p : cloud.getPoints()) {
41  points->InsertNextPoint(p.u);
42  }
43 
50 
53  spline->SetXSpline(xSpline);
54  spline->SetYSpline(ySpline);
55  spline->SetZSpline(zSpline);
56  spline->SetPoints(points);
57  spline->ClosedOff();
58 
61  functionSource->SetParametricFunction(spline);
62  functionSource->Update();
63 
64  vtkPolyData *result = functionSource->GetOutput();
65  if (!result) return nullptr;
66 
68 }
69 
70 void CurveFitting::setInputcloud(PointCloudT::Ptr input_cloud) {
71  cloud = input_cloud;
72  getMinMax3D(*input_cloud, point_min, point_max);
73 }
74 
75 void CurveFitting::grid_mean_xyz(double x_resolution,
76  double y_resolution,
77  vector<double> &x_mean,
78  vector<double> &y_mean,
79  vector<double> &z_mean,
80  PointCloudT::Ptr &new_cloud) {
81  if (y_resolution <= 0) {
82  y_resolution = point_max.y - point_min.y;
83  }
84  int raster_rows, raster_cols;
85  raster_rows = ceil((point_max.x - point_min.x) / x_resolution);
86  raster_cols = ceil((point_max.y - point_min.y) / y_resolution);
87  vector<int> idx_point;
88  vector<vector<vector<float>>> row_col;
89  vector<vector<float>> col_;
90  vector<float> vector_4;
91  vector_4.resize(4);
92  col_.resize(raster_cols, vector_4);
93  row_col.resize(raster_rows, col_);
94  int point_num = cloud->size();
95  for (int i_point = 0; i_point < point_num; i_point++) {
96  int row_idx =
97  ceil((cloud->points[i_point].x - point_min.x) / x_resolution) -
98  1;
99  int col_idx =
100  ceil((cloud->points[i_point].y - point_min.y) / y_resolution) -
101  1;
102  if (row_idx < 0) row_idx = 0;
103  if (col_idx < 0) col_idx = 0;
104  row_col[row_idx][col_idx][0] += cloud->points[i_point].x;
105  row_col[row_idx][col_idx][1] += cloud->points[i_point].y;
106  row_col[row_idx][col_idx][2] += cloud->points[i_point].z;
107  row_col[row_idx][col_idx][3] += 1;
108  }
109  PointT point_mean_tem;
110  for (int i_row = 0; i_row < row_col.size(); i_row++) {
111  for (int i_col = 0; i_col < row_col[i_row].size(); i_col++) {
112  if (row_col[i_row][i_col][3] != 0) {
113  double x_mean_tem =
114  row_col[i_row][i_col][0] / row_col[i_row][i_col][3];
115  double y_mean_tem =
116  row_col[i_row][i_col][1] / row_col[i_row][i_col][3];
117  double z_mean_tem =
118  row_col[i_row][i_col][2] / row_col[i_row][i_col][3];
119  x_mean.push_back(x_mean_tem);
120  y_mean.push_back(y_mean_tem);
121  z_mean.push_back(z_mean_tem);
122  point_mean_tem.x = x_mean_tem;
123  point_mean_tem.y = y_mean_tem;
124  point_mean_tem.z = z_mean_tem;
125  new_cloud->push_back(point_mean_tem);
126  }
127  }
128  }
129 }
130 
131 void CurveFitting::line_fitting(vector<double> x,
132  vector<double> y,
133  double &k,
134  double &b) {
135  MatrixXd A_(2, 2), B_(2, 1), A12(2, 1);
136  int num_point = x.size();
137  double A01(0.0), A02(0.0), B00(0.0), B10(0.0);
138  for (int i_point = 0; i_point < num_point; i_point++) {
139  A01 += x[i_point] * x[i_point];
140  A02 += x[i_point];
141  B00 += x[i_point] * y[i_point];
142  B10 += y[i_point];
143  }
144  A_ << A01, A02, A02, num_point;
145  B_ << B00, B10;
146  A12 = A_.inverse() * B_;
147  k = A12(0, 0);
148  b = A12(1, 0);
149 }
150 
151 void CurveFitting::polynomial2D_fitting(
152  vector<double> x, vector<double> y, double &a, double &b, double &c) {
153  MatrixXd A_(3, 3), B_(3, 1), A123(3, 1);
154  int num_point = x.size();
155  double A01(0.0), A02(0.0), A12(0.0), A22(0.0), B00(0.0), B10(0.0), B12(0.0);
156  for (int i_point = 0; i_point < num_point; i_point++) {
157  A01 += x[i_point];
158  A02 += x[i_point] * x[i_point];
159  A12 += x[i_point] * x[i_point] * x[i_point];
160  A22 += x[i_point] * x[i_point] * x[i_point] * x[i_point];
161  B00 += y[i_point];
162  B10 += x[i_point] * y[i_point];
163  B12 += x[i_point] * x[i_point] * y[i_point];
164  }
165  A_ << num_point, A01, A02, A01, A02, A12, A02, A12, A22;
166  B_ << B00, B10, B12;
167  A123 = A_.inverse() * B_;
168  a = A123(2, 0);
169  b = A123(1, 0);
170  c = A123(0, 0);
171 }
172 
173 void CurveFitting::polynomial3D_fitting(vector<double> x,
174  vector<double> y,
175  vector<double> z,
176  double &a,
177  double &b,
178  double &c) {
179  int num_point = x.size();
180  MatrixXd A_(3, 3), B_(3, 1), A123(3, 1);
181  double A01(0.0), A02(0.0), A12(0.0), A22(0.0), B00(0.0), B10(0.0), B12(0.0);
182  for (int i_point = 0; i_point < num_point; i_point++) {
183  double x_y = sqrt(pow(x[i_point], 2) + pow(y[i_point], 2));
184  A01 += x_y;
185  A02 += pow(x_y, 2);
186  A12 += pow(x_y, 3);
187  A22 += pow(x_y, 4);
188  B00 += z[i_point];
189  B10 += x_y * z[i_point];
190  B12 += pow(x_y, 2) * z[i_point];
191  }
192  A_ << num_point, A01, A02, A01, A02, A12, A02, A12, A22;
193  B_ << B00, B10, B12;
194  A123 = A_.inverse() * B_;
195  line_fitting(x, y, k_line, b_line);
196  a = A123(2, 0);
197  b = A123(1, 0);
198  c = A123(0, 0);
199  c_3d = c;
200  b_3d = b;
201  a_3d = a;
202 }
203 
204 void CurveFitting::getPolynomial3D(PointCloudT::Ptr outCurve, double step_) {
205  PointT point_min_, point_max_;
206  getMinMax3D(*cloud, point_min_, point_max_);
207  int idx_minx, idx_maxy; // x
208  for (int i_point = 0; i_point < cloud->size(); i_point++) {
209  if (cloud->points[i_point].x == point_min_.x) idx_minx = i_point;
210  if (cloud->points[i_point].x == point_max_.x) idx_maxy = i_point;
211  }
212  float m_min =
213  cloud->points[idx_minx].x + k_line * cloud->points[idx_minx].y;
214  float m_max =
215  cloud->points[idx_maxy].x + k_line * cloud->points[idx_maxy].y;
216 
217  float x_min = (m_min - b_line * k_line) / (1 + k_line * k_line);
218  float x_max = (m_max - b_line * k_line) / (1 + k_line * k_line);
219 
220  int step_num = ceil((x_max - x_min) / step_);
221  for (int i_ = 0; i_ < step_num + 1; i_++) {
222  double tem_value = x_min + i_ * step_;
223  if (tem_value > x_max) {
224  tem_value = x_max;
225  }
226  PointT point_;
227  point_.x = tem_value;
228  point_.y = k_line * tem_value + b_line;
229  double xxyy = sqrt(pow(point_.x, 2) + pow(point_.y, 2));
230  point_.z = c_3d + b_3d * xxyy + a_3d * pow(xxyy, 2);
231  outCurve->push_back(point_);
232  }
233 }
234 
235 } // namespace CurveFittingTool
int points
pcl::PointXYZ PointT
Definition: PCLCloud.h:16
core::Tensor result
Definition: VtkUtils.cpp:76
A 3D cloud and its associated features (color, normals, scalar fields, etc.)
Colored polyline.
Definition: ecvPolyline.h:24
std::vector< CCVector3 > & getPoints()
static ccPolyline * ConvertToPolyline(vtkPolyData *polydata, bool silent=false)
Definition: vtk2cc.cpp:392
a[190]
normal_z y
normal_z x
normal_z z
Definition: Eigen.h:103
MiniVec< float, N > ceil(const MiniVec< float, N > &a)
Definition: MiniVec.h:89
Definition: Eigen.h:85
Eigen::Matrix2f A12