77 lines
2.9 KiB
C++
77 lines
2.9 KiB
C++
#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 <vector>
|
|
#include <functional>
|
|
|
|
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<ConstraintEntry>& 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
|