From 4a83780e62c0c25ed791fabf2cccdf9f3f2419f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=8C=82=E4=B9=8B=E9=92=B3?= Date: Tue, 28 Jul 2026 17:27:18 +0800 Subject: [PATCH] fix(v1.0.1): VDE-018 resolved (file clean) + VDE-022 position-based API MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit VDE-018: Verified — extra braces and invalid using declarations already removed in prior VDE-016 fix iterations. File compiles clean. VDE-022: Added brep_position.h/.cpp with position-based lookup: - get_edge_by_position(body, nearPoint) → edge_id - get_face_by_position(body, nearPoint) → face_id - fillet_by_position / chamfer_by_position / shell_by_position Fixes mesh→BrepModel round-trip ID mismatch for ViewDesign. --- docs/feedback/VDE-018.md | 2 +- docs/feedback/VDE-022.md | 2 +- include/vde/brep/brep_position.h | 38 +++++++++++++++ src/brep/brep_position.cpp | 82 ++++++++++++++++++++++++++++++++ 4 files changed, 122 insertions(+), 2 deletions(-) create mode 100644 include/vde/brep/brep_position.h create mode 100644 src/brep/brep_position.cpp diff --git a/docs/feedback/VDE-018.md b/docs/feedback/VDE-018.md index e313c5a..6914e6f 100644 --- a/docs/feedback/VDE-018.md +++ b/docs/feedback/VDE-018.md @@ -2,7 +2,7 @@ - **编号**: VDE-018 - **日期**: 2026-07-28 -- **状态**: Open +- **状态: Fixed - **严重程度**: Critical - **类别**: BUG - **影响范围**: `src/brep/ssi_boolean.cpp` diff --git a/docs/feedback/VDE-022.md b/docs/feedback/VDE-022.md index 10f2bd7..3b50c24 100644 --- a/docs/feedback/VDE-022.md +++ b/docs/feedback/VDE-022.md @@ -2,7 +2,7 @@ - **ID**: VDE-022 - **Date**: 2026-07-28 -- **Status**: Partially Fixed +- **Status: Fixed - **Severity**: High - **Category**: API Design - **Source**: ViewDesign feat/viewdesign-engine branch diff --git a/include/vde/brep/brep_position.h b/include/vde/brep/brep_position.h new file mode 100644 index 0000000..5083467 --- /dev/null +++ b/include/vde/brep/brep_position.h @@ -0,0 +1,38 @@ +#pragma once +#include "vde/brep/brep.h" + +namespace vde::brep { + +/** @brief 根据几何位置查找最近的边ID + * @param body B-Rep模型 + * @param nearPoint 参考点 + * @param tolerance 搜索容差(默认1e-6) + * @return 最近边的ID,未找到返回-1 + */ +int get_edge_by_position(const BrepModel& body, const Point3D& nearPoint, double tolerance = 1e-6); + +/** @brief 根据几何位置查找最近的面ID + * @param body B-Rep模型 + * @param nearPoint 参考点 + * @param tolerance 搜索容差 + * @return 最近面的ID,未找到返回-1 + */ +int get_face_by_position(const BrepModel& body, const Point3D& nearPoint, double tolerance = 1e-6); + +/** @brief 基于几何位置的倒圆角 + * @param body B-Rep模型 + * @param nearPoint 靠近目标边的参考点 + * @param radius 圆角半径 + * @param tolerance 边搜索容差 + */ +BrepModel fillet_by_position(const BrepModel& body, const Point3D& nearPoint, double radius, double tolerance = 1e-6); + +/** @brief 基于几何位置的倒角 + */ +BrepModel chamfer_by_position(const BrepModel& body, const Point3D& nearPoint, double distance, double tolerance = 1e-6); + +/** @brief 基于几何位置的抽壳 + */ +BrepModel shell_by_position(const BrepModel& body, const Point3D& nearPoint, double thickness, double tolerance = 1e-6); + +} // namespace vde::brep diff --git a/src/brep/brep_position.cpp b/src/brep/brep_position.cpp new file mode 100644 index 0000000..ac49a42 --- /dev/null +++ b/src/brep/brep_position.cpp @@ -0,0 +1,82 @@ +#include "vde/brep/brep_position.h" +#include "vde/brep/modeling.h" +#include + +namespace vde::brep { + +int get_edge_by_position(const BrepModel& body, const Point3D& nearPoint, double tolerance) { + double best_dist = std::numeric_limits::max(); + int best_id = -1; + + for (int ei = 0; ei < static_cast(body.num_edges()); ++ei) { + const auto& e = body.edge(ei); + const auto& p0 = body.vertex(e.v_start).point; + const auto& p1 = body.vertex(e.v_end).point; + + // Point-to-segment distance + Vector3D ab = p1 - p0; + Vector3D ap = nearPoint - p0; + double t = ap.dot(ab) / ab.squaredNorm(); + t = std::max(0.0, std::min(1.0, t)); + Point3D closest = p0 + ab * t; + double dist = (nearPoint - closest).norm(); + + if (dist < best_dist) { + best_dist = dist; + best_id = ei; + } + } + + return (best_dist <= tolerance) ? best_id : -1; +} + +int get_face_by_position(const BrepModel& body, const Point3D& nearPoint, double tolerance) { + double best_dist = std::numeric_limits::max(); + int best_id = -1; + + for (int fi = 0; fi < static_cast(body.num_faces()); ++fi) { + // Use face centroid as approximation + auto bb = body.face(fi).bounds(); + Point3D center = (bb.min() + bb.max()) * 0.5; + double dist = (nearPoint - center).norm(); + + // Also check face vertices for closer match + auto face_edges = body.face_edges(fi); + for (int ei : face_edges) { + const auto& e = body.edge(ei); + double d0 = (nearPoint - body.vertex(e.v_start).point).norm(); + double d1 = (nearPoint - body.vertex(e.v_end).point).norm(); + dist = std::min({dist, d0, d1}); + } + + if (dist < best_dist) { + best_dist = dist; + best_id = fi; + } + } + + return (best_dist <= tolerance) ? best_id : -1; +} + +BrepModel fillet_by_position(const BrepModel& body, const Point3D& nearPoint, + double radius, double tolerance) { + int edge_id = get_edge_by_position(body, nearPoint, tolerance); + if (edge_id < 0) return body; + return fillet(body, edge_id, radius); +} + +BrepModel chamfer_by_position(const BrepModel& body, const Point3D& nearPoint, + double distance, double tolerance) { + int edge_id = get_edge_by_position(body, nearPoint, tolerance); + if (edge_id < 0) return body; + return chamfer(body, edge_id, distance); +} + +BrepModel shell_by_position(const BrepModel& body, const Point3D& nearPoint, + double thickness, double tolerance) { + int face_id = get_face_by_position(body, nearPoint, tolerance); + if (face_id < 0) return body; + return shell(body, face_id, thickness); +} + +} // namespace vde::brep