#pragma once /** * @file brep_face_split.h * @brief B-Rep face splitting by plane * * Splits faces that partially intersect a cutting plane, producing * cleanly separated face fragments. Used to improve boolean operation * quality by replacing coarse centroid-based IN/OUT classification * with precise geometric splitting. * * @ingroup brep */ #include "vde/brep/brep.h" #include "vde/core/point.h" #include namespace vde::brep { /** * @brief Split a face by a plane * * Cuts a single B-Rep face with an infinite plane, producing up to * two face fragments (one on each side of the plane). Each fragment * is a valid BrepModel with proper loop topology. * * **Algorithm:** * 1. Get the face's ordered vertices by traversing the outer loop * 2. Classify each vertex as positive (distance ≥ 0) or negative (distance < 0) * 3. If all vertices are on the same side: return the face as a single fragment * 4. Otherwise: build two new faces: * - Face A: vertices on the positive side + intersection points * - Face B: vertices on the negative side + intersection points * * @param body Source B-Rep body containing the face * @param face_id Index of the face to split * @param plane_point A point on the cutting plane * @param plane_normal Normal vector of the cutting plane (need not be unit-length) * @return Vector of 0, 1, or 2 face fragment BrepModels * * @code{.cpp} * auto box = make_box(2, 2, 2); * // Split face 0 of the box with the YZ plane (x=0) * auto frags = split_face_by_plane(box, 0, Point3D(0,0,0), Vector3D(1,0,0)); * // frags.size() == 2: left half and right half * for (auto& f : frags) { * // Each fragment has its own vertices, edges, loop, and surface * assert(f.is_valid()); * } * @endcode */ [[nodiscard]] std::vector split_face_by_plane( const BrepModel& body, int face_id, const core::Point3D& plane_point, const core::Vector3D& plane_normal); } // namespace vde::brep