646 lines
30 KiB
C++
646 lines
30 KiB
C++
/***************************************************************************
|
|
* Copyright (c) 2011 Konstantinos Poulios <logari81@gmail.com> *
|
|
* *
|
|
* This file is part of the FreeCAD CAx development system. *
|
|
* *
|
|
* This library is free software; you can redistribute it and/or *
|
|
* modify it under the terms of the GNU Library General Public *
|
|
* License as published by the Free Software Foundation; either *
|
|
* version 2 of the License, or (at your option) any later version. *
|
|
* *
|
|
* This library is distributed in the hope that it will be useful, *
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
|
* GNU Library General Public License for more details. *
|
|
* *
|
|
* You should have received a copy of the GNU Library General Public *
|
|
* License along with this library; see the file COPYING.LIB. If not, *
|
|
* write to the Free Software Foundation, Inc., 59 Temple Place, *
|
|
* Suite 330, Boston, MA 02111-1307, USA *
|
|
* *
|
|
***************************************************************************/
|
|
|
|
#ifndef PLANEGCS_GCS_H
|
|
#define PLANEGCS_GCS_H
|
|
|
|
#include <Eigen/QR>
|
|
#include <memory>
|
|
|
|
#include "SubSystem.h"
|
|
|
|
|
|
#define EIGEN_VERSION \
|
|
(EIGEN_WORLD_VERSION * 10000 + EIGEN_MAJOR_VERSION * 100 + EIGEN_MINOR_VERSION)
|
|
|
|
#if EIGEN_VERSION >= 30202
|
|
#define EIGEN_SPARSEQR_COMPATIBLE
|
|
#include <Eigen/Sparse>
|
|
#endif
|
|
|
|
namespace GCS
|
|
{
|
|
///////////////////////////////////////
|
|
// Other BFGS Solver parameters
|
|
///////////////////////////////////////
|
|
#define XconvergenceRough 1e-8
|
|
#define smallF 1e-20
|
|
|
|
///////////////////////////////////////
|
|
// Solver
|
|
///////////////////////////////////////
|
|
|
|
enum SolveStatus
|
|
{
|
|
Success = 0, // Found a solution zeroing the error function
|
|
Converged = 1, // Found a solution minimizing the error function
|
|
Failed = 2, // Failed to find any solution
|
|
SuccessfulSolutionInvalid = 3, // This is a solution where the solver succeeded, but the
|
|
// resulting geometry is OCE-invalid
|
|
};
|
|
|
|
enum Algorithm
|
|
{
|
|
BFGS = 0,
|
|
LevenbergMarquardt = 1,
|
|
DogLeg = 2
|
|
};
|
|
|
|
enum DogLegGaussStep
|
|
{
|
|
FullPivLU = 0,
|
|
LeastNormFullPivLU = 1,
|
|
LeastNormLdlt = 2
|
|
};
|
|
|
|
enum QRAlgorithm
|
|
{
|
|
EigenDenseQR = 0,
|
|
EigenSparseQR = 1
|
|
};
|
|
|
|
enum DebugMode
|
|
{
|
|
NoDebug = 0,
|
|
Minimal = 1,
|
|
IterationLevel = 2
|
|
};
|
|
|
|
// Magic numbers for Constraint tags
|
|
// - Positive Tags identify a higher level constraint form which the solver constraint
|
|
// originates
|
|
// - Negative Tags represent temporary constraints, used for example in moving operations, these
|
|
// have a different handling in component splitting, see GCS::initSolution. Lifetime is defined
|
|
// by the container object via GCS::clearByTag.
|
|
// - -1 is typically used as tag for these temporary constraints, its parameters are
|
|
// enforced with
|
|
// a lower priority than the main system (real sketcher constraints). It gives a nice
|
|
// effect when dragging the edge of an unconstrained circle, that the center won't move
|
|
// if the edge can be dragged, and only when/if the edge cannot be dragged, e.g. radius
|
|
// constraint, the center is moved).
|
|
enum SpecialTag
|
|
{
|
|
DefaultTemporaryConstraint = -1
|
|
};
|
|
|
|
class System
|
|
{
|
|
// This is the main class. It holds all constraints and information
|
|
// about partitioning into subsystems and solution strategies
|
|
private:
|
|
VEC_pD plist; // list of the unknown parameters
|
|
VEC_pD pdrivenlist; // list of parameters of driven constraints
|
|
MAP_pD_I pIndex;
|
|
|
|
VEC_FIXED_POINTS_COORDS pts; // list of fixed points by tag
|
|
|
|
VEC_pD pDependentParameters; // list of dependent parameters by the system
|
|
|
|
// This is a map of primary and secondary identifiers that are found dependent by the solver
|
|
// GCS ignores from a type point
|
|
std::vector<std::vector<double*>> pDependentParametersGroups;
|
|
|
|
std::vector<Constraint*> clist;
|
|
std::map<Constraint*, VEC_pD> c2p; // constraint to parameter adjacency list
|
|
std::map<double*, std::vector<Constraint*>> p2c; // parameter to constraint adjacency list
|
|
|
|
std::vector<SubSystem*> subSystems, subSystemsAux;
|
|
void clearSubSystems();
|
|
|
|
VEC_D reference;
|
|
void setReference(); // copies the current parameter values to reference
|
|
void resetToReference(); // reverts all parameter values to the stored reference
|
|
|
|
std::vector<VEC_pD> plists; // partitioned plist except equality constraints
|
|
// partitioned clist except equality constraints
|
|
std::vector<std::vector<Constraint*>> clists;
|
|
std::vector<MAP_pD_pD> reductionmaps; // for simplification of equality constraints
|
|
|
|
int dofs;
|
|
std::set<Constraint*> redundant;
|
|
VEC_I conflictingTags, redundantTags, partiallyRedundantTags;
|
|
|
|
bool hasUnknowns; // if plist is filled with the unknown parameters
|
|
bool hasDiagnosis; // if dofs, conflictingTags, redundantTags are up to date
|
|
bool isInit; // if plists, clists, reductionmaps are up to date
|
|
|
|
bool emptyDiagnoseMatrix; // false only if there is at least one driving constraint.
|
|
|
|
int solve_BFGS(SubSystem* subsys, bool isFine = true, bool isRedundantsolving = false);
|
|
int solve_LM(SubSystem* subsys, bool isRedundantsolving = false);
|
|
int solve_DL(SubSystem* subsys, bool isRedundantsolving = false);
|
|
|
|
void makeReducedJacobian(Eigen::MatrixXd& J,
|
|
std::map<int, int>& jacobianconstraintmap,
|
|
GCS::VEC_pD& pdiagnoselist,
|
|
std::map<int, int>& tagmultiplicity);
|
|
|
|
void makeDenseQRDecomposition(const Eigen::MatrixXd& J,
|
|
const std::map<int, int>& jacobianconstraintmap,
|
|
Eigen::FullPivHouseholderQR<Eigen::MatrixXd>& qrJT,
|
|
int& rank,
|
|
Eigen::MatrixXd& R,
|
|
bool transposeJ = true,
|
|
bool silent = false);
|
|
|
|
#ifdef EIGEN_SPARSEQR_COMPATIBLE
|
|
void makeSparseQRDecomposition(
|
|
const Eigen::MatrixXd& J,
|
|
const std::map<int, int>& jacobianconstraintmap,
|
|
Eigen::SparseQR<Eigen::SparseMatrix<double>, Eigen::COLAMDOrdering<int>>& SqrJT,
|
|
int& rank,
|
|
Eigen::MatrixXd& R,
|
|
bool transposeJ = true,
|
|
bool silent = false);
|
|
#endif
|
|
// This function name is long for a reason:
|
|
// - Only for DenseQR
|
|
// - Only for Transposed Jacobian QR decomposition
|
|
void identifyDependentGeometryParametersInTransposedJacobianDenseQRDecomposition(
|
|
const Eigen::FullPivHouseholderQR<Eigen::MatrixXd>& qrJT,
|
|
const GCS::VEC_pD& pdiagnoselist,
|
|
int paramsNum,
|
|
int rank);
|
|
|
|
template<typename T>
|
|
void identifyConflictingRedundantConstraints(Algorithm alg,
|
|
const T& qrJT,
|
|
const std::map<int, int>& jacobianconstraintmap,
|
|
const std::map<int, int>& tagmultiplicity,
|
|
GCS::VEC_pD& pdiagnoselist,
|
|
Eigen::MatrixXd& R,
|
|
int constrNum,
|
|
int rank,
|
|
int& nonredundantconstrNum);
|
|
|
|
void eliminateNonZerosOverPivotInUpperTriangularMatrix(Eigen::MatrixXd& R, int rank);
|
|
|
|
#ifdef EIGEN_SPARSEQR_COMPATIBLE
|
|
void identifyDependentParametersSparseQR(const Eigen::MatrixXd& J,
|
|
const std::map<int, int>& jacobianconstraintmap,
|
|
const GCS::VEC_pD& pdiagnoselist,
|
|
bool silent = true);
|
|
#endif
|
|
|
|
void identifyDependentParametersDenseQR(const Eigen::MatrixXd& J,
|
|
const std::map<int, int>& jacobianconstraintmap,
|
|
const GCS::VEC_pD& pdiagnoselist,
|
|
bool silent = true);
|
|
|
|
template<typename T>
|
|
void identifyDependentParameters(T& qrJ,
|
|
Eigen::MatrixXd& Rparams,
|
|
int rank,
|
|
const GCS::VEC_pD& pdiagnoselist,
|
|
bool silent = true);
|
|
|
|
#ifdef _GCS_EXTRACT_SOLVER_SUBSYSTEM_
|
|
void extractSubsystem(SubSystem* subsys, bool isRedundantsolving);
|
|
#endif
|
|
public:
|
|
int maxIter;
|
|
int maxIterRedundant;
|
|
bool sketchSizeMultiplier; // if true note that the total number of iterations allowed is
|
|
// MaxIterations *xLength
|
|
bool sketchSizeMultiplierRedundant;
|
|
double convergence;
|
|
double convergenceRedundant;
|
|
QRAlgorithm qrAlgorithm;
|
|
DogLegGaussStep dogLegGaussStep;
|
|
double qrpivotThreshold;
|
|
DebugMode debugMode;
|
|
double LM_eps;
|
|
double LM_eps1;
|
|
double LM_tau;
|
|
double DL_tolg;
|
|
double DL_tolx;
|
|
double DL_tolf;
|
|
double LM_epsRedundant;
|
|
double LM_eps1Redundant;
|
|
double LM_tauRedundant;
|
|
double DL_tolgRedundant;
|
|
double DL_tolxRedundant;
|
|
double DL_tolfRedundant;
|
|
|
|
public:
|
|
System();
|
|
/*System(std::vector<Constraint *> clist_);*/
|
|
~System();
|
|
|
|
void clear();
|
|
void clearByTag(int tagId, bool is_fixed_point = false);
|
|
int addConstraint(Constraint* constr);
|
|
void removeConstraint(Constraint* constr);
|
|
|
|
// basic constraints
|
|
int addConstraintFixed(Point& p, int tagId = 0, bool driving = true);
|
|
|
|
int addConstraintEqual(
|
|
double* param1,
|
|
double* param2,
|
|
int tagId = 0,
|
|
bool driving = true,
|
|
Constraint::Alignment internalalignment = Constraint::Alignment::NoInternalAlignment);
|
|
int addConstraintProportional(double* param1,
|
|
double* param2,
|
|
double ratio,
|
|
int tagId,
|
|
bool driving = true);
|
|
int addConstraintDifference(double* param1,
|
|
double* param2,
|
|
double* difference,
|
|
int tagId = 0,
|
|
bool driving = true);
|
|
int addConstraintP2PDistance(Point& p1,
|
|
Point& p2,
|
|
double* distance,
|
|
int tagId = 0,
|
|
bool driving = true);
|
|
int addConstraintP2PAngle(Point& p1,
|
|
Point& p2,
|
|
double* angle,
|
|
double incrAngle,
|
|
int tagId = 0,
|
|
bool driving = true);
|
|
int
|
|
addConstraintP2PAngle(Point& p1, Point& p2, double* angle, int tagId = 0, bool driving = true);
|
|
int addConstraintP2LDistance(Point& p,
|
|
Line& l,
|
|
double* distance,
|
|
int tagId = 0,
|
|
bool driving = true);
|
|
int addConstraintPointOnLine(Point& p, Line& l, int tagId = 0, bool driving = true);
|
|
int
|
|
addConstraintPointOnLine(Point& p, Point& lp1, Point& lp2, int tagId = 0, bool driving = true);
|
|
int addConstraintPointOnPerpBisector(Point& p, Line& l, int tagId = 0, bool driving = true);
|
|
int addConstraintPointOnPerpBisector(Point& p,
|
|
Point& lp1,
|
|
Point& lp2,
|
|
int tagId = 0,
|
|
bool driving = true);
|
|
int addConstraintParallel(Line& l1, Line& l2, int tagId = 0, bool driving = true);
|
|
int addConstraintPerpendicular(Line& l1, Line& l2, int tagId = 0, bool driving = true);
|
|
int addConstraintPerpendicular(Point& l1p1,
|
|
Point& l1p2,
|
|
Point& l2p1,
|
|
Point& l2p2,
|
|
int tagId = 0,
|
|
bool driving = true);
|
|
int
|
|
addConstraintL2LAngle(Line& l1, Line& l2, double* angle, int tagId = 0, bool driving = true);
|
|
int addConstraintL2LAngle(Point& l1p1,
|
|
Point& l1p2,
|
|
Point& l2p1,
|
|
Point& l2p2,
|
|
double* angle,
|
|
int tagId = 0,
|
|
bool driving = true);
|
|
int addConstraintAngleViaPoint(Curve& crv1,
|
|
Curve& crv2,
|
|
Point& p,
|
|
double* angle,
|
|
int tagId = 0,
|
|
bool driving = true);
|
|
int addConstraintAngleViaTwoPoints(Curve& crv1,
|
|
Curve& crv2,
|
|
Point& p1,
|
|
Point& p2,
|
|
double* angle,
|
|
int tagId = 0,
|
|
bool driving = true);
|
|
int addConstraintAngleViaPointAndParam(Curve& crv1,
|
|
Curve& crv2,
|
|
Point& p,
|
|
double* cparam,
|
|
double* angle,
|
|
int tagId = 0,
|
|
bool driving = true);
|
|
int addConstraintAngleViaPointAndTwoParams(Curve& crv1,
|
|
Curve& crv2,
|
|
Point& p,
|
|
double* cparam1,
|
|
double* cparam2,
|
|
double* angle,
|
|
int tagId = 0,
|
|
bool driving = true);
|
|
int addConstraintMidpointOnLine(Line& l1, Line& l2, int tagId = 0, bool driving = true);
|
|
int addConstraintMidpointOnLine(Point& l1p1,
|
|
Point& l1p2,
|
|
Point& l2p1,
|
|
Point& l2p2,
|
|
int tagId = 0,
|
|
bool driving = true);
|
|
int addConstraintTangentCircumf(Point& p1,
|
|
Point& p2,
|
|
double* rd1,
|
|
double* rd2,
|
|
bool internal = false,
|
|
int tagId = 0,
|
|
bool driving = true);
|
|
int addConstraintTangentAtBSplineKnot(BSpline& b,
|
|
Line& l,
|
|
unsigned int knotindex,
|
|
int tagId = 0,
|
|
bool driving = true);
|
|
|
|
// derived constraints
|
|
int addConstraintP2PCoincident(Point& p1, Point& p2, int tagId = 0, bool driving = true);
|
|
int addConstraintHorizontal(Line& l, int tagId = 0, bool driving = true);
|
|
int addConstraintHorizontal(Point& p1, Point& p2, int tagId = 0, bool driving = true);
|
|
int addConstraintVertical(Line& l, int tagId = 0, bool driving = true);
|
|
int addConstraintVertical(Point& p1, Point& p2, int tagId = 0, bool driving = true);
|
|
int addConstraintCoordinateX(Point& p, double* x, int tagId = 0, bool driving = true);
|
|
int addConstraintCoordinateY(Point& p, double* y, int tagId = 0, bool driving = true);
|
|
int addConstraintArcRules(Arc& a, int tagId = 0, bool driving = true);
|
|
int addConstraintPointOnCircle(Point& p, Circle& c, int tagId = 0, bool driving = true);
|
|
int addConstraintPointOnEllipse(Point& p, Ellipse& e, int tagId = 0, bool driving = true);
|
|
int addConstraintPointOnHyperbolicArc(Point& p,
|
|
ArcOfHyperbola& e,
|
|
int tagId = 0,
|
|
bool driving = true);
|
|
int addConstraintPointOnParabolicArc(Point& p,
|
|
ArcOfParabola& e,
|
|
int tagId = 0,
|
|
bool driving = true);
|
|
int addConstraintPointOnBSpline(Point& p,
|
|
BSpline& b,
|
|
double* pointparam,
|
|
int tagId,
|
|
bool driving = true);
|
|
int addConstraintArcOfEllipseRules(ArcOfEllipse& a, int tagId = 0, bool driving = true);
|
|
int addConstraintCurveValue(Point& p, Curve& a, double* u, int tagId = 0, bool driving = true);
|
|
int addConstraintArcOfHyperbolaRules(ArcOfHyperbola& a, int tagId = 0, bool driving = true);
|
|
int addConstraintArcOfParabolaRules(ArcOfParabola& a, int tagId = 0, bool driving = true);
|
|
int addConstraintPointOnArc(Point& p, Arc& a, int tagId = 0, bool driving = true);
|
|
int addConstraintPerpendicularLine2Arc(Point& p1,
|
|
Point& p2,
|
|
Arc& a,
|
|
int tagId = 0,
|
|
bool driving = true);
|
|
int addConstraintPerpendicularArc2Line(Arc& a,
|
|
Point& p1,
|
|
Point& p2,
|
|
int tagId = 0,
|
|
bool driving = true);
|
|
int addConstraintPerpendicularCircle2Arc(Point& center,
|
|
double* radius,
|
|
Arc& a,
|
|
int tagId = 0,
|
|
bool driving = true);
|
|
int addConstraintPerpendicularArc2Circle(Arc& a,
|
|
Point& center,
|
|
double* radius,
|
|
int tagId = 0,
|
|
bool driving = true);
|
|
int addConstraintPerpendicularArc2Arc(Arc& a1,
|
|
bool reverse1,
|
|
Arc& a2,
|
|
bool reverse2,
|
|
int tagId = 0,
|
|
bool driving = true);
|
|
int addConstraintTangent(Line& l, Circle& c, int tagId = 0, bool driving = true);
|
|
int addConstraintTangent(Line& l, Ellipse& e, int tagId = 0, bool driving = true);
|
|
int addConstraintTangent(Line& l, Arc& a, int tagId = 0, bool driving = true);
|
|
int addConstraintTangent(Circle& c1, Circle& c2, int tagId = 0, bool driving = true);
|
|
int addConstraintTangent(Arc& a1, Arc& a2, int tagId = 0, bool driving = true);
|
|
int addConstraintTangent(Circle& c, Arc& a, int tagId = 0, bool driving = true);
|
|
|
|
int addConstraintCircleRadius(Circle& c, double* radius, int tagId = 0, bool driving = true);
|
|
int addConstraintArcRadius(Arc& a, double* radius, int tagId = 0, bool driving = true);
|
|
int
|
|
addConstraintCircleDiameter(Circle& c, double* diameter, int tagId = 0, bool driving = true);
|
|
int addConstraintArcDiameter(Arc& a, double* diameter, int tagId = 0, bool driving = true);
|
|
int addConstraintEqualLength(Line& l1, Line& l2, int tagId = 0, bool driving = true);
|
|
int addConstraintEqualRadius(Circle& c1, Circle& c2, int tagId = 0, bool driving = true);
|
|
int addConstraintEqualRadii(Ellipse& e1, Ellipse& e2, int tagId = 0, bool driving = true);
|
|
int addConstraintEqualRadii(ArcOfHyperbola& a1,
|
|
ArcOfHyperbola& a2,
|
|
int tagId = 0,
|
|
bool driving = true);
|
|
int addConstraintEqualRadius(Circle& c1, Arc& a2, int tagId = 0, bool driving = true);
|
|
int addConstraintEqualRadius(Arc& a1, Arc& a2, int tagId = 0, bool driving = true);
|
|
int addConstraintEqualFocus(ArcOfParabola& a1,
|
|
ArcOfParabola& a2,
|
|
int tagId = 0,
|
|
bool driving = true);
|
|
int
|
|
addConstraintP2PSymmetric(Point& p1, Point& p2, Line& l, int tagId = 0, bool driving = true);
|
|
int
|
|
addConstraintP2PSymmetric(Point& p1, Point& p2, Point& p, int tagId = 0, bool driving = true);
|
|
int addConstraintSnellsLaw(Curve& ray1,
|
|
Curve& ray2,
|
|
Curve& boundary,
|
|
Point p,
|
|
double* n1,
|
|
double* n2,
|
|
bool flipn1,
|
|
bool flipn2,
|
|
int tagId,
|
|
bool driving = true);
|
|
|
|
int
|
|
addConstraintC2CDistance(Circle& c1, Circle& c2, double* dist, int tagId, bool driving = true);
|
|
int addConstraintC2LDistance(Circle& c, Line& l, double* dist, int tagId, bool driving = true);
|
|
int addConstraintP2CDistance(Point& p,
|
|
Circle& c,
|
|
double* distance,
|
|
int tagId = 0,
|
|
bool driving = true);
|
|
int addConstraintArcLength(Arc& a, double* dist, int tagId, bool driving = true);
|
|
|
|
// internal alignment constraints
|
|
int addConstraintInternalAlignmentPoint2Ellipse(Ellipse& e,
|
|
Point& p1,
|
|
InternalAlignmentType alignmentType,
|
|
int tagId = 0,
|
|
bool driving = true);
|
|
int addConstraintInternalAlignmentEllipseMajorDiameter(Ellipse& e,
|
|
Point& p1,
|
|
Point& p2,
|
|
int tagId = 0,
|
|
bool driving = true);
|
|
int addConstraintInternalAlignmentEllipseMinorDiameter(Ellipse& e,
|
|
Point& p1,
|
|
Point& p2,
|
|
int tagId = 0,
|
|
bool driving = true);
|
|
int addConstraintInternalAlignmentEllipseFocus1(Ellipse& e,
|
|
Point& p1,
|
|
int tagId = 0,
|
|
bool driving = true);
|
|
int addConstraintInternalAlignmentEllipseFocus2(Ellipse& e,
|
|
Point& p1,
|
|
int tagId = 0,
|
|
bool driving = true);
|
|
int addConstraintInternalAlignmentPoint2Hyperbola(Hyperbola& e,
|
|
Point& p1,
|
|
InternalAlignmentType alignmentType,
|
|
int tagId = 0,
|
|
bool driving = true);
|
|
int addConstraintInternalAlignmentHyperbolaMajorDiameter(Hyperbola& e,
|
|
Point& p1,
|
|
Point& p2,
|
|
int tagId = 0,
|
|
bool driving = true);
|
|
int addConstraintInternalAlignmentHyperbolaMinorDiameter(Hyperbola& e,
|
|
Point& p1,
|
|
Point& p2,
|
|
int tagId = 0,
|
|
bool driving = true);
|
|
int addConstraintInternalAlignmentHyperbolaFocus(Hyperbola& e,
|
|
Point& p1,
|
|
int tagId = 0,
|
|
bool driving = true);
|
|
int addConstraintInternalAlignmentParabolaFocus(Parabola& e,
|
|
Point& p1,
|
|
int tagId = 0,
|
|
bool driving = true);
|
|
int addConstraintInternalAlignmentBSplineControlPoint(BSpline& b,
|
|
Circle& c,
|
|
unsigned int poleindex,
|
|
int tag = 0,
|
|
bool driving = true);
|
|
int addConstraintInternalAlignmentKnotPoint(BSpline& b,
|
|
Point& p,
|
|
unsigned int knotindex,
|
|
int tagId = 0,
|
|
bool driving = true);
|
|
|
|
double calculateAngleViaPoint(const Curve& crv1, const Curve& crv2, Point& p) const;
|
|
double calculateAngleViaPoint(const Curve& crv1, const Curve& crv2, Point& p1, Point& p2) const;
|
|
double calculateAngleViaParams(const Curve& crv1,
|
|
const Curve& crv2,
|
|
double* param1,
|
|
double* param2) const;
|
|
void calculateNormalAtPoint(const Curve& crv, const Point& p, double& rtnX, double& rtnY) const;
|
|
|
|
// Calculates errors of all constraints which have a tag equal to
|
|
// the one supplied. Individual errors are summed up using RMS.
|
|
// If none are found, NAN is returned
|
|
// If there's only one, a signed value is returned.
|
|
// Effectively, it calculates the error of a UI constraint
|
|
double calculateConstraintErrorByTag(int tagId);
|
|
|
|
void rescaleConstraint(int id, double coeff);
|
|
|
|
void declareUnknowns(VEC_pD& params);
|
|
void declareDrivenParams(VEC_pD& params);
|
|
void initSolution(Algorithm alg = DogLeg);
|
|
|
|
int solve(bool isFine = true, Algorithm alg = DogLeg, bool isRedundantsolving = false);
|
|
int solve(VEC_pD& params,
|
|
bool isFine = true,
|
|
Algorithm alg = DogLeg,
|
|
bool isRedundantsolving = false);
|
|
int solve(SubSystem* subsys,
|
|
bool isFine = true,
|
|
Algorithm alg = DogLeg,
|
|
bool isRedundantsolving = false);
|
|
int solve(SubSystem* subsysA,
|
|
SubSystem* subsysB,
|
|
bool isFine = true,
|
|
bool isRedundantsolving = false);
|
|
|
|
void applySolution();
|
|
void undoSolution();
|
|
// FIXME: looks like XconvergenceFine is not the solver precision, at least in DogLeg
|
|
// solver.
|
|
// Note: Yes, every solver has a different way of interpreting precision
|
|
// but one has to study what is this needed for in order to decide
|
|
// what to return (this is unchanged from previous versions)
|
|
double getFinePrecision()
|
|
{
|
|
return convergence;
|
|
}
|
|
|
|
int diagnose(Algorithm alg = DogLeg);
|
|
int dofsNumber() const
|
|
{
|
|
return hasDiagnosis ? dofs : -1;
|
|
}
|
|
void getConflicting(VEC_I& conflictingOut) const
|
|
{
|
|
conflictingOut = hasDiagnosis ? conflictingTags : VEC_I(0);
|
|
}
|
|
void getRedundant(VEC_I& redundantOut) const
|
|
{
|
|
redundantOut = hasDiagnosis ? redundantTags : VEC_I(0);
|
|
}
|
|
void getPartiallyRedundant(VEC_I& partiallyredundantOut) const
|
|
{
|
|
partiallyredundantOut = hasDiagnosis ? partiallyRedundantTags : VEC_I(0);
|
|
}
|
|
void getDependentParams(VEC_pD& pdependentparameterlist) const
|
|
{
|
|
pdependentparameterlist = pDependentParameters;
|
|
}
|
|
void
|
|
getDependentParamsGroups(std::vector<std::vector<double*>>& pdependentparametergroups) const
|
|
{
|
|
pdependentparametergroups = pDependentParametersGroups;
|
|
}
|
|
bool isEmptyDiagnoseMatrix() const
|
|
{
|
|
return emptyDiagnoseMatrix;
|
|
}
|
|
|
|
bool hasConflicting() const
|
|
{
|
|
return !(hasDiagnosis && conflictingTags.empty());
|
|
}
|
|
bool hasRedundant() const
|
|
{
|
|
return !(hasDiagnosis && redundantTags.empty());
|
|
}
|
|
bool hasPartiallyRedundant() const
|
|
{
|
|
return !(hasDiagnosis && partiallyRedundantTags.empty());
|
|
}
|
|
|
|
void invalidatedDiagnosis();
|
|
|
|
// Unit testing interface - not intended for use by production code
|
|
protected:
|
|
size_t _getNumberOfConstraints(int tagID = -1)
|
|
{
|
|
if (tagID < 0) {
|
|
return clist.size();
|
|
}
|
|
return std::count_if(clist.begin(), clist.end(), [tagID](Constraint* constraint) {
|
|
return constraint->getTag() == tagID;
|
|
});
|
|
}
|
|
};
|
|
|
|
|
|
///////////////////////////////////////
|
|
// Helper elements
|
|
///////////////////////////////////////
|
|
|
|
void deleteAllContent(VEC_pD& doublevec);
|
|
void deleteAllContent(std::vector<Constraint*>& constrvec);
|
|
void deleteAllContent(std::vector<SubSystem*>& subsysvec);
|
|
|
|
} // namespace GCS
|
|
|
|
#endif // PLANEGCS_GCS_H
|