| |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
|
|
| #ifndef PLANEGCS_GCS_H |
| #define PLANEGCS_GCS_H |
|
|
| #include <Eigen/QR> |
|
|
| #include "../../SketcherGlobal.h" |
| #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 |
| { |
| |
| |
| |
| #define XconvergenceRough 1e-8 |
| #define smallF 1e-20 |
|
|
| |
| |
| |
|
|
| enum SolveStatus |
| { |
| Success = 0, |
| Converged = 1, |
| Failed = 2, |
| SuccessfulSolutionInvalid = 3, |
| |
| }; |
|
|
| 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 |
| }; |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| enum SpecialTag |
| { |
| DefaultTemporaryConstraint = -1 |
| }; |
|
|
| class SketcherExport System |
| { |
| |
| |
| private: |
| VEC_pD plist; |
| VEC_pD pdrivenlist; |
| MAP_pD_I pIndex; |
|
|
| VEC_pD pDependentParameters; |
|
|
| |
| |
| std::vector<std::vector<double*>> pDependentParametersGroups; |
|
|
| std::vector<Constraint*> clist; |
| std::map<Constraint*, VEC_pD> c2p; |
| std::map<double*, std::vector<Constraint*>> p2c; |
|
|
| std::vector<SubSystem*> subSystems, subSystemsAux; |
| void clearSubSystems(); |
|
|
| VEC_D reference; |
| void setReference(); |
| void resetToReference(); |
|
|
| std::vector<VEC_pD> plists; |
| |
| std::vector<std::vector<Constraint*>> clists; |
| std::vector<MAP_pD_pD> reductionmaps; |
|
|
| int dofs; |
| std::set<Constraint*> redundant; |
| VEC_I conflictingTags, redundantTags, partiallyRedundantTags; |
|
|
| bool hasUnknowns; |
| bool hasDiagnosis; |
| bool isInit; |
|
|
| bool emptyDiagnoseMatrix; |
|
|
| 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 |
| |
| |
| |
| 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; |
| |
| bool sketchSizeMultiplierRedundant; |
| double convergence; |
| double convergenceRedundant; |
| QRAlgorithm qrAlgorithm; |
| bool autoChooseAlgorithm; |
| int autoQRThreshold; |
| 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(); |
|
|
| void clear(); |
| void clearByTag(int tagId); |
|
|
| int addConstraint(Constraint* constr); |
| void removeConstraint(Constraint* constr); |
|
|
| |
| 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 |
| ); |
|
|
| |
| 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); |
|
|
| |
| 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; |
|
|
| |
| |
| |
| |
| |
| 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(); |
| |
| |
| |
| |
| |
| 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(); |
|
|
| |
| 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; |
| }); |
| } |
| }; |
|
|
|
|
| |
| |
| |
|
|
| void deleteAllContent(VEC_pD& doublevec); |
| void deleteAllContent(std::vector<Constraint*>& constrvec); |
| void deleteAllContent(std::vector<SubSystem*>& subsysvec); |
|
|
| } |
|
|
| #endif |
|
|