乐于分享
好东西不私藏

WPS JSA练习-三角网法土方计算 2026-07-20

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 === 0return 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 = [	  [00],	  [50],	  [63],	  [36],	  [05],	  [-12]	];// 内部点const interiorPoints = [	  [22],	  [33],	  [42],	  [2.54]	];// 合并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}