WPS JSA练习-三角网法土方计算 2026-07-20
//第三方库为d3-delaunay//cdn 链接:https://cdn.jsdelivr.net/npm/d3-delaunay@6.0.4/dist/d3-delaunay.min.js//判断三角形是否在多边形边界内function pointInPolygonInclusive(p, poly) {const x = p[0], y = p[1];let inside = false;// 1️⃣ 先判断是否在边上(含顶点)for (let i = 0, j = poly.length - 1; i < poly.length; j = i++) {const xi = poly[i][0], yi = poly[i][1];const xj = poly[j][0], yj = poly[j][1];// 向量叉积(判断共线)const cross = (x - xi) * (yj - yi) - (y - yi) * (xj - xi);// 向量点积(判断投影是否在线段内)const dot = (x - xi) * (xj - xi) + (y - yi) * (yj - yi);const len2 = (xj - xi) ** 2 + (yj - yi) ** 2;// 共线 + 投影在线段范围内 → 在边上if (Math.abs(cross) < 1e-12 && dot >= 0 && dot <= len2) {return true;}}// 2️⃣ 射线法判断内部for (let i = 0, j = poly.length - 1; i < poly.length; j = i++) {const xi = poly[i][0], yi = poly[i][1];const xj = poly[j][0], yj = poly[j][1];const intersect =yi > y !== yj > y &&x < ((xj - xi) * (y - yi)) / (yj - yi) + xi;if (intersect) inside = !inside;}return inside;}//检测高程点是否在三角形内function isPointInTriangleWithAABB(px, py,ax, ay,bx, by,cx, cy,eps = 1e-9) {// ===== AABB 包围盒检测 =====const minX = Math.min(ax, bx, cx);const maxX = Math.max(ax, bx, cx);const minY = Math.min(ay, by, cy);const maxY = Math.max(ay, by, cy);if (px < minX - eps || px > maxX + eps ||py < minY - eps || py > maxY + eps) {return false;}// ===== 重心坐标检测 =====const v0x = cx - ax;const v0y = cy - ay;const v1x = bx - ax;const v1y = by - ay;const v2x = px - ax;const v2y = py - ay;const dot00 = v0x * v0x + v0y * v0y;const dot01 = v0x * v1x + v0y * v1y;const dot02 = v0x * v2x + v0y * v2y;const dot11 = v1x * v1x + v1y * v1y;const dot12 = v1x * v2x + v1y * v2y;const denom = dot00 * dot11 - dot01 * dot01;if (denom === 0) return false; // 退化三角形const u = (dot11 * dot02 - dot01 * dot12) / denom;const v = (dot00 * dot12 - dot01 * dot02) / denom;return u >= -eps && v >= -eps && (u + v) <= 1 + eps;}function demo(){// 多边形边界(按顺序)const boundary = [[0, 0],[5, 0],[6, 3],[3, 6],[0, 5],[-1, 2]];// 内部点const interiorPoints = [[2, 2],[3, 3],[4, 2],[2.5, 4]];// 合并const points = [...boundary, ...interiorPoints];// 构建 Delaunayconst delaunay =d3.Delaunay.from(points);// 过滤三角形:三个顶点都在多边形内const triangles = [];for (let i = 0; i < delaunay.triangles.length; i += 3) {const a = delaunay.triangles[i];const b = delaunay.triangles[i + 1];const c = delaunay.triangles[i + 2];const pa = points[a];const pb = points[b];const pc = points[c];if (pointInPolygonInclusive(pa, boundary) &&pointInPolygonInclusive(pb, boundary) &&pointInPolygonInclusive(pc, boundary)) {triangles.push([pa, pb, pc]);}}// Range("A1")// console.log("合法三角网:", triangles);results = []for(let i=0;i<triangles.length;i++){results.push([...triangles[i][0]])results.push([...triangles[i][1]])results.push([...triangles[i][2]])}Range("A1").Resize(results.length,results[0].length).Value2 = resultsRange("D1").Resize(boundary.length,boundary[0].length).Value2 = boundary}
夜雨聆风