调教AI给我写了一个KD树的算法

news2024/11/23 11:19:30

我不擅长C++,但是目前需要用C++写一个KD树的算法。首先我有一份点云数据,需要找给定坐标范围0.1mm内的所有点。

于是我开始问AI,他一开始给的答案,完全是错误的,但是我一步步给出反馈,告诉他的问题,他居然给出的正确的答案(我和python代码做了对比,python有线程的库实现)

下面,是我和AI的对话过程。

这看起来像是一系列三维空间中的点的坐标数据,每行表示一个点,包含了该点的 x、y、z 坐标值。如果你想要使用 KD 树对这些点进行空间检索或者其他操作,你可以使用 C++ 来读取这些数据,然后构建 KD 树。以下是一个简单的示例代码,可以帮助你读取这个文件并构建 KD 树:

```cpp
#include <iostream>
#include <fstream>
#include <vector>
#include <string>
#include <sstream>

// Define a structure to represent a point in 3D space
struct Point3D {
    double x, y, z;
};

// Define a node structure for the KD tree
struct KDNode {
    Point3D point;
    KDNode* left;
    KDNode* right;
    int axis; // 0 for x, 1 for y, 2 for z

    KDNode(const Point3D& p) : point(p), left(nullptr), right(nullptr), axis(0) {}
};

// Function to recursively build a KD tree from a list of points
KDNode* buildKDTree(std::vector<Point3D>& points, int depth = 0) {
    if (points.empty()) return nullptr;

    // Determine current axis
    int axis = depth % 3;

    // Sort points based on current axis
    if (axis == 0)
        std::sort(points.begin(), points.end(), [](const Point3D& a, const Point3D& b) { return a.x < b.x; });
    else if (axis == 1)
        std::sort(points.begin(), points.end(), [](const Point3D& a, const Point3D& b) { return a.y < b.y; });
    else
        std::sort(points.begin(), points.end(), [](const Point3D& a, const Point3D& b) { return a.z < b.z; });

    // Find median
    size_t medianIdx = points.size() / 2;
    KDNode* node = new KDNode(points[medianIdx]);
    node->axis = axis;

    // Recursively build left and right subtrees
    std::vector<Point3D> leftPoints(points.begin(), points.begin() + medianIdx);
    std::vector<Point3D> rightPoints(points.begin() + medianIdx + 1, points.end());
    node->left = buildKDTree(leftPoints, depth + 1);
    node->right = buildKDTree(rightPoints, depth + 1);

    return node;
}

// Function to print a KD tree (for debugging)
void printKDTree(KDNode* root) {
    if (root) {
        std::cout << "(" << root->point.x << ", " << root->point.y << ", " << root->point.z << ")" << std::endl;
        printKDTree(root->left);
        printKDTree(root->right);
    }
}

int main() {
    std::ifstream file("point_cloud.txt");
    if (!file.is_open()) {
        std::cerr << "Error opening file." << std::endl;
        return 1;
    }

    std::vector<Point3D> points;
    std::string line;
    while (std::getline(file, line)) {
        std::istringstream iss(line);
        double x, y, z;
        char comma;
        if (iss >> x >> comma >> y >> comma >> z) {
            points.push_back({x, y, z});
        } else {
            std::cerr << "Error reading line: " << line << std::endl;
        }
    }

    file.close();

    // Build KD tree
    KDNode* root = buildKDTree(points);

    // Print KD tree (for debugging)
    printKDTree(root);

    // Cleanup
    // You need to implement a function to delete the KD tree nodes

    return 0;
}
```

请注意,这只是一个简单的示例,仅用于演示如何读取点云文件并构建 KD 树。在实际应用中,你可能需要添加更多的功能和错误检查,并在程序结束时正确地清理分配的内存。

要解决这个问题,我们可以使用 KD 树进行最近邻搜索。给定一个点,我们可以通过搜索 KD 树来找到距离该点最近的点,并检查这些点是否在给定的范围内。下面是一个修改后的示例代码,用于找到给定点附近一定范围内的所有点:

```cpp
#include <iostream>
#include <fstream>
#include <vector>
#include <string>
#include <sstream>
#include <cmath>

// Define a structure to represent a point in 3D space
struct Point3D {
    double x, y, z;
};

// Define a node structure for the KD tree
struct KDNode {
    Point3D point;
    KDNode* left;
    KDNode* right;
    int axis; // 0 for x, 1 for y, 2 for z

    KDNode(const Point3D& p) : point(p), left(nullptr), right(nullptr), axis(0) {}
};

// Function to recursively build a KD tree from a list of points
KDNode* buildKDTree(std::vector<Point3D>& points, int depth = 0) {
    if (points.empty()) return nullptr;

    // Determine current axis
    int axis = depth % 3;

    // Sort points based on current axis
    if (axis == 0)
        std::sort(points.begin(), points.end(), [](const Point3D& a, const Point3D& b) { return a.x < b.x; });
    else if (axis == 1)
        std::sort(points.begin(), points.end(), [](const Point3D& a, const Point3D& b) { return a.y < b.y; });
    else
        std::sort(points.begin(), points.end(), [](const Point3D& a, const Point3D& b) { return a.z < b.z; });

    // Find median
    size_t medianIdx = points.size() / 2;
    KDNode* node = new KDNode(points[medianIdx]);
    node->axis = axis;

    // Recursively build left and right subtrees
    std::vector<Point3D> leftPoints(points.begin(), points.begin() + medianIdx);
    std::vector<Point3D> rightPoints(points.begin() + medianIdx + 1, points.end());
    node->left = buildKDTree(leftPoints, depth + 1);
    node->right = buildKDTree(rightPoints, depth + 1);

    return node;
}

// Function to calculate Euclidean distance between two points
double distance(const Point3D& a, const Point3D& b) {
    return std::sqrt(std::pow(a.x - b.x, 2) + std::pow(a.y - b.y, 2) + std::pow(a.z - b.z, 2));
}

// Function to perform range search in KD tree
void rangeSearch(KDNode* root, const Point3D& target, double radius, std::vector<Point3D>& result) {
    if (!root) return;

    // Calculate distance to current point
    double dist = distance(root->point, target);

    // If the current point is within the radius, add it to the result
    if (dist <= radius) {
        result.push_back(root->point);
    }

    // Recursively search left and right subtrees if they might contain points within the radius
    if (root->left && target.axis[root->axis] - radius < root->point.axis[root->axis]) {
        rangeSearch(root->left, target, radius, result);
    }
    if (root->right && target.axis[root->axis] + radius >= root->point.axis[root->axis]) {
        rangeSearch(root->right, target, radius, result);
    }
}

int main() {
    std::ifstream file("point_cloud.txt");
    if (!file.is_open()) {
        std::cerr << "Error opening file." << std::endl;
        return 1;
    }

    std::vector<Point3D> points;
    std::string line;
    while (std::getline(file, line)) {
        std::istringstream iss(line);
        double x, y, z;
        char comma;
        if (iss >> x >> comma >> y >> comma >> z) {
            points.push_back({x, y, z});
        } else {
            std::cerr << "Error reading line: " << line << std::endl;
        }
    }

    file.close();

    // Build KD tree
    KDNode* root = buildKDTree(points);

    // Define the target point and search radius
    Point3D target = {1.0, 2.0, 3.0};
    double radius = 0.1; // in this case, 0.1mm

    // Perform range search
    std::vector<Point3D> result;
    rangeSearch(root, target, radius, result);

    // Print the points within the range
    std::cout << "Points within " << radius << "mm of (" << target.x << ", " << target.y << ", " << target.z << "):" << std::endl;
    for (const auto& p : result) {
        std::cout << "(" << p.x << ", " << p.y << ", " << p.z << ")" << std::endl;
    }

    // Cleanup
    // You need to implement a function to delete the KD tree nodes

    return 0;
}
```

这段代码将找到距离给定点不超过 0.1mm 的所有点,并将它们打印出来。请确保在使用时,将实际的搜索半径(以毫米为单位)传递给 `rangeSearch` 函数。

你是对的,我的确犯了一个错误。在 `rangeSearch` 函数中,我没有正确地限制搜索的范围,导致了重复添加点的问题。让我来修复这个问题。

修改后的 `rangeSearch` 函数应该会在递归搜索左右子树时正确地限制搜索范围,避免了重复添加点的问题。以下是修复后的代码:

```cpp
// Function to perform range search in KD tree
void rangeSearch(KDNode* root, const Point3D& target, double radius, std::vector<Point3D>& result) {
    if (!root) return;

    // Calculate distance to current point
    double dist = distance(root->point, target);

    // If the current point is within the radius, add it to the result
    if (dist <= radius) {
        result.push_back(root->point);
    }

    // Recursively search left and right subtrees if they might contain points within the radius
    if (root->left && (target.x - radius) <= root->point.x) {
        rangeSearch(root->left, target, radius, result);
    }
    if (root->right && (target.x + radius) >= root->point.x) {
        rangeSearch(root->right, target, radius, result);
    }
    if (root->left && (target.y - radius) <= root->point.y) {
        rangeSearch(root->left, target, radius, result);
    }
    if (root->right && (target.y + radius) >= root->point.y) {
        rangeSearch(root->right, target, radius, result);
    }
    if (root->left && (target.z - radius) <= root->point.z) {
        rangeSearch(root->left, target, radius, result);
    }
    if (root->right && (target.z + radius) >= root->point.z) {
        rangeSearch(root->right, target, radius, result);
    }
}
```

这次,我修正了对左右子树的递归调用,确保了在向下搜索时正确地限制了搜索范围。现在应该能够正确地找到给定点附近半径为0.1mm范围内的所有点。

抱歉,打印结果的小数位数不够精确是因为我没有设置输出精度。让我修正这个问题,确保打印结果的小数位数和原始数据一致。

```cpp
#include <iomanip> // Add this include for setprecision

// Function to perform range search in KD tree
void rangeSearch(KDNode* root, const Point3D& target, double radius, std::vector<Point3D>& result) {
    if (!root) return;

    // Calculate distance to current point
    double dist = distance(root->point, target);

    // If the current point is within the radius, add it to the result
    if (dist <= radius) {
        result.push_back(root->point);
    }

    // Determine current axis
    int axis = root->axis;

    // Recursively search left and right subtrees if they might contain points within the radius
    if (axis == 0) {
        if (root->left && (target.x - radius) <= root->point.x) {
            rangeSearch(root->left, target, radius, result);
        }
        if (root->right && (target.x + radius) >= root->point.x) {
            rangeSearch(root->right, target, radius, result);
        }
    }
    else if (axis == 1) {
        if (root->left && (target.y - radius) <= root->point.y) {
            rangeSearch(root->left, target, radius, result);
        }
        if (root->right && (target.y + radius) >= root->point.y) {
            rangeSearch(root->right, target, radius, result);
        }
    }
    else {
        if (root->left && (target.z - radius) <= root->point.z) {
            rangeSearch(root->left, target, radius, result);
        }
        if (root->right && (target.z + radius) >= root->point.z) {
            rangeSearch(root->right, target, radius, result);
        }
    }
}

int main() {
    // Build KD tree and other code...

    // Print the points within the range
    std::cout << std::fixed << std::setprecision(6); // Set precision to 6 decimal places
    std::cout << "Points within " << radius << "mm of (" << target.x << ", " << target.y << ", " << target.z << "):" << std::endl;
    for (const auto& p : result) {
        std::cout << "(" << p.x << ", " << p.y << ", " << p.z << ")" << std::endl;
    }

    // Cleanup and other code...
}
```

通过使用 `std::fixed` 和 `std::setprecision(6)`,我设置了输出的精度为 6 位小数,确保了打印结果的小数位数与原始数据一致。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1638881.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

机器学习-06-聚类算法总结

聚类总结 1.聚类 机器学习 任务 聚类 无label的 分类 label是离散的 回归 label是连续的 2.聚类算法-kmeans 划分聚类 思想&#xff1a; D中选取k个作为初始质心 repeat 计算所有点与质心的距离&#xff0c;分到近的质心簇 更新簇之间的质心 until 质心不改 不足&#xff…

TCP协议为什么使用三次握手进行连接?

回答: TCP协议使用三次握手来建立一个可靠的连接&#xff0c;确保两端的通信设备都准备好进行数据传输。这个过程涉及三个步骤&#xff1a; SYN&#xff1a;客户端发送一个SYN&#xff08;同步序列编号&#xff09;包到服务器&#xff0c;以开始新的连接。SYN-ACK&#xff1a;…

0418EmpTomCat项目 初次使用ajax实现局部动态离职

0418EmpTomCat项目包-CSDN博客 数据库字段&#xff1a; 员工部门表 分页查询&#xff1b; 多条件查询&#xff1b; 添加新员工&#xff1b; ajax点击离职操作效果&#xff1a;

什么是限流?常见的限流算法

目录 1. 什么是限流 2. 常见限流算法 3. 固定窗口算法 4. 滑动窗口算法 5. 漏桶算法 6. 令牌桶算法 7. 限流算法选择 1. 什么是限流 限流&#xff08;Rate Limiting&#xff09;是一种应用程序或系统资源管理的策略&#xff0c;用于控制对某个服务、接口或功能的访问速…

硬件知识积累 DP 接口简单介绍以及 DP信号飞线到显示屏的问题

1. DP 接口的介绍 定义与起源&#xff1a; DP接口是由PC及芯片制造商联盟开发&#xff0c;并由视频电子标准协会&#xff08;VESA&#xff09;标准化的数字式视频接口标准。它的设计初衷是为了取代传统的VGA、DVI和FPD-Link&#xff08;LVDS&#xff09;接口&#xff0c;以满足…

【PCL】教程 supervoxel_clustering执行超体聚类并可视化点云数据及其聚类结果

[done, 417.125 ms : 307200 points] Available dimensions: x y z rgba 源点云milk_cartoon_all_small_clorox.pcd > Loading point cloud... > Extracting supervoxels! Found 423 supervoxels > Getting supervoxel adjacency 这段代码主要是使用PCL&#xff08;Po…

【如此简单!数据库入门系列】之数据库设计基础--函数依赖

文章目录 问题函数依赖函数依赖的作用函数依赖的性质重新理解主键总结系列文章 问题 考虑一个在线商店数据库&#xff0c;其中包含以下表&#xff1a; 【订单表】 Order_Num(订单号)Product_ID(产品ID)Count(数量)Price(单价)110210021011003203200 你觉得这张表是否存在问…

【C++】深入理解string类

一、熟悉string类 1.1 string类的由来&#xff1a; C语音中的字符串需要我们自己管理底层空间&#xff0c;容易内存泄露。而C是面向对象语音&#xff0c;所以它把字符串封装成一个string类。 C中对于string的定义为&#xff1a;typedef basic_string string; 也就是说C中的str…

负债56亿,购买理财产品遭违约,操纵虚假粉丝,流量在下滑,客户数量减少,汽车之家面临大量风险(九)

本文由猛兽财经历时5个多月完成。猛兽财经将通过以下二十二个章节、8万字以上的内容来全面、深度的分析汽车之家这家公司。 由于篇幅限制&#xff0c;全文分为&#xff08;一&#xff09;到&#xff08;十&#xff09;篇发布。 本文为全文的第二十二章。 目录 一、汽车之家公…

Transformers:它们如何转换您的数据?

一、说明 在快速发展的人工智能和机器学习领域&#xff0c;一项创新因其对我们处理、理解和生成数据的方式产生深远影响而脱颖而出&#xff1a;Transformers。Transformer 彻底改变了自然语言处理 &#xff08;NLP&#xff09; 及其他领域&#xff0c;为当今一些最先进的 AI 应…

代码随想录-二叉树(节点)

目录 104. 二叉树的最大深度 题目描述&#xff1a; 输入输出描述&#xff1a; 思路和想法&#xff1a; 111. 二叉树的最小深度 题目描述&#xff1a; 输入输出描述&#xff1a; 思路和想法&#xff1a; 222. 完全二叉树的节点个数 题目描述&#xff1a; ​输入输出描…

关于举办《Llama3关键技术深度解析与构建Responsible AI、算法及开发落地实战》线上高级研修讲座的通知

关于举办《Llama3关键技术深度解析与构建Responsible AI、算法及开发落地实战》线上高级研修讲座的通知

Mybatis逆向工程的2种方法,一键高效快速生成Pojo、Mapper、XML,摆脱大量重复开发

一、写在开头 最近一直在更新《Java成长计划》这个专栏&#xff0c;主要是Java全流程学习的一个记录&#xff0c;目前已经更新到Java并发多线程部分&#xff0c;后续会继续更新&#xff1b;而今天准备开设一个全新的专栏 《EfficientFarm》。 EfficientFarm&#xff1a;高效农…

Tomcat PUT方法任意写文件漏洞(CVE-2017-12615)

1 漏洞原理 在Apache Tomcat服务器中&#xff0c;PUT方法通常用于上传文件。攻击者可以通过发送PUT请求&#xff0c;将恶意文件上传到服务器。 当攻击者发送PUT请求时&#xff0c;Tomcat服务器会将请求中的数据写入指定的文件。如果攻击者能够控制文件路径&#xff0c;那么他们…

Mac brew安装Redis之后更新配置文件的方法

安装命令 brew install redis 查看安装位置命令 brew list redis #查看redis安装的位置 % brew list redis /usr/local/Cellar/redis/6.2.5/.bottle/etc/ (2 files) /usr/local/Cellar/redis/6.2.5/bin/redis-benchmark /usr/local/Cellar/redis/6.2.5/bin/redis-check-ao…

跨平台桌面客户端开发框架

跨平台桌面客户端开发框架允许开发者创建能够在多个操作系统上运行的桌面应用程序。以下是一些流行的跨平台桌面客户端开发框架。这些框架各有优势&#xff0c;选择哪个框架取决于项目需求、团队的技术栈以及对特定特性的偏好。 1.Electron &#xff1a; 使用JavaScript, HTML…

Java IO流(三)

1. 字符流 1.1 什么是字符流 在Java中&#xff0c;字符流是指提供了基于字符的I/O能力的API。 Java 1.0中提供的基于字节的I/O流API只能支持8位字节流&#xff0c;无法妥善地处理16位Unicode字符。由于需要支持Unicode处理国际化字符&#xff0c;因此Java 1.1 对基础流式I/O库…

vue3+ts 原生 js drag drop 实现

vue3ts 原生 js drag drop 实现 一直以来没有涉及的一个领域就是 drag drop 拖动操作&#xff0c;研究了下&#xff0c;实现了&#xff0c;所以写个教程。 官方说明页面及实例&#xff1a;https://developer.mozilla.org/en-US/docs/Web/API/HTML_Drag_and_Drop_API 最终效果&…

SpringCloud整合Gateway结合Nacos

目录 一、引入依赖 二、开启两个测试项目 2.1 order service ​编辑 2.2 user service 三、gateway项目 3.1 新建一个bootstrap.yml文件 3.2 将我们的的网关配置写道nacos里的配置里 3.3 测试&#xff1a;看能够根据网关路由到两个测试的项目 四、 优化 4.1 将项目打包…

数据库(MySQL)—— DQL语句(聚合,分组,排序,分页)

数据库&#xff08;MySQL&#xff09;—— DQL语句&#xff08;聚合&#xff0c;分组&#xff0c;排序&#xff0c;分页&#xff09; 聚合函数常见的聚合函数语法 分组查询语法 排序查询语法 分页查询语法 DQL的执行顺序 我们今天来继续学习MySQL的DQL语句的聚合和分组查询&…