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

网站建设备案信息营销咨询顾问

网站建设备案信息,营销咨询顾问,广州海珠区繁华吗,绵阳市城乡建设和规划局网站文章目录一、问题描述二、解题思路​ 在做项目时遇到了一个数学问题,即,如何判断给定一个三角面片与空间中某个球体有相交部分?这个问题看似简单,实际处理起来需要一些方法和手段。一、问题描述 已知空间中球体的球心位置center&a…

文章目录

        • 一、问题描述
        • 二、解题思路

​ 在做项目时遇到了一个数学问题,即,如何判断给定一个三角面片与空间中某个球体有相交部分?这个问题看似简单,实际处理起来需要一些方法和手段。

一、问题描述

已知空间中球体的球心位置center,半径为r,三角形三个顶点分别为v1,v2,v3。判断该三角形与球体是否有交点?

二、解题思路

​ 通过写写画画,我们可以大致将球体和三角形的位置分为以下三种情况:

(一)三角形三个顶点至少有一个在球体内部

image-20230305153905184

​ 这种情况相对来说比较简单,只需要判断三角形三个顶点到球心的最小距离<半径 r 即可。

(二)三个顶点都在球体外部,但至少有一条线段与球体相交

image-20230305154203013

​ 计算三边所在直线到球心的距离,最短距离 < r 即可。

​ 但是同时需要确保 ∠OAC\angle OACOAC∠OCA\angle OCAOCA 均< ∠ODA\angle ODAODA,否则会出现以下错误的情况:

image-20230305154357287

​ 根本原因是,我们求的是线段与球体相交,而不是一条直线。

(三)三个顶点、三条边都在球体外部,但平面与球体相交

image-20230305154528284

​ 同理,计算球心到平面的距离 < r 即可。

​ 一样的,需要避免以下的情况,原因一样,我们求的是三角形与球体是否有交点,而不是平面:

image-20230305154638704

​ 判断方式:作球心 O 到平面 ABC 的投影 P,看 P 是否在三角形内部:

image-20230305154737066
  • 方法一: 面积法。算出三角形 ABP、BCP、CAP 的面积和,与 ABC 面积进行比较。如果相同,则 P 在内部

  • 方法二: 矢量法。若 P 在三角形内部,则:

    • 对 BC 而言,P、A 在同一侧
    • 对 CA 而言,P、B 在同一侧
    • 对 AB 而言,P、C 在同一侧

    可以用矢量的叉乘判断两点是否在线段的同一侧。

    即,对于 BC 而言,BP→×BC→\overrightarrow{BP}\times\overrightarrow{BC}BP×BCBP→×BA→\overrightarrow{BP}\times\overrightarrow{BA}BP×BA 同向,则 P、A 在同一侧。

实现代码:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class Segment
{public Vector3 start; // 起始位置public Vector3 end;   // 终点位置/// <summary>/// 线段向量/// </summary>public Vector3 vector => end - start;/// <summary>/// 单位方向/// </summary>public Vector3 direction => vector.normalized;/// <summary>/// 线段长度/// </summary>public float length => vector.magnitude;public Segment(Vector3 start, Vector3 end) {this.start = start;this.end   = end;}/// <summary>/// 计算点到线段所在直线的距离/// </summary>/// <param name="point">点</param>/// <returns></returns>public float LineDistance(Vector3 point) {float theta = Vector3.Angle(point - start, vector);return (point - start).magnitude * Mathf.Sin(Mathf.Deg2Rad * theta);}/// <summary>/// 线段是否穿过球体/// </summary>/// <param name="center">球心</param>/// <param name="radius">半径</param>/// <returns></returns>public bool CrossSphere(Vector3 center, float radius) {// 如果线段两端点其中一个在球体内部,直接返回 trueif (Vector3.Distance(center, start) < radius || Vector3.Distance(center, end) < radius) return true;// 球心到线段距离大于半径,则返回 falsefloat d = LineDistance(center);if (d >= radius) return false;// 计算球心与线段的两个夹角,以判断线段是否穿过球体float theta = Mathf.Asin(d / radius) * Mathf.Rad2Deg;float a1    = Vector3.Angle(center - start, vector);float a2    = Vector3.Angle(center - end,   -vector);return a1 <= theta && a2 <= theta;}/// <summary>/// 判断两点是否处于线段同一侧/// </summary>/// <param name="p1">点 1</param>/// <param name="p2">点 2</param>/// <returns></returns>public bool SameSide(Vector3 p1, Vector3 p2) {Vector3 v1 = Vector3.Cross(p1 - start, vector);Vector3 v2 = Vector3.Cross(p2 - start, vector);return Vector3.Dot(v1, v2) >= 0;}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;/// <summary>
/// 三角形
/// </summary>
public class Triangle
{public Vector3 v1; // 顶点 1public Vector3 v2; // 顶点 2public Vector3 v3; // 顶点 3/// <summary>/// 线段 12/// </summary>public Segment l1 => new Segment(v1, v2);/// <summary>/// 线段 23/// </summary>public Segment l2 => new Segment(v2, v3);/// <summary>/// 线段 31/// </summary>public Segment l3 => new Segment(v3, v1);/// <summary>/// 所在平面/// </summary>public Plane plane => new Plane(v1, v2, v3);public Triangle(Vector3 v1, Vector3 v2, Vector3 v3) {SetInfo(v1, v2, v3);}/// <summary>/// 设置三角形位置/// </summary>/// <param name="v1">顶点 1</param>/// <param name="v2">顶点 2</param>/// <param name="v3">顶点 3</param>public void SetInfo(Vector3 v1, Vector3 v2, Vector3 v3) {this.v1 = v1;this.v2 = v2;this.v3 = v3;}/// <summary>/// 顶点到点 point 的最小距离/// </summary>/// <param name="point">点 point</param>/// <returns></returns>public float MinPointDistance(Vector3 point) {float   d1 = Vector3.Distance(v1, point);float   d2 = Vector3.Distance(v2, point);float   d3 = Vector3.Distance(v3, point);return Mathf.Min(d1, d2, d3);}/// <summary>/// 投影转化为平面三角形(大小不变)/// </summary>/// <param name="center">投影中心</param>/// <returns>平面三角形</returns>public Triangle2D CastTriangle2D(Vector3 center) {Vector3 origin  = plane.ClosestPointOnPlane(center);Vector3 vector1 = v1 - origin;Vector3 vector2 = v2 - origin;Vector3 vector3 = v3 - origin;float a12 = Vector3.SignedAngle(vector1, vector2, plane.normal) * Mathf.Deg2Rad;float a13 = Vector3.SignedAngle(vector1, vector3, plane.normal) * Mathf.Deg2Rad;Vector2 p1 = new Vector2(vector1.magnitude,                  0);Vector2 p2 = new Vector2(vector2.magnitude * Mathf.Cos(a12), vector2.magnitude * Mathf.Sin(a12));Vector2 p3 = new Vector2(vector3.magnitude * Mathf.Cos(a13), vector3.magnitude * Mathf.Sin(a13));return new Triangle2D(p1, p2, p3);}/// <summary>/// 判断三角形是否穿过球体/// </summary>/// <param name="center">球心</param>/// <param name="radius">半径</param>/// <returns></returns>public bool CrossSphere(Vector3 center, float radius) {// 如果最近的点在球体内部则返回 tureif (MinPointDistance(center) < radius) return true;// 如果有线段穿过了球体,则返回 trueif (l1.CrossSphere(center, radius) || l2.CrossSphere(center, radius) || l3.CrossSphere(center, radius)) return true;// 否则投影球心到三角平面上,看其是否在三角形内float d = Mathf.Abs(plane.GetDistanceToPoint(center));if (d < radius) {                            // 球心到平面的距离小于半径才可能相交Triangle2D t2D = CastTriangle2D(center); // 进行投影return t2D.Contains(Vector2.zero);       // 判断}return false;}
}
using System;
using UnityEngine;/// <summary>
/// 平面线段
/// </summary>
public class Segment2D
{public Vector2 start; // 起始位置public Vector2 end;   // 终点位置/// <summary>/// 线段向量/// </summary>public Vector2 vector => end - start;/// <summary>/// 单位方向/// </summary>public Vector2 direction => vector.normalized;public float length => vector.magnitude;/// <summary>/// 线段长度/// </summary>public Segment2D(Vector2 start, Vector2 end) {this.start = start;this.end   = end;}/// <summary>/// 判断两点是否处于线段同一侧/// </summary>/// <param name="p1">点 1</param>/// <param name="p2">点 2</param>/// <returns></returns>public bool SameSide(Vector2 p1, Vector2 p2) {Vector3 v1 = Vector3.Cross(p1 - start, vector);Vector3 v2 = Vector3.Cross(p2 - start, vector);return Vector3.Dot(v1, v2) >= 0;}
}
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class Triangle2D 
{public Vector2 v1; // 顶点 1public Vector2 v2; // 顶点 2public Vector2 v3; // 顶点 3/// <summary>/// 线段 12/// </summary>public Segment2D l1 => new Segment2D(v1, v2);/// <summary>/// 线段 23/// </summary>public Segment2D l2 => new Segment2D(v2, v3);/// <summary>/// 线段 31/// </summary>public Segment2D l3 => new Segment2D(v3, v1);public Triangle2D(Vector2 v1, Vector2 v2, Vector2 v3) {SetInfo(v1, v2, v3);}/// <summary>/// 设置三角形位置/// </summary>/// <param name="v1">顶点 1</param>/// <param name="v2">顶点 2</param>/// <param name="v3">顶点 3</param>public void SetInfo(Vector2 v1, Vector2 v2, Vector2 v3) {this.v1 = v1;this.v2 = v2;this.v3 = v3;}/// <summary>/// 判断点 point 是否在三角形内部/// </summary>/// <param name="point">点</param>/// <returns></returns>public bool Contains(Vector2 point) {return l1.SameSide(point, v3) && l2.SameSide(point, v1) && l3.SameSide(point, v2);}
}
http://www.yidumall.com/news/35199.html

相关文章:

  • 宿迁市宿城区二手房最新消息seo发帖软件
  • 云南网站建设方案seo推广平台服务
  • 安装了wordpress程序seo网络搜索引擎优化
  • wordpress如何关闭网页福州seo网站排名
  • 网站设计公司网页设计产品软文模板
  • 用cms做网站的具体步骤珠海百度搜索排名优化
  • 网站制作公司珠海百度应用商店app下载
  • 吉林企业建站系统费用seo网站分析报告
  • 网站需要哪些手续清远疫情防控措施
  • 软件界面设计软件有哪些东莞seo网络公司
  • 企业做网站需要什么软件百度企业
  • 一个女的让我和她做优惠网站百度浏览器下载官方免费
  • 合肥网站建设哪里好龙网网络推广软件
  • 网站建设与管理书籍sem竞价专员
  • 精美化妆品网站模板排名第一的助勃药
  • 南充做网站公司北京网络营销咨询公司
  • 在美国做网站如何接入收款工具链接买卖
  • 虚拟机网站建设推广手段有哪些
  • 佛山网站搭建费用杭州百度推广代理公司哪家好
  • 做网站每个月可以赚多少已备案域名30元
  • 洞口网站建设免费推广app软件下载
  • 中国黄页网seo海外
  • 医院管理系统网站开发产品营销方案
  • 淮北市建筑北京百度seo排名公司
  • 查网站空间商关键词推广价格
  • 如何做亚马逊国外网站百度推广登录平台客服
  • wordpress 标签链接地址系统优化软件有哪些
  • 做一个网站只做前端怎么做网络广告文案案例
  • 邢台做网站网络推广方案有哪些
  • 盘锦网站建设雅虎搜索引擎中文版