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

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

于是我开始问AI,他一开始给的答案,完全是错误的,但是我一步步给出反馈,告诉他的问题,他居然给出的正确的答案(我和python代码做了对比,python现成程的库实现,可作为结果进行参考)

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

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

#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 zKDNode(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 axisint axis = depth % 3;// Sort points based on current axisif (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; });elsestd::sort(points.begin(), points.end(), [](const Point3D& a, const Point3D& b) { return a.z < b.z; });// Find mediansize_t medianIdx = points.size() / 2;KDNode* node = new KDNode(points[medianIdx]);node->axis = axis;// Recursively build left and right subtreesstd::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 treeKDNode* root = buildKDTree(points);// Print KD tree (for debugging)printKDTree(root);// Cleanup// You need to implement a function to delete the KD tree nodesreturn 0;
}

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

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

#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 zKDNode(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 axisint axis = depth % 3;// Sort points based on current axisif (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; });elsestd::sort(points.begin(), points.end(), [](const Point3D& a, const Point3D& b) { return a.z < b.z; });// Find mediansize_t medianIdx = points.size() / 2;KDNode* node = new KDNode(points[medianIdx]);node->axis = axis;// Recursively build left and right subtreesstd::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 pointdouble dist = distance(root->point, target);// If the current point is within the radius, add it to the resultif (dist <= radius) {result.push_back(root->point);}// Recursively search left and right subtrees if they might contain points within the radiusif (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 treeKDNode* root = buildKDTree(points);// Define the target point and search radiusPoint3D target = {1.0, 2.0, 3.0};double radius = 0.1; // in this case, 0.1mm// Perform range searchstd::vector<Point3D> result;rangeSearch(root, target, radius, result);// Print the points within the rangestd::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 nodesreturn 0;
}

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

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

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

// 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 pointdouble dist = distance(root->point, target);// If the current point is within the radius, add it to the resultif (dist <= radius) {result.push_back(root->point);}// Recursively search left and right subtrees if they might contain points within the radiusif (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范围内的所有点。

我明白了问题所在。在 `rangeSearch` 函数中,我没有正确地检查当前节点的坐标与目标点的距离,以确定是否需要继续向下搜索。让我来修正这个问题,确保每个节点只在满足条件时才向下搜索。

// 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 pointdouble dist = distance(root->point, target);// If the current point is within the radius, add it to the resultif (dist <= radius) {result.push_back(root->point);}// Determine current axisint axis = root->axis;// Recursively search left and right subtrees if they might contain points within the radiusif (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);}}
}

在这个修正版本中,我添加了对当前节点的坐标与目标点的距离的检查,以确定是否需要继续向下搜索。这样就可以确保每个节点只在满足条件时才向下搜索,从而避免了重复添加点的问题。现在应该能够正确地找到给定点附近半径为0.1mm范围内的所有点。

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

#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 pointdouble dist = distance(root->point, target);// If the current point is within the radius, add it to the resultif (dist <= radius) {result.push_back(root->point);}// Determine current axisint axis = root->axis;// Recursively search left and right subtrees if they might contain points within the radiusif (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 rangestd::cout << std::fixed << std::setprecision(6); // Set precision to 6 decimal placesstd::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 位小数,确保了打印结果的小数位数与原始数据一致。

python的实现(作为验证AI的答案是否正确)

from scipy.spatial import KDTree
import timedef read_points_from_file(filename):points = []with open(filename, 'r') as file:for line in file:# 解析每行数据,并转换为浮点数x, y, z = map(float, line.strip().split(','))points.append((x, y, z))return pointsdef find_points_in_range(kd_tree, target_point, radius):# 使用 KD 树的 query_ball_point 方法搜索指定范围内的所有点indices = kd_tree.query_ball_point(target_point, radius)return [kd_tree.data[i] for i in indices]def main():start_time = time.time()#filename = "D:/test_pro/old/CppTest/算法测试/test0/x64/Debug/test.txt";filename = "D:/test_pro/old/CppTest/算法测试/test0/x64/Debug/20240502.txt";points = read_points_from_file(filename)end_time = time.time()duration = (end_time - start_time) * 1000  # 将秒转换为毫秒print("文件读取时间:", duration, "milliseconds")start_time = time.time()kd_tree = KDTree(points)end_time = time.time()duration = (end_time - start_time) * 1000  # 将秒转换为毫秒print("构建kd树时间:", duration, "milliseconds")target_point = ( -141.874398,25.022764,2.484327)radius = 1start_time = time.time()points_in_range = find_points_in_range(kd_tree, target_point, radius)end_time = time.time()duration = (end_time - start_time) * 1000  # 将秒转换为毫秒print("查找时间:", duration, "milliseconds")print("一共有:", len(points_in_range), "个点")print("在指定范围内的点有:", points_in_range)for item in points_in_range:print(f'{item[0]},{item[1]},{item[2]}')if __name__ == "__main__":main()

小结

 让我比较震惊的一点是,它无法直接给出正确的答案,但是如果能正确的指出它的错误,它居然就能一次次逼近正确,最终给出正确的答案。

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

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

相关文章

nuxt3使用记录六:禁用莫名其妙的Tailwind CSS(html文件大大减小)

发现这个问题是因为&#xff0c;今天我突然很好奇&#xff0c;我发现之前构建的自动产生的200.html和404.html足足290k&#xff0c;怎么这么大呢&#xff1f;不是很占用我带宽&#xff1f; 一个啥东西都没有的静态页面&#xff0c;凭啥这么大&#xff01;所以我就想着手动把他…

ThinkPHP--5.0.23-rce远程代码执行

一、漏洞原理 实现框架的核心类Requests的method方法实现表单请求类伪装&#xff0c;默认为$_POST[‘_method’]变量&#xff0c;却没有对_method属性进行严格校验&#xff0c;可以通过变量覆盖Requests类的属性&#xff0c;在结合框架特性实现对任意函数的调用实现任意代码执…

Linux shell编程学习笔记48:touch命令

0 前言 touch是csdn技能树Linux基础练习题中最常见的一条命令&#xff0c;这次我们就来研究它的功能和用法。 1. touch命令的功能、格式和选项说明 我们可以使用命令 touch --help 来查看touch命令的帮助信息。 purpleEndurer bash ~ $ touch --help Usage: touch [OPTION]…

idm线程怎么设置 idm线程数怎么上不去 idm免安装

IDM&#xff08;Internet Download Manager&#xff09;是一款流行的下载管理软件&#xff0c;IDM采用高级的多线程下载技术&#xff0c;可以将下载文件分成多个部分同时下载&#xff0c;从而提高下载速度&#xff0c;它因高效的下载速度和丰富的功能而受到用户的喜爱。接下来&…

MVC和DDD的贫血和充血模型对比

文章目录 架构区别MVC三层架构DDD四层架构 贫血模型代码示例 充血模型代码示例 架构区别 MVC三层架构 MVC三层架构是软件工程中的一种设计模式&#xff0c;它将软件系统分为 模型&#xff08;Model&#xff09;、视图&#xff08;View&#xff09;和控制器&#xff08;Contro…

一个5000刀的XSS

背景介绍 今天分享国外一个白帽小哥Crypto通过发现Apple某网站XSS而获得5000美元赏金的故事。废话不多说&#xff0c;让我们开始吧&#xff5e; 狩猎过程 易受攻击的 Apple 服务网站是&#xff1a;https://discussions.apple.com&#xff0c;该服务是苹果用户和开发者讨论问题…

这是一个简单网站,后续还会更新

1、首页效果图 代码 <!DOCTYPE html> <html> <head> <meta charset"utf-8" /> <title>爱德照明网站首页</title> <style> /*外部样式*/ charset "utf-8"…

Luminar开始为沃尔沃生产下一代激光雷达传感器

在自动驾驶技术的浪潮中&#xff0c;激光雷达&#xff08;LiDAR&#xff09;传感器以其高精度和强大的环境感知能力&#xff0c;逐渐成为了该领域的技术之星。Luminar&#xff08;路安达&#xff09;公司作为自动驾驶技术的领军企业&#xff0c;近日宣布已开始为沃尔沃汽车生产…

MySQL-笔记-08.数据库编程

目录 8.1 编程基础 8.1.1 基本语法 8.1.2 运算符与表达式 1. 标识符 2. 常量 &#xff08;1&#xff09; 字符串常量 &#xff08;2&#xff09;日期时间常量 &#xff08;3&#xff09;数值常量 &#xff08;4&#xff09;布尔值常量 &#xff08;5&#xff09;NULL…

如何使用免费软件从Mac恢复音频文件?

要从Mac中删除任何文件&#xff0c;背后是有原因的。大多数Mac用户都希望增加Mac中的空间&#xff0c;这就是为什么他们更喜欢从驱动器中删除文件以便出现一些空间的原因。一些Mac用户错误地删除了该文件&#xff0c;无法识别这是一个重要文件。例如&#xff0c;他们错误地从Ma…

小区服务|基于SprinBoot+vue的小区服务管理系统(源码+数据库+文档)

目录 基于SprinBootvue的小区服务管理系统 一、前言 二、系统设计 三、系统功能设计 1管理员登录 2 客服聊天管理、反馈管理管理 3 公告信息管理 4公告类型管理 四、数据库设计 五、核心代码 六、论文参考 七、最新计算机毕设选题推荐 八、源码获取&#xff1a; 博…

计算机网络复习-网络层

章节主要内容 虚拟互连网络 实际的计算机网络是错综复杂的物理设备通过使用ip协议&#xff0c;屏蔽了物理网络之间的差异当网络中的主机使用ip协议连接时&#xff0c;则无需关注网络细节 IP协议 ip协议使得复杂的实际网络变为一个虚拟互连的网络ip协议使得网络层可以屏蔽细…

Debian 12 tomcat 9 catalina 日志信息 中文显示乱码

目录 问题现象 解决办法&#xff1a; 1、设定Debian locale 2、设定catalina.sh utf8字符集 问题现象 Debian 12 linux操作系统中&#xff0c;tomcat 9 catalina 启动日志输出 中文乱码 解决办法&#xff1a; 1、设定Debian locale 先确保系统本身就支持中文的 Debian …

[CUDA 学习笔记] GEMM 优化: 双缓冲 (Prefetch) 和 Bank Conflict 解决

GEMM 优化: 双缓冲 (Prefetch) 和 Bank Conflict 解决 前言 本文主要是对 深入浅出GPU优化系列&#xff1a;GEMM优化&#xff08;一&#xff09; - 知乎, 深入浅出GPU优化系列&#xff1a;GEMM优化&#xff08;二&#xff09; - 知乎 以及 深入浅出GPU优化系列&#xff1a;GE…

操作系统:线程互斥|线程同步|锁的概念

目录 前言 1.线程互斥 1.1.互斥量|锁的使用 1.2.锁的本质 1.3.死锁 1.3.1.什么是死锁 1.3.2.死锁产生的4个必要条件 1.3.3.如何避免死锁 2.线程同步 2.1.知识引入 2.2.条件变量 2.2.1.为什么需要条件变量 2.2.2.条件变量接口 前言 进行这一章节的学习之前&#xf…

25计算机考研院校数据分析 | 哈尔滨工业大学

哈尔滨工业大学&#xff08;Harbin Institute of Technology&#xff09;&#xff0c;简称哈工大&#xff0c; 校本部位于黑龙江省哈尔滨市&#xff0c;是由工业和信息化部直属的全国重点大学&#xff0c;位列国家“双一流”、“985工程”、“211工程”&#xff0c;九校联盟 、…

Word文件导出为PDF

Word文件导出为PDF 方法一、使用Word自带另存为PDF功能 打开需要转换为PDF格式的Word文件&#xff0c;依次点击【文件】➡【另存为】➡选择文件保存类型为.PDF 使用这种方法导出的PDF可能存在Word中书签丢失的情况&#xff0c;在导出界面点击&#xff0c;选项进入详细设置 勾…

Python中的`return`语句详解

Python中的return语句详解 对于初学Python或任何编程语言的人来说&#xff0c;理解函数如何返回值是非常重要的。在Python中&#xff0c;return语句用于从函数中返回结果。本篇博客将详细介绍return语句的基本用法&#xff0c;以及如何在不同情境中有效使用它。 什么是return…

U盘未初始化?别慌,数据还有救!

当我们将U盘插入电脑&#xff0c;期待地打开“我的电脑”或文件管理器&#xff0c;却发现U盘显示为未初始化&#xff0c;这种心情无异于一盆冷水浇头。但先别急着慌张&#xff0c;这篇文章将带你了解U盘未初始化的原因&#xff0c;并提供有效的数据恢复方案&#xff0c;让你在遭…

【记录】Python3| 将 PDF 转换成 HTML/XML(✅⭐pdfminer.six)

本文将会被汇总至 【记录】Python3&#xff5c;2024年 PDF 转 XML 或 HTML 的第三方库的使用方式、测评过程以及对比结果&#xff08;汇总&#xff09;&#xff0c;更多其他工具请访问该文章查看。 注意&#xff01;pdfminer.six 和 pdfminer3k 不是同一个&#xff01;&#xf…