当前位置: 首页 > news >正文

解析几何——求点A到点B和C组成直线的垂线的距离,以及点到线段的距离

数学原理

给定三点 A, B, C,点A到直线BC的距离可以通过以下公式计算:

[d=∣(C−B)×(A−B)∣∣C−B∣][ d = \frac{|(C-B) \times (A-B)|}{|C-B|} ][d=CB(CB)×(AB)]

其中:

  • × 表示二维向量的叉积
  • |v| 表示向量的模长

C++ 实现

#include <cmath>
#include <iostream>struct Point {
double x;
double y;Point(double x = 0, double y = 0) : x(x), y(y) {}
};/**
* @brief 计算点A到直线BC的垂直距离
* @param A 目标点
* @param B 直线上的一点
* @param C 直线上的另一点
* @return 点A到直线BC的垂直距离
*/
double pointToLineDistance(const Point& A, const Point& B, const Point& C) {
// 计算向量BC和BA
double bc_x = C.x - B.x;
double bc_y = C.y - B.y;double ba_x = A.x - B.x;
double ba_y = A.y - B.y;// 计算叉积的绝对值 |BC × BA|
double cross_product = std::abs(bc_x * ba_y - bc_y * ba_x);// 计算向量BC的模长
double bc_length = std::sqrt(bc_x * bc_x + bc_y * bc_y);// 避免除零错误
if (bc_length < 1e-10) {
// B和C重合,退化为两点间距离
return std::sqrt((A.x - B.x) * (A.x - B.x) + (A.y - B.y) * (A.y - B.y));
}// 距离 = 平行四边形面积 / 底边长
return cross_product / bc_length;
}/**
* @brief 计算点A到线段BC的最近距离(可能不是垂直距离)
* @param A 目标点
* @param B 线段端点
* @param C 线段另一端点
* @return 点A到线段BC的最近距离
*/
double pointToSegmentDistance(const Point& A, const Point& B, const Point& C) {
// 计算向量
double ab_x = B.x - A.x;
double ab_y = B.y - A.y;
double ac_x = C.x - A.x;
double ac_y = C.y - A.y;
double bc_x = C.x - B.x;
double bc_y = C.y - B.y;// 计算点积来确定投影点在线段上的位置
double t = ((A.x - B.x) * (C.x - B.x) + (A.y - B.y) * (C.y - B.y));// 如果投影点在B的外侧
if (t <= 0) {
return std::sqrt(ab_x * ab_x + ab_y * ab_y);
}double cb_length_sq = bc_x * bc_x + bc_y * bc_y;// 避免除零错误
if (cb_length_sq < 1e-10) {
return std::sqrt(ab_x * ab_x + ab_y * ab_y);
}t /= cb_length_sq;// 如果投影点在C的外侧
if (t >= 1) {
return std::sqrt(ac_x * ac_x + ac_y * ac_y);// 投影点在线段中间,返回垂直距离
return pointToLineDistance(A, B, C);
}// 测试函数
int main() {
// 测试用例
Point A(1, 1);// 目标点
Point B(0, 0);// 直线上的一点
Point C(3, 0);// 直线上的另一点double distance = pointToLineDistance(A, B, C);std::cout << "点A(" << A.x << "," << A.y << ") ";
std::cout << "到直线BC(B:" << B.x << "," << B.y;
std::cout << " -> C:" << C.x << "," << C.y << ") 的距离为: ";
std::cout << distance << std::endl;// 更多测试用例
Point testCases[][3] = {
{{0, 1}, {0, 0}, {1, 0}},// 期望距离为1
{{2, 2}, {0, 0}, {1, 1}},// 共线情况,期望距离为0
{{1, 0}, {0, 0}, {0, 1}}// 期望距离为√2/2 ≈ 0.707
};for (int i = 0; i < 3; ++i) {
double dist = pointToLineDistance(testCases[i][0],
testCases[i][1],
testCases[i][2]);
std::cout << "测试用例 " << i+1 << ": 距离 = " << dist << std::endl;
}return 0;
}

更简洁的实现版本

如果你想要一个更加紧凑的函数:

#include <cmath>struct Point {
double x, y;
};double pointToLineDistance(const Point& A, const Point& B, const Point& C) {
// 向量BC和BA的叉积的绝对值除以BC的模长
return std::abs((C.x - B.x) * (A.y - B.y) - (C.y - B.y) * (A.x - B.x)) /
std::sqrt((C.x - B.x) * (C.x - B.x) + (C.y - B.y) * (C.y - B.y));
}

使用标准库的增强版本

#include <cmath>
#include <algorithm>struct Point {
double x, y;
};double pointToLineDistance(const Point& A, const Point& B, const Point& C) {
double numerator = std::abs((C.x - B.x) * (A.y - B.y) - (C.y - B.y) * (A.x - B.x));
double denominator = std::sqrt(std::pow(C.x - B.x, 2) + std::pow(C.y - B.y, 2));// 处理B和C重合的特殊情况
if (denominator < 1e-10) {
return std::hypot(A.x - B.x, A.y - B.y);return numerator / denominator;
}

关键要点

  1. 数学基础:使用向量叉积计算平行四边形的面积,然后除以底边长度得到高度

  2. 边界情况处理

  • B和C重合时退化为两点间距离
  • 浮点数精度考虑
  1. 时间复杂度:O(1) 常数时间

  2. 适用场景

  • 计算机图形学
  • 路径规划
  • 碰撞检测
  • 地理信息系统
http://www.dtcms.com/a/574153.html

相关文章:

  • 网校 039 网站建设多少钱济南做微网站推广
  • 一台云服务器可以做多少个网站国外网站在国内备案
  • 应用案例实践 | 基于“隐语SecretFlow”多方安全分析的智能化理赔
  • 北京做erp报价的网站做网站用vue吗
  • 大话大模型应用(二)--让大模型听话:Prompt EngineeringContext Engineering
  • 中国古建筑网站高清视频网络服务器免费
  • 自适应网站做多大尺寸的开网站做淘宝客
  • 朝阳网站推广企业网站模板价格
  • ControlNet:Adding Conditional Control to Text-to-Image Diffusion Models
  • 网站维护的方法asp.net 4.0网站开发实例教程
  • web前端 DSL转换技术
  • 有什么好的网站推荐一下成都网页制作要多少钱
  • 厦门建设厅网站站长工具seo综合查询官网
  • 灯塔工厂:如何通过数字化实现制造升级
  • 电商网站 内容优化哪一个网站有做实验的过程
  • 电商平台数据分析市场洞察:API 技术如何打通数据价值闭环
  • 网站设计O2O平台小学学校网站
  • 做企业网站需要准备什么材料手机网站成功案例
  • gitLab如何新建分支(根据某个分支)
  • WEEX平台安全验证技术规范与实践
  • C++ opencv简化轮廓
  • 网站服务器租用和托管wordpress 个人国内收款
  • Java中将System.out内容写入Tomcat日志
  • 做国外的营销的网站官方网站撰写策划书
  • dmp导出到asm可以吗?
  • lprm命令 – 移除打印队列中的任务
  • BuildingAI二开 用户信息增加Coze套餐名称和剩余天数PRD
  • 网站建设有几种方法如何建设一个网站站
  • 格朗图手表网站网站建设服务亮点
  • 银行“两地三中心”网络高可用运维监控方案