#pragma once /** * @file constraint_solver.h * @brief 3D constraint solver for assembly * * Iterative relaxation solver for spatial constraints between assembly nodes. * Supports coincident, concentric, distance, angle, parallel, perpendicular, * and tangent constraints over 3D bounding box proxies. * * @ingroup brep */ #include "vde/brep/assembly.h" #include "vde/core/point.h" #include #include namespace vde::brep { /// Constraint type for 3D assembly solving enum class Constraint3D { Coincident, ///< Face-face alignment (coplanar, opposite normals) Concentric, ///< Axis-axis alignment Distance, ///< Fixed distance between faces Angle, ///< Fixed angle between faces Parallel, ///< Face normals parallel Perpendicular, ///< Face normals perpendicular Tangent ///< Face tangent contact }; /// A single constraint between two assembly nodes struct ConstraintEntry { int node_a; ///< Index into a flattened node list (or 0-based child index) int node_b; ///< Index of the node that moves to satisfy constraint Constraint3D type; double value = 0.0; ///< Distance or angle value (radians for Angle) }; /// Solve a system of 3D constraints on an assembly using iterative relaxation. /// /// Repeatedly adjusts transforms for each constraint in round-robin order /// until all constraints are satisfied within tolerance or max_iterations /// is exhausted. /// /// @param assembly Target assembly (root children are the constrained nodes) /// @param constraints Ordered list of constraints to satisfy /// @param max_iterations Maximum number of relaxation passes (default 100) /// @param tolerance Convergence tolerance (default 1e-6) /// @return true if all constraints satisfied within tolerance [[nodiscard]] bool solve_constraints( Assembly& assembly, const std::vector& constraints, int max_iterations = 100, double tolerance = 1e-6); /// Apply a single coincident (mate) constraint: align the closest opposing /// faces of node_a and node_b so they are coplanar. /// /// @return The correction transform that was applied to node_b [[nodiscard]] core::Transform3D apply_coincident( const AssemblyNode& node_a, AssemblyNode& node_b); /// Apply a single concentric constraint: align the bounding-box-estimated /// cylinder axes of node_a and node_b. /// /// @return The correction transform that was applied to node_b [[nodiscard]] core::Transform3D apply_concentric( const AssemblyNode& node_a, AssemblyNode& node_b); /// Apply a distance constraint: set the closest-approach gap between /// the bounding boxes of node_a and node_b to @p distance. /// /// @return The correction transform that was applied to node_b [[nodiscard]] core::Transform3D apply_distance( const AssemblyNode& node_a, AssemblyNode& node_b, double distance); } // namespace vde::brep