- 积分
- 23803
- 明经币
- 个
- 注册时间
- 2009-5-29
- 在线时间
- 小时
- 威望
-
- 金钱
- 个
- 贡献
-
- 激情
-
|
发表于 2025-2-24 10:48:39
|
显示全部楼层
本帖最后由 czb203 于 2025-2-24 10:50 编辑
 - using System;
- using System.Collections.Generic;
- using System.Linq;
- public struct Point
- {
- public double X { get; }
- public double Y { get; }
- public double Z { get; }
- public Point(double x, double y, double z)
- {
- X = x;
- Y = y;
- Z = z;
- }
- }
- public class Triangle
- {
- public Point P1 { get; }
- public Point P2 { get; }
- public Point P3 { get; }
- public double MinX { get; }
- public double MaxX { get; }
- public double MinY { get; }
- public double MaxY { get; }
- public Triangle(Point p1, Point p2, Point p3)
- {
- P1 = p1;
- P2 = p2;
- P3 = p3;
- MinX = Math.Min(p1.X, Math.Min(p2.X, p3.X));
- MaxX = Math.Max(p1.X, Math.Max(p2.X, p3.X));
- MinY = Math.Min(p1.Y, Math.Min(p2.Y, p3.Y));
- MaxY = Math.Max(p1.Y, Math.Max(p2.Y, p3.Y));
- }
- }
- public class QuadTree
- {
- private const int MaxCapacity = 4;
- private readonly List<Triangle> triangles = new List<Triangle>();
- private QuadTree[] children;
- private readonly double xMin, yMin, xMax, yMax;
- public QuadTree(double xMin, double yMin, double xMax, double yMax)
- {
- this.xMin = xMin;
- this.yMin = yMin;
- this.xMax = xMax;
- this.yMax = yMax;
- }
- public void Insert(Triangle triangle)
- {
- if (children != null)
- {
- foreach (var child in children)
- {
- if (ChildIntersectsTriangle(child, triangle))
- {
- child.Insert(triangle);
- }
- }
- return;
- }
- triangles.Add(triangle);
- if (triangles.Count > MaxCapacity)
- {
- Split();
- foreach (var t in triangles)
- {
- foreach (var child in children)
- {
- if (ChildIntersectsTriangle(child, t))
- {
- child.Insert(t);
- }
- }
- }
- triangles.Clear();
- }
- }
- private bool ChildIntersectsTriangle(QuadTree child, Triangle triangle)
- {
- return !(triangle.MinX > child.xMax ||
- triangle.MaxX < child.xMin ||
- triangle.MinY > child.yMax ||
- triangle.MaxY < child.yMin);
- }
- private void Split()
- {
- double xMid = (xMin + xMax) / 2;
- double yMid = (yMin + yMax) / 2;
- children = new QuadTree[4];
- children[0] = new QuadTree(xMin, yMin, xMid, yMid);
- children[1] = new QuadTree(xMid, yMin, xMax, yMid);
- children[2] = new QuadTree(xMin, yMid, xMid, yMax);
- children[3] = new QuadTree(xMid, yMid, xMax, yMax);
- }
- public List<Triangle> Query(double x, double y)
- {
- var result = new List<Triangle>();
- if (x < xMin || x > xMax || y < yMin || y > yMax)
- return result;
- if (children != null)
- {
- foreach (var child in children)
- {
- result.AddRange(child.Query(x, y));
- }
- }
- else
- {
- result.AddRange(triangles);
- }
- return result;
- }
- }
- public static class TriangleHelper
- {
- public static bool IsPointInTriangle(Point p, Triangle triangle, double epsilon = 1e-6)
- {
- double denominator = ((triangle.P2.Y - triangle.P3.Y) * (triangle.P1.X - triangle.P3.X)) +
- ((triangle.P3.X - triangle.P2.X) * (triangle.P1.Y - triangle.P3.Y));
- if (Math.Abs(denominator) < epsilon)
- return false;
- double a = ((triangle.P2.Y - triangle.P3.Y) * (p.X - triangle.P3.X) +
- (triangle.P3.X - triangle.P2.X) * (p.Y - triangle.P3.Y)) / denominator;
- double b = ((triangle.P3.Y - triangle.P1.Y) * (p.X - triangle.P3.X) +
- (triangle.P1.X - triangle.P3.X) * (p.Y - triangle.P3.Y)) / denominator;
- double c = 1 - a - b;
- return a >= -epsilon && a <= 1 + epsilon &&
- b >= -epsilon && b <= 1 + epsilon &&
- c >= -epsilon && c <= 1 + epsilon &&
- Math.Abs(a + b + c - 1) < 3 * epsilon;
- }
- public static double InterpolateZ(Point p, Triangle triangle)
- {
- double denominator = ((triangle.P2.Y - triangle.P3.Y) * (triangle.P1.X - triangle.P3.X)) +
- ((triangle.P3.X - triangle.P2.X) * (triangle.P1.Y - triangle.P3.Y));
- double a = ((triangle.P2.Y - triangle.P3.Y) * (p.X - triangle.P3.X) +
- (triangle.P3.X - triangle.P2.X) * (p.Y - triangle.P3.Y)) / denominator;
- double b = ((triangle.P3.Y - triangle.P1.Y) * (p.X - triangle.P3.X) +
- (triangle.P1.X - triangle.P3.X) * (p.Y - triangle.P3.Y)) / denominator;
- double c = 1 - a - b;
- return a * triangle.P1.Z + b * triangle.P2.Z + c * triangle.P3.Z;
- }
- }
- public class TerrainInterpolator
- {
- private readonly QuadTree quadTree;
- public TerrainInterpolator(IEnumerable<Triangle> triangles)
- {
- var triangleList = triangles.ToList();
- double xMin = triangleList.Min(t => t.MinX);
- double xMax = triangleList.Max(t => t.MaxX);
- double yMin = triangleList.Min(t => t.MinY);
- double yMax = triangleList.Max(t => t.MaxY);
- quadTree = new QuadTree(xMin, yMin, xMax, yMax);
- foreach (var triangle in triangleList)
- {
- quadTree.Insert(triangle);
- }
- }
- public double? Interpolate(Point p)
- {
- var candidates = quadTree.Query(p.X, p.Y);
- foreach (var triangle in candidates)
- {
- if (TriangleHelper.IsPointInTriangle(p, triangle))
- {
- return TriangleHelper.InterpolateZ(p, triangle);
- }
- }
- return null;
- }
- }
- // 使用示例
- class Program
- {
- static void Main()
- {
- // 创建测试三角形
- var triangles = new List<Triangle>
- {
- new Triangle(
- new Point(0, 0, 100),
- new Point(10, 0, 200),
- new Point(5, 10, 300)
- )
- // 添加更多三角形...
- };
- var interpolator = new TerrainInterpolator(triangles);
-
- Point testPoint = new Point(5, 5, 0);
- double? elevation = interpolator.Interpolate(testPoint);
- if (elevation.HasValue)
- {
- Console.WriteLine($"插值高程值: {elevation.Value}");
- }
- else
- {
- Console.WriteLine("点不在任何三角形内");
- }
- }
- }
|
|