26#include <unordered_set>
86bool allSegments(
const std::vector<BOARD_ITEM*>& aItems )
88 return std::ranges::all_of( aItems, isSegment );
93bool allRadial(
const std::vector<BOARD_ITEM*>& aItems )
95 return std::ranges::all_of( aItems, isCircleOrArc );
100bool allCentered(
const std::vector<BOARD_ITEM*>& aItems )
102 return std::ranges::all_of( aItems,
105 return isCircleOrArc( aItem ) || isEllipseKind( aItem );
118 SEG::ecoord best = ( aEnds[0] - bEnds[0] ).SquaredEuclideanNorm();
120 for(
int i = 0; i < 2; ++i )
122 for(
int j = 0; j < 2; ++j )
124 SEG::ecoord dist = ( aEnds[i] - bEnds[j] ).SquaredEuclideanNorm();
138 return SEG( aEnds[
vA], aEnds[1 -
vA] ).
Angle(
SEG( bEnds[vB], bEnds[1 - vB] ) );
144 const std::vector<BOARD_ITEM*>& aItems )
147 auto makeWhole = [&]()
149 std::unique_ptr<PCB_CONSTRAINT> c = std::make_unique<PCB_CONSTRAINT>( aParent, aType );
164 if( aItems.size() != 2 || !allSegments( aItems ) )
173 if( aItems.size() != 1 || !isSegment( aItems[0] ) )
181 if( aItems.size() != 1 || !isSegment( aItems[0] ) )
186 std::unique_ptr<PCB_CONSTRAINT> c = makeWhole();
187 c->SetValue( ( seg->
GetEnd() - seg->
GetStart() ).EuclideanNorm() );
193 if( aItems.size() != 2 || !allCentered( aItems ) )
201 if( aItems.size() != 2 || !allRadial( aItems ) )
209 if( aItems.size() != 2 || !allSegments( aItems ) )
220 std::unique_ptr<PCB_CONSTRAINT> c = makeWhole();
228 if( aItems.size() != 1 || !isCircleOrArc( aItems[0] ) )
231 std::unique_ptr<PCB_CONSTRAINT> c = makeWhole();
232 c->SetValue(
static_cast<const PCB_SHAPE*
>( aItems[0] )->GetRadius() );
238 if( aItems.size() != 1 || !isArc( aItems[0] ) )
241 std::unique_ptr<PCB_CONSTRAINT> c = makeWhole();
242 c->SetValue(
static_cast<const PCB_SHAPE*
>( aItems[0] )->GetArcAngle().AsDegrees() );
248 if( aItems.size() != 2 )
256 return isCircleOrArc( aItem ) || isEllipseKind( aItem );
259 bool lineCurve = ( isSegment( a ) && isCurve( b ) ) || ( isSegment( b ) && isCurve( a ) );
260 bool curveCurve = isCircleOrArc( a ) && isCircleOrArc( b );
262 if( !lineCurve && !curveCurve )
288 format =
_(
"%s needs two line segments. Click them to constrain." );
293 format =
_(
"%s needs two line segments of nonzero length. Click them to constrain." );
298 format =
_(
"%s needs one line segment, or two anchor points. Click them to constrain." );
302 format =
_(
"%s needs one line segment. Click it to constrain." );
307 format =
_(
"%s needs two arcs, circles or ellipses. Click them to constrain." );
311 format =
_(
"%s needs two arcs or circles. Click them to constrain." );
315 format =
_(
"%s needs one arc or circle. Click it to constrain." );
319 format =
_(
"%s needs one arc. Click it to constrain." );
324 format =
_(
"%s needs a line and a curve, or two arcs or circles. Click them to constrain." );
334 return wxEmptyString;
343 std::vector<CONSTRAINT_ANCHOR_POINT> anchors;
370 VECTOR2I tl( std::min( s.
x, e.
x ), std::min( s.
y, e.
y ) );
371 VECTOR2I br( std::max( s.
x, e.
x ), std::max( s.
y, e.
y ) );
387 for(
int i = 0; i < outline.
PointCount(); ++i )
388 anchors.push_back( { CONSTRAINT_ANCHOR::VERTEX, outline.CPoint( i ), i } );
417 if( !aShape || aIndex < 0 )
425 if( aIndex >= (
int) anchors.size() )
428 return anchors[aIndex];
433 const VECTOR2I& aPos,
double aMaxDist )
435 double best = aMaxDist;
436 std::optional<CONSTRAINT_MEMBER>
result;
442 double dist = ( a.pos - aPos ).EuclideanNorm();
458 std::vector<PCB_SHAPE*> shapes;
464 [&](
const auto& aContainer )
469 shape && aBoard->
IsLayerVisible( shape->GetLayer() ) && layerMatches( shape, aLayer ) )
471 shapes.push_back( shape );
479 collect( footprint->GraphicalItems() );
487 std::vector<BOARD_ITEM*> items;
493 [&](
const auto& aContainer )
498 && aBoard->
IsLayerVisible( item->GetLayer() ) && layerMatches( item, aLayer ) )
500 items.push_back( item );
508 collect( footprint->GraphicalItems() );
515 const std::vector<CONSTRAINT_MEMBER>& aExclude,
518 double best = aMaxDist;
519 std::optional<CONSTRAINT_MEMBER>
result;
531 double dist = ( a.pos - aPos ).EuclideanNorm();
546 const std::optional<VECTOR2I>& aEnd,
double aMaxDist,
549 std::vector<ENDPOINT_BINDING> bindings;
556 using ANCHOR_PAIR = std::pair<CONSTRAINT_MEMBER, CONSTRAINT_MEMBER>;
558 auto bestPairOn = [&](
BOARD_ITEM* aCandidate ) -> std::optional<std::pair<ANCHOR_PAIR, double>>
564 const size_t none = anchors.size();
565 size_t bestEnd = none;
566 size_t secondEnd = none;
567 std::vector<double> dEnd( anchors.size(), 0.0 );
569 for(
size_t j = 0; j < anchors.size(); ++j )
571 dEnd[j] = ( anchors[j].pos - *aEnd ).EuclideanNorm();
573 if( dEnd[j] > aMaxDist )
576 if( bestEnd == none || dEnd[j] < dEnd[bestEnd] )
581 else if( secondEnd == none || dEnd[j] < dEnd[secondEnd] )
587 if( bestEnd == none )
590 std::optional<std::pair<ANCHOR_PAIR, double>> best;
592 for(
size_t i = 0; i < anchors.size(); ++i )
594 double dStart = ( anchors[i].pos - aStart ).EuclideanNorm();
596 if( dStart > aMaxDist )
599 size_t j = ( i == bestEnd ) ? secondEnd : bestEnd;
604 double sum = dStart + dEnd[j];
606 if( !best || sum < best->second )
608 best = std::make_pair(
609 ANCHOR_PAIR{
CONSTRAINT_MEMBER( aCandidate->m_Uuid, anchors[i].anchor, anchors[i].index ),
622 std::optional<ANCHOR_PAIR> bestPair;
623 double bestSum = 0.0;
627 if( item->m_Uuid == aItem )
630 auto pair = bestPairOn( item );
635 if( !bestPair || pair->second < bestSum )
637 bestSum = pair->second;
638 bestPair = pair->first;
657 exclude.push_back( *startTarget );
690 double best = aMaxDist;
691 std::optional<KIID>
result;
695 const SHAPE_T shapeType = shape->GetShape();
700 dist =
SEG( shape->GetStart(), shape->GetEnd() ).
Distance( aPos );
704 dist =
std::abs( ( aPos - shape->GetCenter() ).EuclideanNorm() - shape->GetRadius() );
710 double a = shape->GetEllipseMajorRadius();
711 double b = shape->GetEllipseMinorRadius();
712 double phi = shape->GetEllipseRotation().AsRadians();
714 double lx = d.
x * std::cos( phi ) + d.
y * std::sin( phi );
715 double ly = -d.
x * std::sin( phi ) + d.
y * std::cos( phi );
716 double r = std::hypot( lx, ly );
718 if( a <= 0 || b <= 0 )
721 double theta = std::atan2( ly, lx );
722 double re = a * b / std::hypot( b * std::cos( theta ), a * std::sin( theta ) );
752 std::vector<CONSTRAINT_ANCHOR_POINT> anchors;
757 switch( aItem->
Type() )
793 const std::map<PCB_CONSTRAINT_TYPE, double>& aRemembered )
795 auto it = aRemembered.find( aType );
797 return it != aRemembered.end() ? it->second : aMeasured;
802 const VECTOR2I& aPos,
int aMaxDist )
807 for(
const KIID&
id : aCandidates )
811 if( shape && shape->
HitTest( aPos, aMaxDist ) )
821 std::unordered_set<KIID> ids;
827 [&](
const auto& aContainer )
832 ids.insert( item->m_Uuid );
837 ids.insert( cell->m_Uuid );
845 collect( footprint->GraphicalItems() );
853 std::vector<KIID> ids;
859 std::unordered_set<KIID> seen;
868 if( onBoard.contains( member.m_item ) && seen.insert( member.m_item ).second )
869 ids.push_back( member.m_item );
877 collect( footprint->Constraints() );
884 const VECTOR2I& aRim,
double aMaxDist )
889 std::optional<KIID> best;
890 double bestErr = 0.0;
894 if( shape->m_Uuid == aDimension || !isCircleOrArc( shape ) )
899 std::optional<VECTOR2I> centerPos;
910 double centerErr = ( *centerPos - aCenter ).EuclideanNorm();
912 if( centerErr > aMaxDist )
915 double rimErr =
std::abs( ( aRim - *centerPos ).EuclideanNorm() - shape->GetRadius() );
917 if( rimErr > aMaxDist )
925 double err = centerErr + rimErr;
927 if( !best || err < bestErr )
930 best = shape->m_Uuid;
940 if( !aBoard || !aDimension )
946 auto anyConstraint = [&](
const auto& aMatch )
948 if( std::ranges::any_of( aBoard->
Constraints(), aMatch ) )
953 return std::ranges::any_of( aBoard->
Footprints(),
955 { return std::ranges::any_of( aFootprint->Constraints(), aMatch ); } );
962 auto rimOnItem = [&](
const KIID& aItem )
964 return anyConstraint(
972 const std::vector<CONSTRAINT_MEMBER>& members = aConstraint->
GetMembers();
974 return members.size() == 2 && members[0] == endMember
979 return anyConstraint(
985 const std::vector<CONSTRAINT_MEMBER>& members = aConstraint->
GetMembers();
987 if( members.size() != 2 )
993 if( members[0] == startMember )
994 target = &members[1];
995 else if( members[1] == startMember )
996 target = &members[0];
1003 return item && isCircleOrArc( item ) && rimOnItem( target->
m_item );
1011 return anyConstraint(
1017 const std::vector<CONSTRAINT_MEMBER>& members = aConstraint->
GetMembers();
1020 if( members.size() != 2 || members[0].m_item == members[1].m_item )
1023 if( members[0] == aMember )
1026 return members[1] == aMember
1031 return hasCoincident( startMember ) && hasCoincident( endMember );
1040 switch( aDimension->
Type() )
1055 if( !aBoard || !aDimension )
1066 const std::vector<CONSTRAINT_MEMBER>& members = aConstraint->GetMembers();
1068 return members.size() == 2
1069 && ( ( members[0] == startMember && members[1] == endMember )
1070 || ( members[0] == endMember && members[1] == startMember ) );
1075 auto it = std::ranges::find_if( aList, matches );
1076 return it != aList.end() ? *it :
nullptr;
1104 return existing && existing->
IsDriving();
1112 if( lengthConstraint && lengthConstraint->
IsDriving() )
1123 std::optional<int> aDrivingLengthIU,
1124 const std::optional<wxString>& aOverrideText,
1125 const std::function<
void(
BOARD_ITEM* )>& aBeforeModify,
1126 const std::function<
void(
BOARD_ITEM* )>& aStageAdd,
1127 const std::function<
void(
BOARD_ITEM* )>& aBeforeRemove )
1138 if( !aDrivingLengthIU || *aDrivingLengthIU <= 0 || !
DimensionCanDrive( aBoard, aDimension ) )
1141 aBeforeModify( aDimension );
1147 aBeforeModify( existing );
1148 existing->
SetValue( *aDrivingLengthIU );
1160 constraint->SetValue( *aDrivingLengthIU );
1161 constraint->SetDriving(
true );
1164 aStageAdd( constraint.release() );
1168 aBeforeModify( aDimension );
1178 aBeforeRemove( existing );
1185 const std::function<
void(
BOARD_ITEM* )>& aBeforeModify,
1186 const std::function<
void(
BOARD_ITEM* )>& aBeforeRemove )
1188 if( !aBoard || aDelta == 0 )
1191 auto remapIn = [&](
const CONSTRAINTS& aConstraints )
1195 bool shifts =
false;
1196 bool doomed =
false;
1203 if( aDelta < 0 && member.m_index == aChangedIndex )
1205 else if( member.m_index >= aChangedIndex )
1214 aBeforeRemove( constraint );
1221 aBeforeModify( constraint );
1226 && member.m_index >= aChangedIndex )
1228 member.m_index += aDelta;
1237 remapIn( footprint->Constraints() );
1245 return std::ranges::any_of( aList,
1255 return std::ranges::any_of( aBoard->
Footprints(),
1258 return scan( aFootprint->Constraints() );
1267constexpr double AUTO_BIND_TOL_MM = 0.01;
1268constexpr double AUTO_CORRIDOR_MM = 0.25;
1269constexpr double AUTO_TANGENT_TOL_DEG = 10.0;
1273std::optional<double> tangentDirAt(
const PCB_SHAPE* aShape,
const VECTOR2I& aPos )
1281 if( dir.EuclideanNorm() == 0 )
1282 return std::nullopt;
1284 return std::atan2( dir.y, dir.x );
1292 if( radial.EuclideanNorm() == 0 )
1293 return std::nullopt;
1295 return std::atan2( radial.y, radial.x ) +
M_PI / 2;
1298 default:
return std::nullopt;
1308 const double tangentTol = AUTO_TANGENT_TOL_DEG *
M_PI / 180.0;
1313 if( !curveInvolved )
1316 std::optional<double> myDir = tangentDirAt( aShape, aPos );
1317 std::optional<double> otherDir = tangentDirAt( aTarget, aPos );
1319 if( !myDir || !otherDir )
1322 double diff = std::fabs( std::fmod( *myDir - *otherDir,
M_PI ) );
1323 diff = std::min( diff,
M_PI - diff );
1325 if( diff > tangentTol )
1338void addUnlessDuplicate(
const BOARD* aBoard, std::vector<AUTO_CONSTRAINT>& aResult,
1339 std::unique_ptr<PCB_CONSTRAINT> aConstraint,
bool aNeedsSolve )
1344 if( std::ranges::any_of( aResult,
1353 aResult.push_back( { std::move( aConstraint ), aNeedsSolve } );
1359std::vector<AUTO_CONSTRAINT> selectCenterBindings(
const BOARD* aBoard,
const PCB_SHAPE* aShape,
BOARD_ITEM* aParent )
1361 std::vector<AUTO_CONSTRAINT>
result;
1363 const double tol =
pcbIUScale.mmToIU( AUTO_BIND_TOL_MM );
1368 if( std::optional<CONSTRAINT_MEMBER> target =
1371 std::unique_ptr<PCB_CONSTRAINT> constraint;
1383 constraint->AddMember( target->m_item, target->m_anchor, target->m_index );
1386 addUnlessDuplicate( aBoard,
result, std::move( constraint ),
false );
1390 if( *outline != aShape->
m_Uuid )
1396 addUnlessDuplicate( aBoard,
result, std::move( constraint ),
false );
1406 std::vector<AUTO_CONSTRAINT>& aResult, std::set<CONSTRAINT_ANCHOR>& aBound,
1407 std::vector<std::pair<VECTOR2I, KIID>>& aTouches )
1409 const double tol =
pcbIUScale.mmToIU( AUTO_BIND_TOL_MM );
1417 constraint->AddMember( aShape->
m_Uuid, binding.sourceAnchor );
1418 constraint->AddMember( binding.target.m_item, binding.target.m_anchor, binding.target.m_index );
1420 aBound.insert( binding.sourceAnchor );
1423 aTouches.emplace_back( pos, binding.target.m_item );
1425 addUnlessDuplicate( aBoard, aResult, std::move( constraint ),
false );
1433 std::vector<AUTO_CONSTRAINT>& aResult,
const std::set<CONSTRAINT_ANCHOR>& aBound,
1434 std::vector<std::pair<VECTOR2I, KIID>>& aTouches )
1436 const double tol =
pcbIUScale.mmToIU( AUTO_BIND_TOL_MM );
1440 if( aBound.contains(
anchor ) )
1446 if( !target || *target == aShape->
m_Uuid )
1456 if( ( pos - mid ).EuclideanNorm() <= tol )
1460 auto constraint = std::make_unique<PCB_CONSTRAINT>( aParent, type );
1464 aTouches.emplace_back( pos, *target );
1466 addUnlessDuplicate( aBoard, aResult, std::move( constraint ),
false );
1474 std::vector<AUTO_CONSTRAINT>& aResult )
1479 const double tol =
pcbIUScale.mmToIU( AUTO_BIND_TOL_MM );
1480 const double corridor =
pcbIUScale.mmToIU( AUTO_CORRIDOR_MM );
1483 std::vector<VECTOR2I> boundPos;
1492 if( span.Distance(
anchor.pos ) > corridor )
1496 if( (
anchor.pos - aShape->
GetStart() ).EuclideanNorm() <= corridor
1497 || (
anchor.pos - aShape->
GetEnd() ).EuclideanNorm() <= corridor )
1503 if( std::ranges::any_of( boundPos,
1506 return (
anchor.pos - aP ).EuclideanNorm() <= tol;
1512 boundPos.push_back(
anchor.pos );
1515 constraint->AddMember( item->m_Uuid,
anchor.anchor,
anchor.index );
1518 addUnlessDuplicate( aBoard, aResult, std::move( constraint ),
true );
1526 std::vector<AUTO_CONSTRAINT>& aResult,
const std::vector<std::pair<VECTOR2I, KIID>>& aTouches )
1528 for(
const auto& [pos,
id] : aTouches )
1532 if( target && target != aShape )
1534 if( std::unique_ptr<PCB_CONSTRAINT> tangent = makeTangent( aShape, target, pos, aParent ) )
1535 addUnlessDuplicate( aBoard, aResult, std::move( tangent ),
true );
1543 std::vector<AUTO_CONSTRAINT>& aResult )
1551 if( !horizontal && !vertical )
1558 addUnlessDuplicate( aBoard, aResult, std::move( constraint ),
false );
1566 std::vector<AUTO_CONSTRAINT>
result;
1568 if( !aBoard || !aShape )
1572 return selectCenterBindings( aBoard, aShape, aParent );
1574 std::set<CONSTRAINT_ANCHOR> bound;
1575 std::vector<std::pair<VECTOR2I, KIID>> touches;
1577 selectEndpointCoincidents( aBoard, aShape, aParent,
result, bound, touches );
1578 selectOutlineFallbacks( aBoard, aShape, aParent,
result, bound, touches );
1579 selectCorridorPins( aBoard, aShape, aParent,
result );
1580 selectTangents( aBoard, aShape, aParent,
result, touches );
1582 if( aAxisConstraint )
1583 selectAxisConstraint( aBoard, aShape, aParent,
result );
constexpr EDA_IU_SCALE pcbIUScale
constexpr BOX2I KiROUND(const BOX2D &aBoxD)
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
virtual bool IsOnLayer(PCB_LAYER_ID aLayer) const
Test to see if this object is on the given layer.
FOOTPRINT * GetParentFootprint() const
Information pertinent to a Pcbnew printed circuit board.
const FOOTPRINTS & Footprints() const
const CONSTRAINTS & Constraints() const
Geometric constraints (#2329) owned by this board.
bool IsLayerVisible(PCB_LAYER_ID aLayer) const
A proxy function that calls the correspondent function in m_BoardSettings tests whether a given layer...
BOARD_ITEM * ResolveItem(const KIID &aID, bool aAllowNullptrReturn=false) const
const DRAWINGS & Drawings() const
KICAD_T Type() const
Returns the type of object.
SHAPE_POLY_SET & GetPolyShape()
const VECTOR2I & GetEnd() const
Return the ending point of the graphic.
const VECTOR2I & GetStart() const
Return the starting point of the graphic.
A geometric constraint between board items (issue #2329).
const std::vector< CONSTRAINT_MEMBER > & GetMembers() const
bool IsDriving() const
A driving constraint forces its value; a reference (non-driving) one only measures it.
PCB_CONSTRAINT_TYPE GetConstraintType() const
void SetValue(std::optional< double > aValue)
void SetDriving(bool aDriving)
void Update()
Update the dimension's cached text and geometry.
void SetOverrideTextEnabled(bool aOverride)
void SetOverrideText(const wxString &aValue)
bool GetOverrideTextEnabled() const
VECTOR2I GetCenter() const override
This defaults to the center of the bounding box if not overridden.
bool HitTest(const VECTOR2I &aPosition, int aAccuracy=0) const override
Test if aPosition is inside or on the boundary of this item.
PCB_LAYER_ID GetLayer() const override
Return the primary layer this item is on.
VECTOR2I::extended_type ecoord
int Distance(const SEG &aSeg) const
Compute minimum Euclidean distance to segment aSeg.
EDA_ANGLE Angle(const SEG &aOther) const
Determine the smallest angle between two segments.
Represent a polyline containing arcs as well as line segments: A chain of connected line and/or arc s...
int PointCount() const
Return the number of points (vertices) in this line chain.
Represent a set of closed polygons.
int HoleCount(int aOutline) const
Returns the number of holes in a given outline.
int OutlineCount() const
Return the number of outlines in the set.
const SHAPE_LINE_CHAIN & COutline(int aIndex) const
bool IsConstrainableItem(const BOARD_ITEM *aItem)
True when aItem is one ResolveConstrainableItem() accepts: a PCB_SHAPE or a dimension.
std::vector< ENDPOINT_BINDING > SelectEndpointBindings(const BOARD *aBoard, const KIID &aItem, const VECTOR2I &aStart, const std::optional< VECTOR2I > &aEnd, double aMaxDist, PCB_LAYER_ID aLayer)
Choose the coincident bindings a freshly drawn item endpoints should take so it tracks the geometry i...
std::optional< KIID > NearestConstrainedShape(const BOARD *aBoard, const std::vector< KIID > &aCandidates, const VECTOR2I &aPos, int aMaxDist)
The candidate shape whose outline aPos hits within aMaxDist, or std::nullopt.
void RemapPolygonVertexMembers(BOARD *aBoard, const KIID &aPoly, int aChangedIndex, int aDelta, const std::function< void(BOARD_ITEM *)> &aBeforeModify, const std::function< void(BOARD_ITEM *)> &aBeforeRemove)
Repoint persisted VERTEX constraint members after an outline edit of polygon aPoly inserts or removes...
std::vector< BOARD_ITEM * > CollectConstrainableItems(const BOARD *aBoard, PCB_LAYER_ID aLayer)
Every constrainable item on a visible layer – shapes plus dimensions – for board-wide anchor picking.
std::optional< KIID > NearestOutlineShape(const BOARD *aBoard, const VECTOR2I &aPos, double aMaxDist, bool aAllowCircle, PCB_LAYER_ID aLayer)
The shape whose outline is nearest aPos within aMaxDist.
std::vector< KIID > ConstrainedShapeIds(const BOARD *aBoard)
The member ids of every board and footprint constraint that are on aBoard, in first reference order: ...
double InitialConstraintValue(PCB_CONSTRAINT_TYPE aType, double aMeasured, const std::map< PCB_CONSTRAINT_TYPE, double > &aRemembered)
Value a freshly authored constraint dialog should open with.
EDA_ANGLE MeasureCornerAngle(const SEG &aA, const SEG &aB)
The corner angle between two segments, in the closed range [0, 180] degrees.
BOARD_ITEM * ResolveConstrainableItem(const BOARD *aBoard, const KIID &aId)
The board item a constraint may reference: a PCB_SHAPE or a dimension, or nullptr for anything else (...
bool DimensionHasValueMode(const PCB_DIMENSION_BASE *aDimension)
True for dimension types with a measured value aligned orthogonal or radial offering the Driven Drivi...
std::optional< CONSTRAINT_MEMBER > NearestConstraintAnchor(const BOARD *aBoard, const VECTOR2I &aPos, double aMaxDist, const std::vector< CONSTRAINT_MEMBER > &aExclude, PCB_LAYER_ID aLayer)
Find the constrainable-item anchor (a shape's segment/arc endpoint or centre, or a dimension's featur...
std::vector< CONSTRAINT_ANCHOR_POINT > ConstraintItemAnchors(const BOARD_ITEM *aItem)
The constraint anchors an item exposes.
std::optional< CONSTRAINT_ANCHOR_POINT > ConstraintShapeVertex(const PCB_SHAPE *aShape, int aIndex)
VERTEX anchor at ordinal aIndex of a rectangle or eligible polygon or std::nullopt if the shape has n...
wxString ConstraintSelectionHint(PCB_CONSTRAINT_TYPE aType)
A sentence naming what aType needs selected, for the moment a selection does not fit it and the tool ...
bool DimensionCanDrive(const BOARD *aBoard, const PCB_DIMENSION_BASE *aDimension)
True when Driving mode may be offered for aDimension needs both endpoints bound via DimensionEndpoint...
std::vector< AUTO_CONSTRAINT > SelectShapeAutoConstraints(const BOARD *aBoard, const PCB_SHAPE *aShape, BOARD_ITEM *aParent, bool aAxisConstraint)
Choose the constraints a freshly drawn shape should get from what its features landed on.
bool ConstraintIsDuplicateOnBoard(const BOARD *aBoard, const PCB_CONSTRAINT *aConstraint)
True if the board or one of its footprints already carries an equal constraint.
std::unique_ptr< PCB_CONSTRAINT > BuildConstraintFromItems(BOARD_ITEM *aParent, PCB_CONSTRAINT_TYPE aType, const std::vector< BOARD_ITEM * > &aItems)
Build a constraint of aType from a set of selected board items, or nullptr if the selection does not ...
std::vector< CONSTRAINT_ANCHOR_POINT > ConstraintShapeAnchors(const PCB_SHAPE *aShape)
Enumerate a shape constraint anchors with positions segment and arc endpoints arc centre circle centr...
std::optional< KIID > SelectRadialDimensionTarget(const BOARD *aBoard, const KIID &aDimension, const VECTOR2I &aCenter, const VECTOR2I &aRim, double aMaxDist)
Single circle or arc a radial dimension binds to or std::nullopt.
DIM_VALUE_MODE DimensionValueMode(const BOARD *aBoard, const PCB_DIMENSION_BASE *aDimension)
The value mode aDimension is in, derived from state: a self driving length means Driving,...
PCB_CONSTRAINT * FindDimensionLengthConstraint(const BOARD *aBoard, const PCB_DIMENSION_BASE *aDimension)
Self FIXED_LENGTH constraint whose members are exactly aDimension START and END or nullptr the drivin...
std::vector< PCB_SHAPE * > CollectConstraintShapes(const BOARD *aBoard, PCB_LAYER_ID aLayer)
Every PCB_SHAPE on a visible layer (drawings plus footprint graphics) – the candidates constraints ca...
std::unordered_set< KIID > CollectMemberCandidateIds(const BOARD *aBoard)
The ids of every item on aBoard a constraint member can resolve to (shapes, dimensions and table cell...
bool ConstraintPolygonIsModelable(const PCB_SHAPE *aShape)
True when polygon has one non empty hole free arc free outline making it solver eligible Shared by ad...
std::optional< CONSTRAINT_MEMBER > NearestAnchorAmong(const std::vector< PCB_SHAPE * > &aShapes, const VECTOR2I &aPos, double aMaxDist)
The {shape, anchor} member nearest aPos within aMaxDist among aShapes, or std::nullopt.
std::optional< VECTOR2I > ConstraintAnchorPosition(const BOARD *aBoard, const CONSTRAINT_MEMBER &aMember)
Current location of a constraint member's anchor (its shape's START/END/CENTER, or a dimension's feat...
bool DimensionEndpointsBound(const BOARD *aBoard, const PCB_DIMENSION_BASE *aDimension)
True when both of aDimension measured endpoints are bound to anchors that still resolve a coincident ...
PCB_CONSTRAINT * SetDimensionValueMode(BOARD *aBoard, PCB_DIMENSION_BASE *aDimension, DIM_VALUE_MODE aMode, std::optional< int > aDrivingLengthIU, const std::optional< wxString > &aOverrideText, const std::function< void(BOARD_ITEM *)> &aBeforeModify, const std::function< void(BOARD_ITEM *)> &aStageAdd, const std::function< void(BOARD_ITEM *)> &aBeforeRemove)
Apply a value mode transition to aDimension Driving creates or updates the driving length with aDrivi...
DIM_VALUE_MODE
Mode a value bearing dimension value is in Driven mirrors measured geometry Driving forces geometry t...
@ RECTANGLE
Use RECTANGLE instead of RECT to avoid collision in a Windows header.
PCB_LAYER_ID
A quick note on layer IDs:
bool contains(const _Container &__container, _Value __value)
Returns true if the container contains the given value.
EDA_ANGLE abs(const EDA_ANGLE &aAngle)
bool ConstraintsAreDuplicate(const PCB_CONSTRAINT &aA, const PCB_CONSTRAINT &aB)
True if two constraints express the same relation, meaning the same type and the same members compare...
wxString ConstraintTypeLabel(PCB_CONSTRAINT_TYPE aType)
Human-readable name of a constraint type (e.g. "Parallel"), for menus and lists.
CONSTRAINT_ANCHOR
Which feature of a referenced board item participates in a constraint.
@ VERTEX
An indexed rectangle corner or polygon outline vertex; pairs with CONSTRAINT_MEMBER::m_index.
@ WHOLE
The item as a whole (a segment as a line, a circle).
@ START
First endpoint of a segment or arc.
@ END
Second endpoint of a segment or arc.
@ CENTER
Center of an arc or circle.
PCB_CONSTRAINT_TYPE
The geometric relationship a PCB_CONSTRAINT enforces between its members.
@ CONCENTRIC
Two arcs/circles share a center.
@ SYMMETRIC
Two points are mirror images about an axis.
@ FIXED_POSITION
A point is locked at its current location.
@ VERTICAL
A segment (or two points) is vertical.
@ TANGENT
A line and a curve, or two curves, touch tangentially.
@ COINCIDENT
Two points are made to coincide.
@ PERPENDICULAR
Two segments are perpendicular.
@ FIXED_RADIUS
An arc/circle has a driving radius value.
@ HORIZONTAL
A segment (or two points) is horizontal.
@ EQUAL_RADIUS
Two arcs/circles have equal radius.
@ MIDPOINT
A point is the midpoint of a segment.
@ POINT_ON_LINE
A point lies on a segment's supporting line.
@ FIXED_LENGTH
A segment has a driving length value.
@ ANGULAR_DIMENSION
An angle between members (driving or reference).
@ COLLINEAR
Two segments lie on the same line.
@ ARC_ANGLE
An arc has a driving or reference swept-angle value.
@ PARALLEL
Two segments are parallel.
@ EQUAL_LENGTH
Two segments have equal length.
std::deque< PCB_CONSTRAINT * > CONSTRAINTS
One constraint chosen for a freshly drawn shape.
std::unique_ptr< PCB_CONSTRAINT > constraint
A selectable feature of a shape (a segment endpoint, arc centre, ...) and its location.
One participant in a constraint: a referenced board item plus the feature of that item that participa...
KIID m_item
Referenced board item, usually a PCB_SHAPE.
CONSTRAINT_ANCHOR m_anchor
Which feature of that item participates.
int m_index
Vertex ordinal; only meaningful for the VERTEX anchor.
One of a drawn item feature points bound coincident to an object anchor by draw time auto constrain s...
wxString result
Test unit parsing edge cases and error handling.
@ PCB_SHAPE_T
class PCB_SHAPE, a segment not on copper layers
@ PCB_DIM_ORTHOGONAL_T
class PCB_DIM_ORTHOGONAL, a linear dimension constrained to x/y
@ PCB_DIM_ALIGNED_T
class PCB_DIM_ALIGNED, a linear dimension (graphic item)
@ PCB_DIM_RADIAL_T
class PCB_DIM_RADIAL, a radius or diameter dimension
VECTOR2< int32_t > VECTOR2I
VECTOR2< double > VECTOR2D