• 平面度计算 C++实现


    直接贴代码

    cmake

    cmake_minimum_required(VERSION 2.8.3)
    project(test)
    
    #-------------------------------------- 编译器设置 --------------------------------------
    #set(CMAKE_BUILD_TYPE Release)
    set(CMAKE_BUILD_TYPE Debug)
    
    if(CMAKE_BUILD_TYPE STREQUAL "Release")
        set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O3 -std=c++11 -fPIC")
    else()
        set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -O0 -std=c++11 -fPIC")
    endif()
    message("*** ${PROJECT_NAME}: Build type:" ${CMAKE_BUILD_TYPE} ${CMAKE_CXX_FLAGS} "***")
    
    set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/cmakes)
    #-------------------------------------- -添加项目- --------------------------------------
    
    add_executable(
    ${PROJECT_NAME}
    test.cpp )
    target_link_libraries(
    ${PROJECT_NAME}
    ${catkin_LIBRARIES})

    test.cpp文件

    // system
    #include <vector>
    #include <iostream>
    // eigen3
    #include <eigen3/Eigen/Dense>
    #include <eigen3/Eigen/Eigenvalues>
    using namespace Eigen;
    
    typedef struct Pt
    {
      double x;
      double y;
      double z;
    }Point;
    /* 最小二乘法拟合平面:Ax + By + Cz + D = 0 */
    /* xjParameters:返回参数A B C D */
    /* xjData:存放输入点 */
    bool xjFitPlaneByLeastSquares(std::vector<double>& xjParameters, const std::vector<Point>& xjData)
    {
      xjParameters.clear();
      int count = xjData.size();
      if (count < 3)
        return false;
    
      double meanX = 0, meanY = 0, meanZ = 0;
      double meanXX = 0, meanYY = 0, meanZZ = 0;
      double meanXY = 0, meanXZ = 0, meanYZ = 0;
      for (int i = 0; i < count; i++)
      {
        meanX += xjData[i].x;
        meanY += xjData[i].y;
        meanZ += xjData[i].z;
    
        meanXX += xjData[i].x * xjData[i].x;
        meanYY += xjData[i].y * xjData[i].y;
        meanZZ += xjData[i].z * xjData[i].z;
    
        meanXY += xjData[i].x * xjData[i].y;
        meanXZ += xjData[i].x * xjData[i].z;
        meanYZ += xjData[i].y * xjData[i].z;
      }
      meanX  /= count;
      meanY  /= count;
      meanZ  /= count;
      meanXX /= count;
      meanYY /= count;
      meanZZ /= count;
      meanXY /= count;
      meanXZ /= count;
      meanYZ /= count;
    
      /* eigenvector */
      Matrix3d eMat;
      eMat(0, 0) = meanXX - meanX * meanX; eMat(0, 1) = meanXY - meanX * meanY; eMat(0, 2) = meanXZ - meanX * meanZ;
      eMat(1, 0) = meanXY - meanX * meanY; eMat(1, 1) = meanYY - meanY * meanY; eMat(1, 2) = meanYZ - meanY * meanZ;
      eMat(2, 0) = meanXZ - meanX * meanZ; eMat(2, 1) = meanYZ - meanY * meanZ; eMat(2, 2) = meanZZ - meanZ * meanZ;
      Eigen::EigenSolver<Eigen::Matrix3d> xjMat(eMat);
      Matrix3d                            eValue  = xjMat.pseudoEigenvalueMatrix();
      Matrix3d                            eVector = xjMat.pseudoEigenvectors();
    
      /* the eigenvector corresponding to the minimum eigenvalue */
      double v1        = eValue(0, 0);
      double v2        = eValue(1, 1);
      double v3        = eValue(2, 2);
      int    minNumber = 0;
      if ((abs(v2) <= abs(v1)) && (abs(v2) <= abs(v3)))
      {
        minNumber = 1;
      }
      if ((abs(v3) <= abs(v1)) && (abs(v3) <= abs(v2)))
      {
        minNumber = 2;
      }
      double A = eVector(0, minNumber);
      double B = eVector(1, minNumber);
      double C = eVector(2, minNumber);
      double D = -(A * meanX + B * meanY + C * meanZ);
    
      /* result */
      if (C < 0)
      {
        A *= -1.0;
        B *= -1.0;
        C *= -1.0;
        D *= -1.0;
      }
      xjParameters.push_back(A);
      xjParameters.push_back(B);
      xjParameters.push_back(C);
      xjParameters.push_back(D);
      return true;
    }
    double dist(Point pt, std::vector<double> xjParameters) // Distance between point and plane
    {
      double dt = 0.0;
      double mA, mB, mC, mD, mX, mY, mZ;
    
      mA = xjParameters[0];
      mB = xjParameters[1];
      mC = xjParameters[2];
      mD = xjParameters[3];
    
      mX = pt.x;
      mY = pt.y;
      mZ = pt.z;
    
      dt = fabs(mA*mX+mB*mY+mC*mZ+mD)/sqrt(mA*mA+mB*mB+mC*mC);
      return dt;
    }
    
    int main(int argc, char* * argv)
    {
      std::vector<double> xjParameters;
      std::vector<Point>  xjData;
    
      double x[] = {58.8249, 149.3559, 259.9059, 273.2909, 272.2909, 272.2909,
                    255.5409, 164.0009, 66.0309, 47.0559, 47.0559, 47.0559};
      double y[] = {-52.3037, -52.3037, -52.3037, -82.1139, -127.5069, -168.7469,
                    -185.3669, -185.3669, -185.3669, -163.4689, -118.4089, -68.9889};
      double z[] = {0, -0.165, -0.202, -0.231, -0.163, -0.158,
                    -0.098, -0.157, 0.075, 0.036, -0.012, -0.04};
      Point  tmp;
      for(int i = 0; i < 12; i++)
      {
        tmp.x = x[i];
        tmp.y = y[i];
        tmp.z = z[i];
        xjData.push_back(tmp);
      }
      if(xjFitPlaneByLeastSquares(xjParameters, xjData))
      {
        std::cout<<"A ="<<xjParameters[0]<<" B ="<<xjParameters[1]<<" C ="<<xjParameters[2]<<" D ="<<xjParameters[3]<<std::endl;
        double sum = 0.0;
        for(int j = 0; j<xjData.size(); j++)
        {
          double dis = dist(xjData[j], xjParameters);
          sum += dis;
          std::cout<<"id ="<<j+1 <<" distance ="<<dis<<std::endl;
        }
        sum = sum/xjData.size();
        std::cout<<"Average distance ="<<sum<<std::endl;
      }
      else
      {
        std::cout<<"not find plane"<<std::endl;
      }
      return 0;
    }





  • 相关阅读:
    win10通过ip连接打印机
    tarunexpectedeofinarchive
    软件工程设计阶段的几种图
    代码review checklist
    caffeine的使用
    thetrustanchorsparametermustbenonempty
    mysql explain type的详解
    scp对拷贝文件夹
    虚拟dom与diff算法
    线程池ThreadPoolExecutor的使用
  • 原文地址:https://www.cnblogs.com/zx-hit/p/14792838.html
Copyright © 2020-2023  润新知