namespace Yw.WinFrmUI.Hydro
|
{
|
/// <summary>
|
/// 射线碰撞
|
/// </summary>
|
internal static class Ray32dCaster
|
{
|
|
/// <summary>
|
/// 投射
|
/// </summary>
|
/// <param name="ray">射线</param>
|
/// <param name="zoom">缩放</param>
|
/// <param name="visuals">可见构件列表</param>
|
/// <param name="vecache">点缓存</param>
|
public static List<VisualL3d> Casting(this Ray3 ray, float zoom, List<VisualL3d> visuals, Vector3CacheHelper vecache)
|
{
|
if (ray == null)
|
{
|
return default;
|
}
|
if (visuals == null || visuals.Count < 1)
|
{
|
return default;
|
}
|
if (vecache == null)
|
{
|
return default;
|
}
|
var list = new List<VisualL3d>();
|
foreach (var visual in visuals)
|
{
|
if (visual is NodeL3d node)
|
{
|
var vec = vecache.GetById(node.Id);
|
var epsilon = node.Style2d.Normal.Radiu * zoom;
|
if (ray.IntersectsPoint(vec[0], epsilon, float.MaxValue, out _))
|
{
|
list.Add(visual);
|
}
|
}
|
else if (visual is LinkL3d link)
|
{
|
var vec = vecache.GetById(link.Id);
|
var epsilon = link.Style2d.Normal.Width / 2f * zoom;
|
if (ray.IntersectsLine(vec[0], vec[1], epsilon, float.MaxValue, out _))
|
{
|
list.Add(visual);
|
}
|
}
|
}
|
return list;
|
}
|
|
/// <summary>
|
/// 投射最近节点
|
/// </summary>
|
/// <param name="ray">射线</param>
|
/// <param name="zoom">缩放</param>
|
/// <param name="nodes">节点</param>
|
/// <param name="vecache">点缓存</param>
|
/// <returns></returns>
|
public static NodeL3d CastingClosest(this Ray3 ray, float zoom, List<NodeL3d> nodes, Vector3CacheHelper vecache)
|
{
|
if (ray == null)
|
{
|
return default;
|
}
|
if (nodes == null || nodes.Count < 1)
|
{
|
return default;
|
}
|
if (vecache == null)
|
{
|
return default;
|
}
|
NodeL3d closest = null;
|
float minDistance = float.MaxValue;
|
foreach (var node in nodes)
|
{
|
var vec = vecache.GetById(node.Id);
|
var epsilon = node.Style2d.Normal.Radiu * zoom;
|
if (ray.IntersectsPoint(vec[0], epsilon, float.MaxValue, out float distance))
|
{
|
if (distance <= minDistance)
|
{
|
minDistance = distance;
|
closest = node;
|
}
|
}
|
}
|
return closest;
|
}
|
|
/// <summary>
|
/// 投射最近管段
|
/// </summary>
|
/// <param name="ray">射线</param>
|
/// <param name="links">管段</param>
|
/// <param name="vecache">点缓存</param>
|
/// <returns></returns>
|
public static LinkL3d CastingClosest(this Ray3 ray, float zoom, List<LinkL3d> links, Vector3CacheHelper vecache)
|
{
|
if (ray == null)
|
{
|
return default;
|
}
|
if (links == null || links.Count < 1)
|
{
|
return default;
|
}
|
if (vecache == null)
|
{
|
return default;
|
}
|
LinkL3d closest = null;
|
float minDistance = float.MaxValue;
|
foreach (var link in links)
|
{
|
var vec = vecache.GetById(link.Id);
|
var epsilon = link.Style2d.Normal.Width * zoom;
|
if (ray.IntersectsLine(vec[0], vec[1], epsilon, float.MaxValue, out float distance))
|
{
|
if (distance <= minDistance)
|
{
|
minDistance = distance;
|
closest = link;
|
}
|
}
|
}
|
return closest;
|
}
|
|
/// <summary>
|
/// 投射最近构件
|
/// </summary>
|
/// <param name="ray">射线</param>
|
/// <param name="nw">管网</param>
|
/// <param name="vecache">点缓存</param>
|
/// <returns></returns>
|
public static VisualL3d CastingClosest(this Ray3 ray, float zoom, NetworkL3d nw, Vector3CacheHelper vecache)
|
{
|
VisualL3d visual = CastingClosest(ray, zoom, nw?.Nodes, vecache);
|
if (visual == null)
|
{
|
visual = CastingClosest(ray, zoom, nw?.Links, vecache);
|
}
|
return visual;
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
}
|