KiCad PCB EDA Suite
Loading...
Searching...
No Matches
board_constraint_adapter.cpp File Reference
#include <constraints/board_constraint_adapter.h>
#include <algorithm>
#include <iterator>
#include <ranges>
#include <cmath>
#include <cstdint>
#include <cstring>
#include <functional>
#include <limits>
#include <set>
#include <unordered_map>
#include <unordered_set>
#include <wx/debug.h>
#include <board.h>
#include <footprint.h>
#include <geometry/seg.h>
#include <math/util.h>
#include <pcb_dimension.h>
#include <pcb_shape.h>
#include <constraints/constraint_builder.h>
#include <GCS.h>

Go to the source code of this file.

Functions

static std::vector< PCB_CONSTRAINT * > collectAllConstraints (BOARD *aBoard)
 
bool BoardHasConstraints (BOARD *aBoard)
 True if the board or any of its footprints carries at least one geometric constraint.
 
bool ConstraintItemIsLocked (const BOARD_ITEM *aItem)
 True when the solver must treat aItem as immovable, either locked itself or living inside a locked footprint.
 
static std::unordered_map< KIID, std::vector< PCB_CONSTRAINT * > > buildShapeConstraintMap (BOARD *aBoard, const std::vector< PCB_CONSTRAINT * > &aConstraints, std::vector< KIID > *aErrored=nullptr)
 
static void collectConstraintCluster (const std::unordered_map< KIID, std::vector< PCB_CONSTRAINT * > > &aMap, const KIID &aSeed, std::unordered_set< KIID > &aClusterShapes, std::vector< PCB_CONSTRAINT * > &aClusterConstraints, std::set< KIID > *aVisited=nullptr)
 
template<typename T>
static std::vector< T * > resolveClusterItems (BOARD *aBoard, const std::unordered_set< KIID > &aIds)
 
static std::vector< PCB_SHAPE * > resolveClusterShapes (BOARD *aBoard, const std::unordered_set< KIID > &aIds)
 
static std::vector< PCB_DIMENSION_BASE * > resolveClusterDimensions (BOARD *aBoard, const std::unordered_set< KIID > &aIds)
 
static bool isDegenerateLine (const GCS::Line &aLine)
 
static double directedAngleForCorner (const GCS::Line &aL1, const GCS::Line &aL2, double aCornerDeg)
 
static double arcSweepTarget (double aStartAngle, double aEndAngle, double aSweepDeg)
 
CONSTRAINT_DIAGNOSIS SolveCluster (BOARD *aBoard, const CONSTRAINT_MEMBER &aDragged, const VECTOR2I &aCursor, std::vector< PCB_SHAPE * > *aModified, const std::function< void(BOARD_ITEM *)> &aBeforeModify, bool aIncludeDragged, bool aStabilize, const std::set< KIID > &aEdited, const std::optional< std::pair< CONSTRAINT_MEMBER, VECTOR2I > > &aCoDragged)
 Gather the cluster of shapes transitively constrained with the dragged shape, solve with the dragged anchor pinned to the cursor, and apply the result.
 
CONSTRAINT_DIAGNOSIS ApplyConstraintImmediately (BOARD *aBoard, const PCB_CONSTRAINT *aConstraint, std::vector< PCB_SHAPE * > *aModified, const std::function< void(BOARD_ITEM *)> &aBeforeModify)
 Solve a just-created constraint's cluster so the geometry snaps to satisfy it (SolidWorks-style), pinning the constraint's first member at its current position and letting the solver move the rest.
 
void ReSolveShapeClusters (BOARD *aBoard, const std::vector< PCB_SHAPE * > &aShapes, std::vector< PCB_SHAPE * > *aModified, const std::function< void(BOARD_ITEM *)> &aBeforeModify)
 Re-solve the clusters of shapes edited outside the solver, e.g.
 
void ReSolveShapeClustersHoldingEdited (BOARD *aBoard, const std::vector< PCB_SHAPE * > &aEditedShapes, std::vector< PCB_SHAPE * > *aModified, const std::function< void(BOARD_ITEM *)> &aBeforeModify)
 Re-solve clusters whose new geometry is authoritative holding every edited shape fully fixed so only constrained neighbors move a failed solve leaves that cluster untouched.
 
void ReSolveAfterShapeResize (BOARD *aBoard, PCB_SHAPE *aShape, std::vector< PCB_SHAPE * > *aModified, const std::function< void(BOARD_ITEM *)> &aBeforeModify)
 Re-solve after a resize, e.g. a circle radius edit. Holds aShape fixed so its neighbors adjust.
 
static CLUSTER_DIAGNOSIS diagnoseSingleCluster (BOARD *aBoard, const std::unordered_set< KIID > &aClusterShapes, const std::vector< PCB_CONSTRAINT * > &aClusterConstraints)
 
static void assembleClusterInto (BOARD_CONSTRAINT_DIAGNOSTICS &aResult, const CLUSTER_DIAGNOSIS &aCluster)
 
static void dedupErrored (BOARD_CONSTRAINT_DIAGNOSTICS &aResult)
 
BOARD_CONSTRAINT_DIAGNOSTICS DiagnoseBoardConstraints (BOARD *aBoard)
 Diagnose every constraint cluster on the board (validate only – geometry is not changed) and return the per-shape state plus the conflicting/redundant constraints and total free DOF, for the diagnostics overlay and info bar.
 
static void hashCombine (std::size_t &aSeed, std::size_t aValue)
 
static void hashInt (std::size_t &aSeed, long long aValue)
 
static void hashDouble (std::size_t &aSeed, double aValue)
 
static void hashPoint (std::size_t &aSeed, const VECTOR2I &aPoint)
 
static void hashKiid (std::size_t &aSeed, const KIID &aId)
 
static void hashShape (std::size_t &aSeed, const PCB_SHAPE *aShape)
 
static void hashDimension (std::size_t &aSeed, const PCB_DIMENSION_BASE *aDimension)
 
static void hashConstraint (std::size_t &aSeed, const PCB_CONSTRAINT *aConstraint)
 
static std::size_t hashCluster (BOARD *aBoard, const std::unordered_set< KIID > &aClusterShapes, const std::vector< PCB_CONSTRAINT * > &aClusterConstraints)
 

Variables

static constexpr double IU_PER_NORM_UNIT = 1e6
 
static constexpr int MAX_SOLVE_ITERATIONS = 100
 
static constexpr double STAY_PUT_WEIGHT = 1e-4
 

Function Documentation

◆ ApplyConstraintImmediately()

CONSTRAINT_DIAGNOSIS ApplyConstraintImmediately ( BOARD * aBoard,
const PCB_CONSTRAINT * aConstraint,
std::vector< PCB_SHAPE * > * aModified = nullptr,
const std::function< void(BOARD_ITEM *)> & aBeforeModify = {} )

Solve a just-created constraint's cluster so the geometry snaps to satisfy it (SolidWorks-style), pinning the constraint's first member at its current position and letting the solver move the rest.

aConstraint must already be on the board. A failed solve leaves geometry untouched.

Parameters
aModified[out] the shapes the solve moved, for the caller to stage in a commit.
aBeforeModifyif set, invoked with each moved shape and each reference constraint whose value changed, just before it changes, so the caller can stage it in the commit.

Definition at line 2329 of file board_constraint_adapter.cpp.

References ConstraintAnchorPosition(), ConstraintShapeAnchors(), PCB_CONSTRAINT::GetMembers(), pin, BOARD::ResolveItem(), SolveCluster(), and WHOLE.

Referenced by BOOST_AUTO_TEST_CASE(), BOOST_AUTO_TEST_CASE(), BOOST_AUTO_TEST_CASE(), BOOST_AUTO_TEST_CASE(), BOOST_AUTO_TEST_CASE(), BOOST_AUTO_TEST_CASE(), BOOST_AUTO_TEST_CASE(), BOOST_AUTO_TEST_CASE(), BOOST_AUTO_TEST_CASE(), BOOST_AUTO_TEST_CASE(), BOOST_AUTO_TEST_CASE(), BOOST_AUTO_TEST_CASE(), BOOST_AUTO_TEST_CASE(), BOOST_AUTO_TEST_CASE(), BOOST_AUTO_TEST_CASE(), BOOST_AUTO_TEST_CASE(), BOOST_AUTO_TEST_CASE(), BOOST_AUTO_TEST_CASE(), EditConstraintValue(), DIALOG_DIMENSION_PROPERTIES::resolveDrivingConstraint(), CONSTRAINT_EDIT_TOOL::solveAddedConstraint(), and PCB_PROPERTIES_PANEL::valueChanged().

◆ arcSweepTarget()

static double arcSweepTarget ( double aStartAngle,
double aEndAngle,
double aSweepDeg )
static

Definition at line 278 of file board_constraint_adapter.cpp.

References std::abs(), and M_PI.

Referenced by BOARD_CONSTRAINT_ADAPTER::Build().

◆ assembleClusterInto()

◆ BoardHasConstraints()

bool BoardHasConstraints ( BOARD * aBoard)

True if the board or any of its footprints carries at least one geometric constraint.

Cheap, short-circuiting guard so an unconstrained board pays nothing on every edit.

Definition at line 74 of file board_constraint_adapter.cpp.

References BOARD::Constraints(), and BOARD::Footprints().

Referenced by CONSTRAINT_EDIT_TOOL::DiagnoseAfterMove(), EDIT_TOOL::doMoveSelection(), EDIT_TOOL::Move(), CONSTRAINT_EDIT_TOOL::onHoverMotion(), CONSTRAINT_EDIT_TOOL::SolveAfterEdit(), and CONSTRAINT_EDIT_TOOL::SolveAfterMove().

◆ buildShapeConstraintMap()

static std::unordered_map< KIID, std::vector< PCB_CONSTRAINT * > > buildShapeConstraintMap ( BOARD * aBoard,
const std::vector< PCB_CONSTRAINT * > & aConstraints,
std::vector< KIID > * aErrored = nullptr )
static

◆ collectAllConstraints()

◆ collectConstraintCluster()

static void collectConstraintCluster ( const std::unordered_map< KIID, std::vector< PCB_CONSTRAINT * > > & aMap,
const KIID & aSeed,
std::unordered_set< KIID > & aClusterShapes,
std::vector< PCB_CONSTRAINT * > & aClusterConstraints,
std::set< KIID > * aVisited = nullptr )
static

◆ ConstraintItemIsLocked()

bool ConstraintItemIsLocked ( const BOARD_ITEM * aItem)

True when the solver must treat aItem as immovable, either locked itself or living inside a locked footprint.

BOARD_ITEM::IsLocked() alone misses the parent-footprint case because most edit tools filter footprint children out before their lock checks run, while the solver collects footprint graphics directly.

Definition at line 88 of file board_constraint_adapter.cpp.

References FPHOLDER, BOARD_ITEM::GetBoard(), BOARD::GetBoardUse(), BOARD_ITEM::GetParentFootprint(), BOARD_ITEM::IsLocked(), and FOOTPRINT::IsLocked().

Referenced by BOOST_AUTO_TEST_CASE(), BOOST_AUTO_TEST_CASE(), BOARD_CONSTRAINT_ADAPTER::Build(), hashShape(), BOARD_CONSTRAINT_ADAPTER::holdFreeArcRadii(), BOARD_CONSTRAINT_ADAPTER::holdFreeSegmentLengths(), BOARD_CONSTRAINT_ADAPTER::holdPolygonVertices(), and BOARD_CONSTRAINT_ADAPTER::pinUneditedShapes().

◆ dedupErrored()

static void dedupErrored ( BOARD_CONSTRAINT_DIAGNOSTICS & aResult)
static

◆ DiagnoseBoardConstraints()

◆ diagnoseSingleCluster()

◆ directedAngleForCorner()

static double directedAngleForCorner ( const GCS::Line & aL1,
const GCS::Line & aL2,
double aCornerDeg )
static

Definition at line 229 of file board_constraint_adapter.cpp.

References std::abs(), M_PI, and vA.

Referenced by BOARD_CONSTRAINT_ADAPTER::Build().

◆ hashCluster()

static std::size_t hashCluster ( BOARD * aBoard,
const std::unordered_set< KIID > & aClusterShapes,
const std::vector< PCB_CONSTRAINT * > & aClusterConstraints )
static

◆ hashCombine()

static void hashCombine ( std::size_t & aSeed,
std::size_t aValue )
static

◆ hashConstraint()

◆ hashDimension()

static void hashDimension ( std::size_t & aSeed,
const PCB_DIMENSION_BASE * aDimension )
static

◆ hashDouble()

static void hashDouble ( std::size_t & aSeed,
double aValue )
static

Definition at line 2638 of file board_constraint_adapter.cpp.

References hashCombine().

Referenced by hashConstraint(), and hashShape().

◆ hashInt()

static void hashInt ( std::size_t & aSeed,
long long aValue )
static

Definition at line 2632 of file board_constraint_adapter.cpp.

References hashCombine().

Referenced by hashConstraint(), hashDimension(), hashPoint(), and hashShape().

◆ hashKiid()

static void hashKiid ( std::size_t & aSeed,
const KIID & aId )
static

Definition at line 2657 of file board_constraint_adapter.cpp.

References hashCombine().

Referenced by hashConstraint().

◆ hashPoint()

static void hashPoint ( std::size_t & aSeed,
const VECTOR2I & aPoint )
static

Definition at line 2650 of file board_constraint_adapter.cpp.

References hashInt(), VECTOR2< T >::x, and VECTOR2< T >::y.

Referenced by hashDimension(), and hashShape().

◆ hashShape()

◆ isDegenerateLine()

static bool isDegenerateLine ( const GCS::Line & aLine)
static

Definition at line 223 of file board_constraint_adapter.cpp.

Referenced by BOARD_CONSTRAINT_ADAPTER::Build().

◆ ReSolveAfterShapeResize()

◆ resolveClusterDimensions()

static std::vector< PCB_DIMENSION_BASE * > resolveClusterDimensions ( BOARD * aBoard,
const std::unordered_set< KIID > & aIds )
static

◆ resolveClusterItems()

template<typename T>
static std::vector< T * > resolveClusterItems ( BOARD * aBoard,
const std::unordered_set< KIID > & aIds )
static

Definition at line 184 of file board_constraint_adapter.cpp.

References BOARD::ResolveItem(), and T.

Referenced by resolveClusterDimensions(), and resolveClusterShapes().

◆ resolveClusterShapes()

static std::vector< PCB_SHAPE * > resolveClusterShapes ( BOARD * aBoard,
const std::unordered_set< KIID > & aIds )
static

◆ ReSolveShapeClusters()

void ReSolveShapeClusters ( BOARD * aBoard,
const std::vector< PCB_SHAPE * > & aShapes,
std::vector< PCB_SHAPE * > * aModified = nullptr,
const std::function< void(BOARD_ITEM *)> & aBeforeModify = {} )

◆ ReSolveShapeClustersHoldingEdited()

void ReSolveShapeClustersHoldingEdited ( BOARD * aBoard,
const std::vector< PCB_SHAPE * > & aEditedShapes,
std::vector< PCB_SHAPE * > * aModified,
const std::function< void(BOARD_ITEM *)> & aBeforeModify )

◆ SolveCluster()

CONSTRAINT_DIAGNOSIS SolveCluster ( BOARD * aBoard,
const CONSTRAINT_MEMBER & aDragged,
const VECTOR2I & aCursor,
std::vector< PCB_SHAPE * > * aModified = nullptr,
const std::function< void(BOARD_ITEM *)> & aBeforeModify = {},
bool aIncludeDragged = false,
bool aStabilize = false,
const std::set< KIID > & aEdited = {},
const std::optional< std::pair< CONSTRAINT_MEMBER, VECTOR2I > > & aCoDragged = std::nullopt )

Gather the cluster of shapes transitively constrained with the dragged shape, solve with the dragged anchor pinned to the cursor, and apply the result.

Kept free-standing so the interactive drag hook stays thin and this logic is headless-testable.

Parameters
aBoardthe board (or footprint-holder board) owning the constraints.
aDraggedthe anchor being dragged.
aCursorthe cursor target, in IU.
aModified[out] the neighbor shapes whose geometry the solve changed (excludes the dragged shape itself), for the caller to stage in a commit.
aBeforeModifyif set, invoked with each item (neighbor shape or reference constraint whose measured value changed) immediately before it is modified, so the caller can BOARD_COMMIT::Modify it for a clean undo. The dragged shape is excluded unless aIncludeDragged, since the caller stages it itself.
aIncludeDraggedif true, the dragged shape is also reported in aModified and passed to aBeforeModify – for callers (e.g. solve-on-create) that pin where the shape already is and do not stage it themselves.
aEditedother shapes in this cluster edited alongside the dragged one left free instead of stay-pinned back
aCoDraggedsecond anchor moved by the same handle with its own target for a polygon edge drag pinned at the same weight as the primary
Returns
the diagnosis; .solved is false if the cluster could not be built or did not converge.

Definition at line 2267 of file board_constraint_adapter.cpp.

References BOARD_CONSTRAINT_ADAPTER::Apply(), BOARD_CONSTRAINT_ADAPTER::ApplyReferenceValues(), BOARD_CONSTRAINT_ADAPTER::Build(), buildShapeConstraintMap(), collectAllConstraints(), collectConstraintCluster(), BOARD_CONSTRAINT_ADAPTER::Diagnose(), CONSTRAINT_MEMBER::m_item, resolveClusterDimensions(), resolveClusterShapes(), BOARD::ResolveItem(), BOARD_CONSTRAINT_ADAPTER::Solve(), and CONSTRAINT_DIAGNOSIS::solved.

Referenced by ApplyConstraintImmediately(), BOOST_AUTO_TEST_CASE(), BOOST_AUTO_TEST_CASE(), BOOST_AUTO_TEST_CASE(), BOOST_AUTO_TEST_CASE(), BOOST_AUTO_TEST_CASE(), BOOST_AUTO_TEST_CASE(), BOOST_AUTO_TEST_CASE(), BOOST_AUTO_TEST_CASE(), BOOST_FIXTURE_TEST_CASE(), BOOST_FIXTURE_TEST_CASE(), BOOST_FIXTURE_TEST_CASE(), BOOST_FIXTURE_TEST_CASE(), BOOST_FIXTURE_TEST_CASE(), BOOST_FIXTURE_TEST_CASE(), BOOST_FIXTURE_TEST_CASE(), BOOST_FIXTURE_TEST_CASE(), BOOST_FIXTURE_TEST_CASE(), BOOST_FIXTURE_TEST_CASE(), BOOST_FIXTURE_TEST_CASE(), BOOST_FIXTURE_TEST_CASE(), ReSolveShapeClusters(), and PCB_POINT_EDITOR::updateItem().

Variable Documentation

◆ IU_PER_NORM_UNIT

double IU_PER_NORM_UNIT = 1e6
staticconstexpr

Definition at line 50 of file board_constraint_adapter.cpp.

Referenced by BOARD_CONSTRAINT_ADAPTER::Build().

◆ MAX_SOLVE_ITERATIONS

int MAX_SOLVE_ITERATIONS = 100
staticconstexpr

Definition at line 53 of file board_constraint_adapter.cpp.

Referenced by BOARD_CONSTRAINT_ADAPTER::Build().

◆ STAY_PUT_WEIGHT

double STAY_PUT_WEIGHT = 1e-4
staticconstexpr