Files
STPViewer/tools/SmokeTest/ClipTest.cs
T
etwenandClaude Opus 4.8 0e19dbae1b feat: Initial release v0.1.0
STP/STEP 3D viewer (WPF, .NET 8) - CADability + HelixToolkit.Wpf:

- Multi-file import (STEP/STL/DXF) with STEP assembly tree
  (per-node visibility/color cascade, zoom-to)
- Measurements: point / distance / edge / face / circle / angle /
  face-to-face distance (B-rep exact where available)
- Assembly verification: two-point align (translate), 3-point align
  (rotate+translate via RigidAlign), axis rotate 90, interference
  check (tri-tri intersection + min gap)
- Section view (CPU mesh clipping, originals preserved)
- mm/inch toggle, CSV export (UTF-8 BOM), 2x PNG screenshot
- Performance: per-file merged edge lines, per-leaf merged mesh in
  browse mode, no BackMaterial on closed solids, edge suspend during
  camera interaction, parallel leaf triangulation with retry
- SmokeTest CLI: import pipeline, --tree, --clip-test,
  --interference-test, --align-test (all passing)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-13 00:16:10 +08:00

72 lines
2.8 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// 剖面裁切數學驗證:對單位幾何裁切,檢查保留側與面積守恆
using System.Windows.Media;
using System.Windows.Media.Media3D;
using STPViewer.Services;
namespace SmokeTest;
internal static class ClipTest
{
public static int Run()
{
int failures = 0;
// 單一三角形 (0,0,0)(10,0,0)(0,10,0),面積 50
var mesh = new MeshGeometry3D
{
Positions = new Point3DCollection
{
new(0, 0, 0), new(10, 0, 0), new(0, 10, 0),
},
TriangleIndices = new Int32Collection { 0, 1, 2 },
};
mesh.Freeze();
// case 1: 平面 x=20,全保留
var m1 = SectionService.ClipMesh(mesh, new Point3D(20, 0, 0), new Vector3D(1, 0, 0));
failures += Check("全保留", Area(m1), 50.0);
// case 2: 平面 x=-1,全裁掉
var m2 = SectionService.ClipMesh(mesh, new Point3D(-1, 0, 0), new Vector3D(1, 0, 0));
failures += Check("全裁掉", Area(m2), 0.0);
// case 3: 平面 x=5 → 保留 x≤5:梯形面積 = 50 - 右側小三角形(底5高5)/2 = 50 - 12.5 = 37.5
var m3 = SectionService.ClipMesh(mesh, new Point3D(5, 0, 0), new Vector3D(1, 0, 0));
failures += Check("半裁(x≤5)", Area(m3), 37.5);
foreach (Point3D p in m3.Positions)
if (p.X > 5 + 1e-9) { Console.WriteLine($" FAIL: 頂點 x={p.X} 超出保留側"); failures++; }
// case 4: 反向(保留 x≥5)→ 12.5
var m4 = SectionService.ClipMesh(mesh, new Point3D(5, 0, 0), new Vector3D(-1, 0, 0));
failures += Check("半裁(x≥5)", Area(m4), 12.5);
// case 5: 線段裁切
var segs = new Point3DCollection { new(0, 0, 0), new(10, 0, 0) };
Point3DCollection s1 = SectionService.ClipSegments(segs, new Point3D(4, 0, 0), new Vector3D(1, 0, 0));
double segLen = s1.Count == 2 ? (s1[1] - s1[0]).Length : -1;
failures += Check("線段裁切長度", segLen, 4.0);
Console.WriteLine(failures == 0 ? "ClipTest: 全部通過" : $"ClipTest: {failures} 項失敗");
return failures;
}
private static int Check(string name, double actual, double expected)
{
bool ok = Math.Abs(actual - expected) < 1e-9;
Console.WriteLine($" {(ok ? "PASS" : "FAIL")}: {name} = {actual}(期望 {expected}");
return ok ? 0 : 1;
}
private static double Area(MeshGeometry3D m)
{
double a = 0;
for (int i = 0; i + 2 < m.TriangleIndices.Count; i += 3)
{
Vector3D u = m.Positions[m.TriangleIndices[i + 1]] - m.Positions[m.TriangleIndices[i]];
Vector3D v = m.Positions[m.TriangleIndices[i + 2]] - m.Positions[m.TriangleIndices[i]];
a += Vector3D.CrossProduct(u, v).Length / 2;
}
return a;
}
}