geometry4Sharp Ray-Mesh求交 判断点是否在几何体内部

C# 7.3

geometry4Sharp 1.0.0

该C#代码实现了一个STL模型点位置检测器,使用geometry3Sharp库处理3D网格数据。核心功能包括:

  1. 加载STL文件并验证模型封闭性;

  2. 采用改进的射线投射算法(包含5次随机方向测试)判断点是否在模型内部;

  3. 提供单点和批量检测功能。

算法先进行快速边界框排除,再通过计算射线与三角形交点数确定位置,增强了结果的可靠性。适用于需要判断三维空间中点与STL模型位置关系的应用场景。

cs 复制代码
using g4;
using System;
using System.Collections.Generic;

public class STLPointChecker
{
  private DMesh3 mesh;
  private AxisAlignedBox3d bounds;

  public STLPointChecker(string stlFilePath)
  {
    DMesh3Builder builder = new DMesh3Builder();
    StandardMeshReader reader = new StandardMeshReader() { MeshBuilder = builder };
    IOReadResult result = reader.Read(stlFilePath, ReadOptions.Defaults);
    if (result.code == IOCode.Ok)
      mesh = builder.Meshes[0];

    if (mesh == null)
      return;

    if (!mesh.IsClosed())
      throw new Exception("STL模型不是封闭的,无法判断内外");

    bounds = mesh.CachedBounds;
  }

  // 射线法判断点是否在内部(基础可靠版)
  public bool IsPointInside(Vector3d testPoint)
  {
    if (mesh == null)
    {
      Console.WriteLine("Mesh is null");
      return false;
    }

    // 快速边界框排除
    if (!bounds.Contains(testPoint))
      return false;

    // 创建射线(沿X轴正方向)
    Ray3d ray = new Ray3d(testPoint, Vector3d.AxisX);
    int intersectionCount = 0;
    var rand = new Random();

    // 为确保稳定性,可发射多条随机方向的射线取多数结果
    for (int i = 0; i < 5; i++)
    {
      if (i > 0) // 第一次用X轴,后续用随机方向
      {
        Vector3d randomDir = new Vector3d(
            rand.NextDouble() * 2.0 - 1.0,
            rand.NextDouble() * 2.0 - 1.0,
            rand.NextDouble() * 2.0 - 1.0
        ).Normalized;
        ray = new Ray3d(testPoint, randomDir);
      }

      int count = CountRayIntersections(ray);
      if (count % 2 == 1) // 奇数个交点在内部
        intersectionCount++;
    }

    // 5条射线中3条以上认为在内部则判定为内部
    return intersectionCount >= 3;
  }

  private int CountRayIntersections(Ray3d ray)
  {
    int count = 0;

    // 遍历所有三角形
    foreach (int tid in mesh.TriangleIndices())
    {
      // 使用 geometry3Sharp 内置的高效求交方法
      IntrRay3Triangle3 intersection = new IntrRay3Triangle3(ray,
          new Triangle3d(
              mesh.GetVertex(mesh.GetTriangle(tid).a),
              mesh.GetVertex(mesh.GetTriangle(tid).b),
              mesh.GetVertex(mesh.GetTriangle(tid).c)
          )
      );

      if (intersection.Find() && intersection.IsSimpleIntersection)
      {
        if (intersection.RayParameter > 0) // 确保交点在射线正方向
          count++;
      }
    }

    return count;
  }

  // 批量检查多个点
  public Dictionary<Vector3d, bool> CheckPoints(List<Vector3d> points)
  {
    var results = new Dictionary<Vector3d, bool>();
    foreach (var point in points)
    {
      results[point] = IsPointInside(point);
    }
    return results;
  }
}

// 使用示例
//var checker = new STLPointChecker(@"E:\Data\PathPlanning\convex_hull.stl");

//// 检查单个点
//Vector3d testPoint = new Vector3d(10.0, 5.0, 2.0);
//bool inside = checker.IsPointInside(testPoint);
//Console.WriteLine($"点 ({testPoint.x}, {testPoint.y}, {testPoint.z}) 在内部: {inside}");

//// 批量检查
//var points = new List<Vector3d>
//            {
//                new Vector3d(0, 0, 0),
//                new Vector3d(50, 50, 50),
//                new Vector3d(-10, -10, -10),
//                new Vector3d(2104.38, 633.567, 775.12)
//            };

//var results = checker.CheckPoints(points);
//foreach (var kvp in results)
//{
//  Console.WriteLine($"点 {kvp.Key}: {(kvp.Value ? "内部" : "外部")}");
//}
相关推荐
counterxing13 小时前
我把 Codex 里的 Skills 做成了一个 MCP,还支持分享
前端·agent·ai编程
wangqiaowq14 小时前
windows下nginx的安装
linux·服务器·前端
之歆14 小时前
DAY_12JavaScript DOM 完全指南(二):实战与性能篇
开发语言·前端·javascript·ecmascript
星星也在雾里14 小时前
PgBouncer 解决 PostgreSQL 连接数超限 + 可视化监控
数据库·postgresql
发现一只大呆瓜14 小时前
Vite凭什么这么快?3分钟带你彻底搞懂 Vite 热更新的幕后黑手
前端·面试·vite
Maimai1080814 小时前
React如何用 @microsoft/fetch-event-source 落地 SSE:比原生 EventSource 更灵活的实时推送方案
前端·javascript·react.js·microsoft·前端框架·reactjs·webassembly
cen__y15 小时前
Linux12(Git01)
linux·运维·服务器·c语言·开发语言·git
雨辰AI16 小时前
SpringBoot3 + 人大金仓读写分离 + 分库分表 + 集群高可用 全栈实战
java·数据库·mysql·政务
长城202416 小时前
关于MySql的ONLY_FULL_GROUP_BY问题
数据库·mysql·聚合列
kyriewen16 小时前
产品经理把PRD写成“天书”,我用AI半小时重写了一遍,他当场愣住
前端·ai编程·cursor