c++bounding-boxopen3dpose

How to get the closest bottom left point in OrientedBoundingBox


I'm trying to get the pose (translation, rotation) of the (closest to origin on x then z) left point (furthest on y from origin) in OrientedBoundingBox, my problem is the bounding box in different runs have different rotations, as defined by Open3D I was expecting the following cube:

///      ------- x
///     /|
///    / |
///   /  | z
///  y
///      0 ------------------- 1
///       /|                /|
///      / |               / |
///     /  |              /  |
///    /   |             /   |
/// 2 ------------------- 7  |
///   |    |____________|____| 6
///   |   /3            |   /
///   |  /              |  /
///   | /               | /
///   |/                |/
/// 5 ------------------- 4

so my target was Point 2, but getting the point from GetBoxPoints() with rotations as normal vectors gave me different poses! Can you please tell me how can I get the desired pose? thanks in advance.

    open3d::geometry::OrientedBoundingBox bbox_ws
    std::vector<Eigen::Vector3d> points = bbox_ws.GetBoxPoints();
    Eigen::Vector3d P2 = points[2];
    for (const auto& point : points) {
        if (point.x() < P2.x() && point.y() > P2.y() && point.z() < P2.z()) {
            P2 = point;
        }
    }

    Eigen::Vector3d x_axis = points[7] - P2; // P2P7
    Eigen::Vector3d y_axis = points[0] - P2; // P2P0
    Eigen::Vector3d z_axis = points[5] - P2; // P2P5

    x_axis.normalize();
    y_axis.normalize();
    z_axis.normalize();

    Eigen::Matrix3d rotation_matrix;
    rotation_matrix.col(0) = x_axis;
    rotation_matrix.col(1) = y_axis;
    rotation_matrix.col(2) = z_axis;

According to the extracted values, P5 is my desired point

point number 0 Has values: 1.20885    0.52103   0.172856
point number 1 Has values: 0.939225  -0.536148  0.205281
point number 2 Has values: 1.21036    0.52761   0.399916
point number 3 Has values: 0.810032   0.622739  0.17256
point number 4 Has values: 0.541912  -0.42786   0.432043
point number 5 Has values: 0.811541   0.629318  0.399619
point number 6 Has values: 0.540403  -0.434439  0.204984
point number 7 Has values: 0.940734  -0.529568  0.43234

## Here are other values:

0.945674  -0.514864  0.407497
1.18082  0.423109  0.415139
0.945228  -0.513155  0.211485
0.546889  -0.414905  0.409276
0.781587  0.524777  0.220907
0.546443  -0.413196 0.213265
0.782034  0.523068  0.416919
1.18037  0.424818  0.219128


1.21301    0.515485   0.172203
0.945833  -0.534461   0.226136
1.21074    0.527857   0.401783
0.811611   0.617145   0.162747
0.542156  -0.42043    0.446261
0.809336   0.629517   0.392328
0.54443   -0.432802   0.21668
0.943558  -0.52209    0.455717

Solution

  • Simple stupid solution:

    std::vector<Eigen::Vector3d> sortBoxPoints(std::vector<Eigen::Vector3d>& points, bool verbose){
        ///      4 ------------------- 6
        ///       /.                /|
        ///      / .               / |
        ///     /  .              /  |
        ///    /   .             /   |
        /// 5 ------------------- 3  |
        ///   |    . . . . . . .| . .| 1
        ///   |   .7            |   /
        ///   |  .              |  /
        ///   | .               | /
        ///   |.                |/
        /// 2 ------------------- 0
        ///
        ///               z   x
        ///               |  /
        ///               | /
        ///               |/
        ///       y ------- 
        std::vector<Eigen::Vector3d> sorted_points(8);
        /**
         * ---------- Z ------------------- min
         */
        // Sort the vector based on z-values
        std::sort(points.begin(), points.end(), [](const Eigen::Vector3d& a, const Eigen::Vector3d& b) {
            return a(2) > b(2);  // Sort in descending order based on z-values
        });
    
        // Get the first half of the sorted vector
        size_t halfSize = points.size() / 2;
        /** 3, 4, 5, 6 */
        std::vector<Eigen::Vector3d> ZP_(points.begin(), points.begin() + halfSize);
        /** 0, 1, 2, 7 */
        std::vector<Eigen::Vector3d> ZM_ (points.begin() + halfSize, points.end());
    
        // Sort the vector based on x-values
        std::sort(ZP_.begin(), ZP_.end(), [](const Eigen::Vector3d& a, const Eigen::Vector3d& b) {
            return a(0) > b(0);  // Sort in descending order based on z-values
        });
        std::sort(ZM_.begin(), ZM_.end(), [](const Eigen::Vector3d& a, const Eigen::Vector3d& b) {
            return a(0) > b(0);  // Sort in descending order based on z-values
        });
    
        /**
         * ---------- X ------------------- min
         */
        size_t quarterSize = points.size() / 4;
        /** 4, 6 */
        std::vector<Eigen::Vector3d> ZP_XP (ZP_.begin(), ZP_.begin() + quarterSize);
        /** 5, 3 */
        std::vector<Eigen::Vector3d> ZP_XM (ZP_.begin() + quarterSize, ZP_.end());
    
        /** 7, 1 */
        std::vector<Eigen::Vector3d> ZM_XP (ZM_.begin(), ZM_.begin() + quarterSize);
        /** 2, 0 */
        std::vector<Eigen::Vector3d> ZM_XM (ZM_.begin() + quarterSize, ZM_.end());
    
        /**
         * ---------- Y ------------------- max
         */
        if(ZP_XP[0](1) > ZP_XP[1](1)){
          sorted_points[4] = ZP_XP[0];
          sorted_points[6] = ZP_XP[1];
        }
        else{
          sorted_points[4] = ZP_XP[1];
          sorted_points[6] = ZP_XP[0];
        }
    
        if(ZP_XM[0](1) > ZP_XM[1](1)){
          sorted_points[5] = ZP_XM[0];
          sorted_points[3] = ZP_XM[1];
        }
        else{
          sorted_points[5] = ZP_XM[1];
          sorted_points[3] = ZP_XM[0];
        }
    
        if(ZM_XP[0](1) > ZM_XP[1](1)){
          sorted_points[7] = ZM_XP[0];
          sorted_points[1] = ZM_XP[1];
        }
        else{
          sorted_points[7] = ZM_XP[1];
          sorted_points[1] = ZM_XP[0];
        }
    
        if(ZM_XM[0](1) > ZM_XM[1](1)){
          sorted_points[2] = ZM_XM[0];
          sorted_points[0] = ZM_XM[1];
        }
        else{
          sorted_points[2] = ZM_XM[1];
          sorted_points[0] = ZM_XM[0];
        }
    
        if(verbose){
            int count = 0;
            for (const auto& point : sorted_points) {
                std::cout << "Point  " << count << " values: "<< point.transpose() << std::endl;
                count++;
            }
        }
    
        return sorted_points;
    }