Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: solvespace/solvespace
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 549565958ff3
Choose a base ref
...
head repository: solvespace/solvespace
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: beea4444abd1
Choose a head ref
  • 2 commits
  • 4 files changed
  • 1 contributor

Commits on May 24, 2019

  1. In TryConstrain(), reject redundant constraints in overconstrained gr…

    …oups.
    
    This keeps groups with allowed redundant constraints cleaner when
    they are used together with automatic constraints.
    whitequark committed May 24, 2019
    Copy the full SHA
    cf2f0e5 View commit details
  2. Copy the full SHA
    beea444 View commit details
Showing with 34 additions and 31 deletions.
  1. +9 −3 src/constraint.cpp
  2. +5 −6 src/generate.cpp
  3. +9 −6 src/solvespace.h
  4. +11 −16 src/system.cpp
12 changes: 9 additions & 3 deletions src/constraint.cpp
Original file line number Diff line number Diff line change
@@ -106,10 +106,16 @@ hConstraint Constraint::Constrain(Constraint::Type type, hEntity ptA, hEntity pt
hConstraint Constraint::TryConstrain(Constraint::Type type, hEntity ptA, hEntity ptB,
hEntity entityA, hEntity entityB,
bool other, bool other2) {
SolveResult solvedBefore = SS.TestRankForGroup(SS.GW.activeGroup);
int rankBefore, rankAfter;
SolveResult howBefore = SS.TestRankForGroup(SS.GW.activeGroup, &rankBefore);
hConstraint hc = Constrain(type, ptA, ptB, entityA, entityB, other, other2);
SolveResult solvedAfter = SS.TestRankForGroup(SS.GW.activeGroup);
if(solvedBefore == SolveResult::OKAY && solvedAfter == SolveResult::REDUNDANT_OKAY) {
SolveResult howAfter = SS.TestRankForGroup(SS.GW.activeGroup, &rankAfter);
// There are two cases where the constraint is clearly redundant:
// * If the group wasn't overconstrained and now it is;
// * If the group was overconstrained, and adding the constraint doesn't change rank at all.
if((howBefore == SolveResult::OKAY && howAfter == SolveResult::REDUNDANT_OKAY) ||
(howBefore == SolveResult::REDUNDANT_OKAY && howAfter == SolveResult::REDUNDANT_OKAY &&
rankBefore == rankAfter)) {
SK.constraint.RemoveById(hc);
hc = {};
}
11 changes: 5 additions & 6 deletions src/generate.cpp
Original file line number Diff line number Diff line change
@@ -539,9 +539,10 @@ void SolveSpaceUI::SolveGroup(hGroup hg, bool andFindFree) {
WriteEqSystemForGroup(hg);
Group *g = SK.GetGroup(hg);
g->solved.remove.Clear();
SolveResult how = sys.Solve(g, &(g->solved.dof),
SolveResult how = sys.Solve(g, NULL,
&(g->solved.dof),
&(g->solved.remove),
/*andFindBad=*/true,
/*andFindBad=*/!g->allowRedundant,
/*andFindFree=*/andFindFree,
/*forceDofCheck=*/!g->dofCheckOk);
if(how == SolveResult::OKAY) {
@@ -551,12 +552,10 @@ void SolveSpaceUI::SolveGroup(hGroup hg, bool andFindFree) {
FreeAllTemporary();
}

SolveResult SolveSpaceUI::TestRankForGroup(hGroup hg) {
SolveResult SolveSpaceUI::TestRankForGroup(hGroup hg, int *rank) {
WriteEqSystemForGroup(hg);
Group *g = SK.GetGroup(hg);
SolveResult result = sys.SolveRank(g, NULL, NULL,
/*andFindBad=*/false,
/*andFindFree=*/false);
SolveResult result = sys.SolveRank(g, rank);
FreeAllTemporary();
return result;
}
15 changes: 9 additions & 6 deletions src/solvespace.h
Original file line number Diff line number Diff line change
@@ -289,7 +289,7 @@ class System {

static const double RANK_MAG_TOLERANCE, CONVERGE_TOLERANCE;
int CalculateRank();
bool TestRank();
bool TestRank(int *rank = NULL);
static bool SolveLinearSystem(double X[], double A[][MAX_UNKNOWNS],
double B[], int N);
bool SolveLeastSquares();
@@ -308,11 +308,14 @@ class System {
void MarkParamsFree(bool findFree);
int CalculateDof();

SolveResult Solve(Group *g, int *dof, List<hConstraint> *bad,
bool andFindBad, bool andFindFree, bool forceDofCheck = false);
SolveResult Solve(Group *g, int *rank = NULL, int *dof = NULL,
List<hConstraint> *bad = NULL,
bool andFindBad = false, bool andFindFree = false,
bool forceDofCheck = false);

SolveResult SolveRank(Group *g, int *dof, List<hConstraint> *bad,
bool andFindBad, bool andFindFree);
SolveResult SolveRank(Group *g, int *rank = NULL, int *dof = NULL,
List<hConstraint> *bad = NULL,
bool andFindBad = false, bool andFindFree = false);

void Clear();
};
@@ -776,7 +779,7 @@ class SolveSpaceUI {
bool genForBBox = false);
void SolveGroup(hGroup hg, bool andFindFree);
void SolveGroupAndReport(hGroup hg, bool andFindFree);
SolveResult TestRankForGroup(hGroup hg);
SolveResult TestRankForGroup(hGroup hg, int *rank = NULL);
void WriteEqSystemForGroup(hGroup hg);
void MarkDraggedParams();
void ForceReferences();
27 changes: 11 additions & 16 deletions src/system.cpp
Original file line number Diff line number Diff line change
@@ -170,9 +170,11 @@ int System::CalculateRank() {
return rank;
}

bool System::TestRank() {
bool System::TestRank(int *rank) {
EvalJacobian();
return CalculateRank() == mat.m;
int jacobianRank = CalculateRank();
if(rank) *rank = jacobianRank;
return jacobianRank == mat.m;
}

bool System::SolveLinearSystem(double X[], double A[][MAX_UNKNOWNS],
@@ -396,7 +398,7 @@ void System::FindWhichToRemoveToFixJacobian(Group *g, List<hConstraint> *bad, bo
}
}

SolveResult System::Solve(Group *g, int *dof, List<hConstraint> *bad,
SolveResult System::Solve(Group *g, int *rank, int *dof, List<hConstraint> *bad,
bool andFindBad, bool andFindFree, bool forceDofCheck)
{
WriteEquationsExceptFor(Constraint::NO_CONSTRAINT, g);
@@ -459,18 +461,16 @@ SolveResult System::Solve(Group *g, int *dof, List<hConstraint> *bad,
return SolveResult::TOO_MANY_UNKNOWNS;
}

rankOk = TestRank();
rankOk = TestRank(rank);

// And do the leftovers as one big system
if(!NewtonSolve(0)) {
goto didnt_converge;
}

rankOk = TestRank();
rankOk = TestRank(rank);
if(!rankOk) {
if(!g->allowRedundant) {
if(andFindBad) FindWhichToRemoveToFixJacobian(g, bad, forceDofCheck);
}
if(andFindBad) FindWhichToRemoveToFixJacobian(g, bad, forceDofCheck);
} else {
// This is not the full Jacobian, but any substitutions or single-eq
// solves removed one equation and one unknown, therefore no effect
@@ -517,7 +517,7 @@ SolveResult System::Solve(Group *g, int *dof, List<hConstraint> *bad,
return rankOk ? SolveResult::DIDNT_CONVERGE : SolveResult::REDUNDANT_DIDNT_CONVERGE;
}

SolveResult System::SolveRank(Group *g, int *dof, List<hConstraint> *bad,
SolveResult System::SolveRank(Group *g, int *rank, int *dof, List<hConstraint> *bad,
bool andFindBad, bool andFindFree)
{
WriteEquationsExceptFor(Constraint::NO_CONSTRAINT, g);
@@ -532,15 +532,10 @@ SolveResult System::SolveRank(Group *g, int *dof, List<hConstraint> *bad,
return SolveResult::TOO_MANY_UNKNOWNS;
}

bool rankOk = TestRank();
bool rankOk = TestRank(rank);
if(!rankOk) {
if(!g->allowRedundant) {
if(andFindBad) FindWhichToRemoveToFixJacobian(g, bad, /*forceDofCheck=*/true);
}
if(andFindBad) FindWhichToRemoveToFixJacobian(g, bad, /*forceDofCheck=*/true);
} else {
// This is not the full Jacobian, but any substitutions or single-eq
// solves removed one equation and one unknown, therefore no effect
// on the number of DOF.
if(dof) *dof = CalculateDof();
MarkParamsFree(andFindFree);
}