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 ? "内部" : "外部")}");
//}
相关推荐
浮生望几秒前
React useRef 深度解析:从DOM操作到Web Worker多线程协作
前端
浮生望6 分钟前
React Router v7 实战全景:路由配置、嵌套路由、鉴权守卫与懒加载完整指南
前端
用户938515635078 分钟前
从零在浏览器里跑 DeepSeek-R1:WebGPU + Transformer.js 全链路实战(二)
前端·javascript·typescript
雪隐32 分钟前
个人电脑玩AI-16让5060 Ti给你打工——MiniMax H3 提速实录:从"泡杯茶等视频"到"视频等你",一张 5060 Ti 的自我修养
前端·人工智能·后端
今天AI了吗1 小时前
MCP 协议打通 AI 与国产数据库,SQL 调优全流程一站式闭环
数据库·人工智能·sql
FungLeo1 小时前
Flutter Web 中文字体困境与渲染器选择:CanvasKit vs HTML renderer 实战
前端·flutter·html
灯澜忆梦1 小时前
【MySQL11】进阶篇 | 索引_#3使用规则
数据库·sql·mysql·性能优化
名字还没想好☜1 小时前
Go 的 sync.Cond 实战:用条件变量做等待/通知,比忙轮询省 CPU
开发语言·数据库·后端·golang·go
敲代码的玉米C1 小时前
我修的那个 bug,制造了另一个 bug
前端·人工智能·架构
gis开发之家1 小时前
《Vue3 从入门到大神50篇》Vue3 源码详解(二十):生命周期钩子源码解析 —— onMounted / onUpdated 如何实现?
前端·javascript·前端框架·vue3·vue3源码