diff --git a/src/App/FreeCADInit.py b/src/App/FreeCADInit.py index bb09e479e7..f2a80ed777 100644 --- a/src/App/FreeCADInit.py +++ b/src/App/FreeCADInit.py @@ -178,8 +178,8 @@ def InitApplications(): InstallFile = os.path.join(Dir,"Init.py") if (os.path.exists(InstallFile)): try: - with open(file=InstallFile, encoding="utf-8") as f: - exec(f.read()) + with open(InstallFile, 'rt', encoding='utf-8') as f: + exec(compile(f.read(), InstallFile, 'exec')) except Exception as inst: Log('Init: Initializing ' + Dir + '... failed\n') Log('-'*100+'\n') diff --git a/src/Base/Matrix.cpp b/src/Base/Matrix.cpp index e3e6cd91ea..040ff8dc6a 100644 --- a/src/Base/Matrix.cpp +++ b/src/Base/Matrix.cpp @@ -63,9 +63,9 @@ Matrix4D::Matrix4D (double a11, double a12, double a13, double a14, { } -Matrix4D::Matrix4D (const Matrix4D& rclMtrx) : Matrix4D() +Matrix4D::Matrix4D (const Matrix4D& mat) : Matrix4D() { - (*this) = rclMtrx; + (*this) = mat; } Matrix4D::Matrix4D (const Vector3f& rclBase, const Vector3f& rclDir, float fAngle) @@ -148,47 +148,48 @@ double Matrix4D::determinant() const double Matrix4D::determinant3() const { - double a = dMtrx4D[0][0] * dMtrx4D[1][1] * dMtrx4D[2][2]; - double b = dMtrx4D[0][1] * dMtrx4D[1][2] * dMtrx4D[2][0]; - double c = dMtrx4D[1][0] * dMtrx4D[2][1] * dMtrx4D[0][2]; - double d = dMtrx4D[0][2] * dMtrx4D[1][1] * dMtrx4D[2][0]; - double e = dMtrx4D[1][0] * dMtrx4D[0][1] * dMtrx4D[2][2]; - double f = dMtrx4D[0][0] * dMtrx4D[2][1] * dMtrx4D[1][2]; - double det = (a + b + c) - (d + e + f); + double va = dMtrx4D[0][0] * dMtrx4D[1][1] * dMtrx4D[2][2]; + double vb = dMtrx4D[0][1] * dMtrx4D[1][2] * dMtrx4D[2][0]; + double vc = dMtrx4D[1][0] * dMtrx4D[2][1] * dMtrx4D[0][2]; + double vd = dMtrx4D[0][2] * dMtrx4D[1][1] * dMtrx4D[2][0]; + double ve = dMtrx4D[1][0] * dMtrx4D[0][1] * dMtrx4D[2][2]; + double vf = dMtrx4D[0][0] * dMtrx4D[2][1] * dMtrx4D[1][2]; + double det = (va + vb + vc) - (vd + ve + vf); return det; } -void Matrix4D::move (const Vector3f& rclVct) +void Matrix4D::move (const Vector3f& vec) { - move(convertTo(rclVct)); + move(convertTo(vec)); } -void Matrix4D::move (const Vector3d& rclVct) +void Matrix4D::move (const Vector3d& vec) { - dMtrx4D[0][3] += rclVct.x; - dMtrx4D[1][3] += rclVct.y; - dMtrx4D[2][3] += rclVct.z; + dMtrx4D[0][3] += vec.x; + dMtrx4D[1][3] += vec.y; + dMtrx4D[2][3] += vec.z; } -void Matrix4D::scale (const Vector3f& rclVct) +void Matrix4D::scale (const Vector3f& vec) { - scale(convertTo(rclVct)); + scale(convertTo(vec)); } -void Matrix4D::scale (const Vector3d& rclVct) +void Matrix4D::scale (const Vector3d& vec) { Matrix4D clMat; - clMat.dMtrx4D[0][0] = rclVct.x; - clMat.dMtrx4D[1][1] = rclVct.y; - clMat.dMtrx4D[2][2] = rclVct.z; + clMat.dMtrx4D[0][0] = vec.x; + clMat.dMtrx4D[1][1] = vec.y; + clMat.dMtrx4D[2][2] = vec.z; (*this) = clMat * (*this); } void Matrix4D::rotX (double fAngle) { Matrix4D clMat; - double fsin{}, fcos{}; + double fsin{}; + double fcos{}; fsin = sin (fAngle); fcos = cos (fAngle); @@ -201,7 +202,8 @@ void Matrix4D::rotX (double fAngle) void Matrix4D::rotY (double fAngle) { Matrix4D clMat; - double fsin{}, fcos{}; + double fsin{}; + double fcos{}; fsin = sin (fAngle); fcos = cos (fAngle); @@ -214,7 +216,8 @@ void Matrix4D::rotY (double fAngle) void Matrix4D::rotZ (double fAngle) { Matrix4D clMat; - double fsin{}, fcos{}; + double fsin{}; + double fcos{}; fsin = sin (fAngle); fcos = cos (fAngle); @@ -224,17 +227,20 @@ void Matrix4D::rotZ (double fAngle) (*this) = clMat * (*this); } -void Matrix4D::rotLine(const Vector3d& rclVct, double fAngle) +void Matrix4D::rotLine(const Vector3d& vec, double fAngle) { // **** algorithm was taken from a math book - Matrix4D clMA, clMB, clMC, clMRot; - Vector3d clRotAxis(rclVct); - short iz{}, is{}; - double fcos{}, fsin{}; + Matrix4D clMA; + Matrix4D clMB; + Matrix4D clMC; + Matrix4D clMRot; + Vector3d clRotAxis(vec); + double fcos{}; + double fsin{}; // set all entries to "0" - for (iz = 0; iz < 4; iz++) { - for (is = 0; is < 4; is++) { + for (short iz = 0; iz < 4; iz++) { + for (short is = 0; is < 4; is++) { clMA.dMtrx4D[iz][is] = 0; clMB.dMtrx4D[iz][is] = 0; clMC.dMtrx4D[iz][is] = 0; @@ -269,8 +275,8 @@ void Matrix4D::rotLine(const Vector3d& rclVct, double fAngle) clMC.dMtrx4D[2][0] = -fsin * clRotAxis.y; clMC.dMtrx4D[2][1] = fsin * clRotAxis.x; - for (iz = 0; iz < 3; iz++) { - for (is = 0; is < 3; is++) + for (short iz = 0; iz < 3; iz++) { + for (short is = 0; is < 3; is++) clMRot.dMtrx4D[iz][is] = clMA.dMtrx4D[iz][is] + clMB.dMtrx4D[iz][is] + clMC.dMtrx4D[iz][is]; @@ -279,9 +285,9 @@ void Matrix4D::rotLine(const Vector3d& rclVct, double fAngle) (*this) = clMRot * (*this); } -void Matrix4D::rotLine(const Vector3f& rclVct, float fAngle) +void Matrix4D::rotLine(const Vector3f& vec, float fAngle) { - Vector3d tmp = convertTo(rclVct); + Vector3d tmp = convertTo(vec); rotLine(tmp, static_cast(fAngle)); } @@ -455,35 +461,38 @@ bool Matrix4D::toAxisAngle (Vector3d& rclBase, Vector3d& rclDir, double& rfAngle return true; } -void Matrix4D::transform (const Vector3f& rclVct, const Matrix4D& rclMtrx) +void Matrix4D::transform (const Vector3f& vec, const Matrix4D& mat) { - move(-rclVct); - (*this) = rclMtrx * (*this); - move(rclVct); + move(-vec); + (*this) = mat * (*this); + move(vec); } -void Matrix4D::transform (const Vector3d& rclVct, const Matrix4D& rclMtrx) +void Matrix4D::transform (const Vector3d& vec, const Matrix4D& mat) { - move(-rclVct); - (*this) = rclMtrx * (*this); - move(rclVct); + move(-vec); + (*this) = mat * (*this); + move(vec); } void Matrix4D::inverse () { - Matrix4D clInvTrlMat, clInvRotMat; - short iz{}, is{}; + Matrix4D clInvTrlMat; + Matrix4D clInvRotMat; /**** Herausnehmen und Inversion der TranslationsMatrix aus der TransformationMatrix ****/ - for (iz = 0 ;iz < 3; iz++) + for (short iz = 0 ;iz < 3; iz++) { clInvTrlMat.dMtrx4D[iz][3] = -dMtrx4D[iz][3]; + } /**** Herausnehmen und Inversion der RotationsMatrix aus der TransformationMatrix ****/ - for (iz = 0 ;iz < 3; iz++) - for (is = 0 ;is < 3; is++) + for (short iz = 0 ;iz < 3; iz++) { + for (short is = 0 ;is < 3; is++) { clInvRotMat.dMtrx4D[iz][is] = dMtrx4D[is][iz]; + } + } /**** inv(M) = inv(Mtrl * Mrot) = inv(Mrot) * inv(Mtrl) ****/ (*this) = clInvRotMat * clInvTrlMat; @@ -563,12 +572,12 @@ void Matrix_gauss(Matrix a, Matrix b) void Matrix4D::inverseOrthogonal() { - Base::Vector3d c(dMtrx4D[0][3],dMtrx4D[1][3],dMtrx4D[2][3]); + Base::Vector3d vec(dMtrx4D[0][3],dMtrx4D[1][3],dMtrx4D[2][3]); transpose(); - c = this->operator * (c); - dMtrx4D[0][3] = -c.x; dMtrx4D[3][0] = 0; - dMtrx4D[1][3] = -c.y; dMtrx4D[3][1] = 0; - dMtrx4D[2][3] = -c.z; dMtrx4D[3][2] = 0; + vec = this->operator * (vec); + dMtrx4D[0][3] = -vec.x; dMtrx4D[3][0] = 0; + dMtrx4D[1][3] = -vec.y; dMtrx4D[3][1] = 0; + dMtrx4D[2][3] = -vec.z; dMtrx4D[3][2] = 0; } void Matrix4D::inverseGauss () @@ -767,8 +776,9 @@ std::string Matrix4D::analyse() const } } } - if (hastranslation) + if (hastranslation) { text += " with Translation"; + } } return text; } @@ -831,20 +841,26 @@ Matrix4D& Matrix4D::Hat(const Vector3d& rV) ScaleType Matrix4D::hasScale(double tol) const { + const double defaultTolerance = 1e-9; // check for uniform scaling // // For a scaled rotation matrix it matters whether // the scaling was applied from the left or right side. // Only in case of uniform scaling it doesn't make a difference. - if (tol == 0.0) - tol = 1e-9; + if (tol == 0.0) { + tol = defaultTolerance; + } // check if the absolute values are proportionally close or equal - auto closeAbs = [&](double a, double b) { - double c = fabs(a); - double d = fabs(b); - if (d>c) return (d-c)/d <= tol; - else if (c>d) return (c-d)/c <= tol; + auto closeAbs = [&](double val_a, double val_b) { + double abs_a = fabs(val_a); + double abs_b = fabs(val_b); + if (abs_b > abs_a) { + return (abs_b - abs_a)/abs_b <= tol; + } + if (abs_a > abs_b) { + return (abs_a-abs_b)/abs_a <= tol; + } return true; }; diff --git a/src/Base/Matrix.h b/src/Base/Matrix.h index 2827dda65b..5569dea636 100644 --- a/src/Base/Matrix.h +++ b/src/Base/Matrix.h @@ -67,7 +67,7 @@ public: double a31, double a32, double a33, double a34, double a41, double a42, double a43, double a44 ); /// Construction - Matrix4D (const Matrix4D& rclMtrx); + Matrix4D (const Matrix4D& mat); /// Construction with an Axis Matrix4D (const Vector3f& rclBase, const Vector3f& rclDir, float fAngle); Matrix4D (const Vector3d& rclBase, const Vector3d& rclDir, double fAngle); @@ -77,28 +77,28 @@ public: /** @name Operators */ //@{ /// Matrix addition - inline Matrix4D operator + (const Matrix4D& rclMtrx) const; - inline Matrix4D& operator += (const Matrix4D& rclMtrx); + inline Matrix4D operator + (const Matrix4D& mat) const; + inline Matrix4D& operator += (const Matrix4D& mat); /// Matrix subtraction - inline Matrix4D operator - (const Matrix4D& rclMtrx) const; - inline Matrix4D& operator -= (const Matrix4D& rclMtrx); + inline Matrix4D operator - (const Matrix4D& mat) const; + inline Matrix4D& operator -= (const Matrix4D& mat); /// Matrix multiplication - inline Matrix4D& operator *= (const Matrix4D& rclMtrx); + inline Matrix4D& operator *= (const Matrix4D& mat); /// Assignment - inline Matrix4D& operator = (const Matrix4D& rclMtrx); + inline Matrix4D& operator = (const Matrix4D& mat); /// Matrix multiplication - inline Matrix4D operator * (const Matrix4D& rclMtrx) const; + inline Matrix4D operator * (const Matrix4D& mat) const; /// Multiplication matrix with vector - inline Vector3f operator * (const Vector3f& rclVct) const; - inline Vector3d operator * (const Vector3d& rclVct) const; + inline Vector3f operator * (const Vector3f& vec) const; + inline Vector3d operator * (const Vector3d& vec) const; inline void multVec(const Vector3d & src, Vector3d & dst) const; inline void multVec(const Vector3f & src, Vector3f & dst) const; inline Matrix4D operator * (double) const; inline Matrix4D& operator *= (double); /// Comparison - inline bool operator != (const Matrix4D& rclMtrx) const; + inline bool operator != (const Matrix4D& mat) const; /// Comparison - inline bool operator == (const Matrix4D& rclMtrx) const; + inline bool operator == (const Matrix4D& mat) const; /// Index operator inline double* operator [] (unsigned short usNdx); /// Index operator @@ -107,14 +107,18 @@ public: inline Vector3d getRow(unsigned short usNdx) const; /// Get vector of column inline Vector3d getCol(unsigned short usNdx) const; - /// Get vector of trace - inline Vector3d trace() const; + /// Get vector of diagonal + inline Vector3d diagonal() const; + /// Get trace of the 3x3 matrix + inline double trace3() const; + /// Get trace of the 4x4 matrix + inline double trace() const; /// Set row to vector inline void setRow(unsigned short usNdx, const Vector3d&); /// Set column to vector inline void setCol(unsigned short usNdx, const Vector3d&); - /// Set trace to vector - inline void setTrace(const Vector3d&); + /// Set diagonal to vector + inline void setDiagonal(const Vector3d&); /// Compute the determinant of the matrix double determinant() const; /// Compute the determinant of the 3x3 sub-matrix @@ -154,16 +158,16 @@ public: void move (double x, double y, double z) { move(Vector3d(x,y,z)); } /// moves the coordinatesystem for the vector - void move (const Vector3f& rclVct); - void move (const Vector3d& rclVct); + void move (const Vector3f& vec); + void move (const Vector3d& vec); /// scale for the vector void scale (float x, float y, float z) { scale(Vector3f(x,y,z)); } void scale (double x, double y, double z) { scale(Vector3d(x,y,z)); } /// scale for the x,y,z value - void scale (const Vector3f& rclVct); - void scale (const Vector3d& rclVct); + void scale (const Vector3f& vec); + void scale (const Vector3d& vec); /// uniform scale void scale (float scalexyz) { scale(Vector3f(scalexyz, scalexyz, scalexyz)); } @@ -178,9 +182,9 @@ public: /// Rotate around the Z axis (in transformed space) for the given value in radians void rotZ (double fAngle); /// Rotate around an arbitrary axis passing the origin in radians - void rotLine (const Vector3f& rclVct, float fAngle); + void rotLine (const Vector3f& vec, float fAngle); /// Rotate around an arbitrary axis passing the origin in radians - void rotLine (const Vector3d& rclVct, double fAngle); + void rotLine (const Vector3d& vec, double fAngle); /// Rotate around an arbitrary axis that needn't necessarily pass the origin in radians void rotLine (const Vector3f& rclBase, const Vector3f& rclDir, float fAngle); /// Rotate around an arbitrary axis that needn't necessarily pass the origin in radians @@ -189,8 +193,8 @@ public: bool toAxisAngle (Vector3f& rclBase, Vector3f& rclDir, float& fAngle, float& fTranslation) const; bool toAxisAngle (Vector3d& rclBase, Vector3d& rclDir, double& fAngle, double& fTranslation) const; /// transform (move,scale,rotate) around a point - void transform (const Vector3f& rclVct, const Matrix4D& rclMtrx); - void transform (const Vector3d& rclVct, const Matrix4D& rclMtrx); + void transform (const Vector3f& vec, const Matrix4D& mat); + void transform (const Vector3d& vec, const Matrix4D& mat); /// Matrix is expected to have a 3x3 rotation submatrix. void inverse (); /// Matrix is expected to have a 3x3 rotation submatrix. @@ -210,55 +214,55 @@ private: double dMtrx4D[4][4]; }; -inline Matrix4D Matrix4D::operator + (const Matrix4D& rclMtrx) const +inline Matrix4D Matrix4D::operator + (const Matrix4D& mat) const { Matrix4D clMat; for (int iz = 0; iz < 4; iz++) { for (int is = 0; is < 4; is++) { - clMat.dMtrx4D[iz][is] = dMtrx4D[iz][is] + rclMtrx[iz][is]; + clMat.dMtrx4D[iz][is] = dMtrx4D[iz][is] + mat[iz][is]; } } return clMat; } -inline Matrix4D& Matrix4D::operator += (const Matrix4D& rclMtrx) +inline Matrix4D& Matrix4D::operator += (const Matrix4D& mat) { for (int iz = 0; iz < 4; iz++) { for (int is = 0; is < 4; is++) { - dMtrx4D[iz][is] += rclMtrx[iz][is]; + dMtrx4D[iz][is] += mat[iz][is]; } } return *this; } -inline Matrix4D Matrix4D::operator - (const Matrix4D& rclMtrx) const +inline Matrix4D Matrix4D::operator - (const Matrix4D& mat) const { Matrix4D clMat; for (int iz = 0; iz < 4; iz++) { for (int is = 0; is < 4; is++) { - clMat.dMtrx4D[iz][is] = dMtrx4D[iz][is] - rclMtrx[iz][is]; + clMat.dMtrx4D[iz][is] = dMtrx4D[iz][is] - mat[iz][is]; } } return clMat; } -inline Matrix4D& Matrix4D::operator -= (const Matrix4D& rclMtrx) +inline Matrix4D& Matrix4D::operator -= (const Matrix4D& mat) { for (int iz = 0; iz < 4; iz++) { for (int is = 0; is < 4; is++) { - dMtrx4D[iz][is] -= rclMtrx[iz][is]; + dMtrx4D[iz][is] -= mat[iz][is]; } } return *this; } -inline Matrix4D& Matrix4D::operator *= (const Matrix4D& rclMtrx) +inline Matrix4D& Matrix4D::operator *= (const Matrix4D& mat) { Matrix4D clMat; @@ -266,8 +270,7 @@ inline Matrix4D& Matrix4D::operator *= (const Matrix4D& rclMtrx) for (int is = 0; is < 4; is++) { clMat.dMtrx4D[iz][is] = 0; for (int ie = 0; ie < 4; ie++) { - clMat.dMtrx4D[iz][is] += dMtrx4D[iz][ie] * - rclMtrx.dMtrx4D[ie][is]; + clMat.dMtrx4D[iz][is] += dMtrx4D[iz][ie] * mat.dMtrx4D[ie][is]; } } } @@ -277,7 +280,7 @@ inline Matrix4D& Matrix4D::operator *= (const Matrix4D& rclMtrx) return *this; } -inline Matrix4D Matrix4D::operator * (const Matrix4D& rclMtrx) const +inline Matrix4D Matrix4D::operator * (const Matrix4D& mat) const { Matrix4D clMat; @@ -285,8 +288,7 @@ inline Matrix4D Matrix4D::operator * (const Matrix4D& rclMtrx) const for (int is = 0; is < 4; is++) { clMat.dMtrx4D[iz][is] = 0; for (int ie = 0; ie < 4; ie++) { - clMat.dMtrx4D[iz][is] += dMtrx4D[iz][ie] * - rclMtrx.dMtrx4D[ie][is]; + clMat.dMtrx4D[iz][is] += dMtrx4D[iz][ie] * mat.dMtrx4D[ie][is]; } } } @@ -294,51 +296,51 @@ inline Matrix4D Matrix4D::operator * (const Matrix4D& rclMtrx) const return clMat; } -inline Matrix4D& Matrix4D::operator= (const Matrix4D& rclMtrx) +inline Matrix4D& Matrix4D::operator= (const Matrix4D& mat) { for (int iz = 0; iz < 4; iz++) { for (int is = 0; is < 4; is++) { - dMtrx4D[iz][is] = rclMtrx.dMtrx4D[iz][is]; + dMtrx4D[iz][is] = mat.dMtrx4D[iz][is]; } } return *this; } -inline Vector3f Matrix4D::operator* (const Vector3f& rclVct) const +inline Vector3f Matrix4D::operator* (const Vector3f& vec) const { - double x = static_cast(rclVct.x); - double y = static_cast(rclVct.y); - double z = static_cast(rclVct.z); + double sx = static_cast(vec.x); + double sy = static_cast(vec.y); + double sz = static_cast(vec.z); return Vector3f( - static_cast(dMtrx4D[0][0]*x + dMtrx4D[0][1]*y + - dMtrx4D[0][2]*z + dMtrx4D[0][3]), - static_cast(dMtrx4D[1][0]*x + dMtrx4D[1][1]*y + - dMtrx4D[1][2]*z + dMtrx4D[1][3]), - static_cast(dMtrx4D[2][0]*x + dMtrx4D[2][1]*y + - dMtrx4D[2][2]*z + dMtrx4D[2][3]) + static_cast(dMtrx4D[0][0]*sx + dMtrx4D[0][1]*sy + + dMtrx4D[0][2]*sz + dMtrx4D[0][3]), + static_cast(dMtrx4D[1][0]*sx + dMtrx4D[1][1]*sy + + dMtrx4D[1][2]*sz + dMtrx4D[1][3]), + static_cast(dMtrx4D[2][0]*sx + dMtrx4D[2][1]*sy + + dMtrx4D[2][2]*sz + dMtrx4D[2][3]) ); } -inline Vector3d Matrix4D::operator* (const Vector3d& rclVct) const +inline Vector3d Matrix4D::operator* (const Vector3d& vec) const { - return Vector3d((dMtrx4D[0][0]*rclVct.x + dMtrx4D[0][1]*rclVct.y + - dMtrx4D[0][2]*rclVct.z + dMtrx4D[0][3]), - (dMtrx4D[1][0]*rclVct.x + dMtrx4D[1][1]*rclVct.y + - dMtrx4D[1][2]*rclVct.z + dMtrx4D[1][3]), - (dMtrx4D[2][0]*rclVct.x + dMtrx4D[2][1]*rclVct.y + - dMtrx4D[2][2]*rclVct.z + dMtrx4D[2][3])); + return Vector3d((dMtrx4D[0][0]*vec.x + dMtrx4D[0][1]*vec.y + + dMtrx4D[0][2]*vec.z + dMtrx4D[0][3]), + (dMtrx4D[1][0]*vec.x + dMtrx4D[1][1]*vec.y + + dMtrx4D[1][2]*vec.z + dMtrx4D[1][3]), + (dMtrx4D[2][0]*vec.x + dMtrx4D[2][1]*vec.y + + dMtrx4D[2][2]*vec.z + dMtrx4D[2][3])); } inline void Matrix4D::multVec(const Vector3d & src, Vector3d & dst) const { - double x = (dMtrx4D[0][0]*src.x + dMtrx4D[0][1]*src.y + - dMtrx4D[0][2]*src.z + dMtrx4D[0][3]); - double y = (dMtrx4D[1][0]*src.x + dMtrx4D[1][1]*src.y + - dMtrx4D[1][2]*src.z + dMtrx4D[1][3]); - double z = (dMtrx4D[2][0]*src.x + dMtrx4D[2][1]*src.y + - dMtrx4D[2][2]*src.z + dMtrx4D[2][3]); - dst.Set(x,y,z); + double dx = (dMtrx4D[0][0]*src.x + dMtrx4D[0][1]*src.y + + dMtrx4D[0][2]*src.z + dMtrx4D[0][3]); + double dy = (dMtrx4D[1][0]*src.x + dMtrx4D[1][1]*src.y + + dMtrx4D[1][2]*src.z + dMtrx4D[1][3]); + double dz = (dMtrx4D[2][0]*src.x + dMtrx4D[2][1]*src.y + + dMtrx4D[2][2]*src.z + dMtrx4D[2][3]); + dst.Set(dx,dy,dz); } inline void Matrix4D::multVec(const Vector3f & src, Vector3f & dst) const @@ -347,15 +349,15 @@ inline void Matrix4D::multVec(const Vector3f & src, Vector3f & dst) const double sy = static_cast(src.y); double sz = static_cast(src.z); - double x = (dMtrx4D[0][0]*sx + dMtrx4D[0][1]*sy + - dMtrx4D[0][2]*sz + dMtrx4D[0][3]); - double y = (dMtrx4D[1][0]*sx + dMtrx4D[1][1]*sy + - dMtrx4D[1][2]*sz + dMtrx4D[1][3]); - double z = (dMtrx4D[2][0]*sx + dMtrx4D[2][1]*sy + - dMtrx4D[2][2]*sz + dMtrx4D[2][3]); - dst.Set(static_cast(x), - static_cast(y), - static_cast(z)); + double dx = (dMtrx4D[0][0]*sx + dMtrx4D[0][1]*sy + + dMtrx4D[0][2]*sz + dMtrx4D[0][3]); + double dy = (dMtrx4D[1][0]*sx + dMtrx4D[1][1]*sy + + dMtrx4D[1][2]*sz + dMtrx4D[1][3]); + double dz = (dMtrx4D[2][0]*sx + dMtrx4D[2][1]*sy + + dMtrx4D[2][2]*sz + dMtrx4D[2][3]); + dst.Set(static_cast(dx), + static_cast(dy), + static_cast(dz)); } inline Matrix4D Matrix4D::operator * (double scalar) const @@ -382,11 +384,11 @@ inline Matrix4D& Matrix4D::operator *= (double scalar) return *this; } -inline bool Matrix4D::operator== (const Matrix4D& rclMtrx) const +inline bool Matrix4D::operator== (const Matrix4D& mat) const { for (int iz = 0; iz < 4; iz++) { for (int is = 0; is < 4; is++) { - if (fabs(dMtrx4D[iz][is] - rclMtrx.dMtrx4D[iz][is]) > traits_type::epsilon()) + if (fabs(dMtrx4D[iz][is] - mat.dMtrx4D[iz][is]) > traits_type::epsilon()) return false; } } @@ -394,16 +396,15 @@ inline bool Matrix4D::operator== (const Matrix4D& rclMtrx) const return true; } -inline bool Matrix4D::operator!= (const Matrix4D& rclMtrx) const +inline bool Matrix4D::operator!= (const Matrix4D& mat) const { - return !( (*this) == rclMtrx ); + return !((*this) == mat); } -inline Vector3f& operator*= (Vector3f& rclVect, - const Matrix4D& rclMtrx) +inline Vector3f& operator*= (Vector3f& vec, const Matrix4D& mat) { - rclVect = rclMtrx * rclVect; - return rclVect; + vec = mat * vec; + return vec; } inline double* Matrix4D::operator[] (unsigned short usNdx) @@ -426,30 +427,40 @@ inline Vector3d Matrix4D::getCol(unsigned short usNdx) const return Vector3d(dMtrx4D[0][usNdx], dMtrx4D[1][usNdx], dMtrx4D[2][usNdx]); } -inline Vector3d Matrix4D::trace() const +inline Vector3d Matrix4D::diagonal() const { return Vector3d(dMtrx4D[0][0], dMtrx4D[1][1], dMtrx4D[2][2]); } -inline void Matrix4D::setRow(unsigned short usNdx, const Vector3d& v) +inline double Matrix4D::trace3() const { - dMtrx4D[usNdx][0] = v.x; - dMtrx4D[usNdx][1] = v.y; - dMtrx4D[usNdx][2] = v.z; + return dMtrx4D[0][0] + dMtrx4D[1][1] + dMtrx4D[2][2]; } -inline void Matrix4D::setCol(unsigned short usNdx, const Vector3d& v) +inline double Matrix4D::trace() const { - dMtrx4D[0][usNdx] = v.x; - dMtrx4D[1][usNdx] = v.y; - dMtrx4D[2][usNdx] = v.z; + return dMtrx4D[0][0] + dMtrx4D[1][1] + dMtrx4D[2][2] + dMtrx4D[3][3]; } -inline void Matrix4D::setTrace(const Vector3d& v) +inline void Matrix4D::setRow(unsigned short usNdx, const Vector3d& vec) { - dMtrx4D[0][0] = v.x; - dMtrx4D[1][1] = v.y; - dMtrx4D[2][2] = v.z; + dMtrx4D[usNdx][0] = vec.x; + dMtrx4D[usNdx][1] = vec.y; + dMtrx4D[usNdx][2] = vec.z; +} + +inline void Matrix4D::setCol(unsigned short usNdx, const Vector3d& vec) +{ + dMtrx4D[0][usNdx] = vec.x; + dMtrx4D[1][usNdx] = vec.y; + dMtrx4D[2][usNdx] = vec.z; +} + +inline void Matrix4D::setDiagonal(const Vector3d& vec) +{ + dMtrx4D[0][0] = vec.x; + dMtrx4D[1][1] = vec.y; + dMtrx4D[2][2] = vec.z; } } // namespace Base diff --git a/src/Base/MatrixPy.xml b/src/Base/MatrixPy.xml index 160b0724de..f59db854ae 100644 --- a/src/Base/MatrixPy.xml +++ b/src/Base/MatrixPy.xml @@ -185,16 +185,16 @@ index : int vector : Base.Vector - + - trace() -> Base.Vector + diagonal() -> Base.Vector Return the diagonal of the 3x3 leading principal submatrix as vector. - + - setTrace(vector) -> None + setDiagonal(vector) -> None Set the diagonal of the 3x3 leading principal submatrix. diff --git a/src/Base/MatrixPyImp.cpp b/src/Base/MatrixPyImp.cpp index e4e9098e88..9cf794d37a 100644 --- a/src/Base/MatrixPyImp.cpp +++ b/src/Base/MatrixPyImp.cpp @@ -487,17 +487,17 @@ PyObject* MatrixPy::setRow(PyObject * args) Py_Return; } -PyObject* MatrixPy::trace(PyObject * args) +PyObject* MatrixPy::diagonal(PyObject * args) { if (!PyArg_ParseTuple(args, "")) return nullptr; Matrix4D* mat = getMatrixPtr(); - Base::Vector3d v = mat->trace(); + Base::Vector3d v = mat->diagonal(); return Py::new_reference_to(Py::Vector(v)); } -PyObject* MatrixPy::setTrace(PyObject * args) +PyObject* MatrixPy::setDiagonal(PyObject * args) { PyObject* o{}; if (!PyArg_ParseTuple(args, "O!", &(VectorPy::Type), &o)) @@ -505,7 +505,7 @@ PyObject* MatrixPy::setTrace(PyObject * args) Base::Vector3d v = Py::Vector(o, false).toVector(); Matrix4D* mat = getMatrixPtr(); - mat->setTrace(v); + mat->setDiagonal(v); Py_Return; } diff --git a/src/Gui/CMakeLists.txt b/src/Gui/CMakeLists.txt index 2d42991bda..248ea7ac4e 100644 --- a/src/Gui/CMakeLists.txt +++ b/src/Gui/CMakeLists.txt @@ -1152,6 +1152,7 @@ SET(FreeCADGui_CPP_SRCS DocumentPyImp.cpp DocumentObserver.cpp DocumentObserverPython.cpp + EditableDatumLabel.cpp ExpressionBinding.cpp ExpressionBindingPy.cpp GraphicsViewZoom.cpp @@ -1183,6 +1184,7 @@ SET(FreeCADGui_SRCS DocumentModel.h DocumentObserver.h DocumentObserverPython.h + EditableDatumLabel.h ExpressionBinding.h ExpressionBindingPy.h ExpressionCompleter.h diff --git a/src/Gui/ComboView.cpp b/src/Gui/ComboView.cpp index f142d7672f..a3a1c89ab6 100644 --- a/src/Gui/ComboView.cpp +++ b/src/Gui/ComboView.cpp @@ -23,15 +23,13 @@ #include "PreCompiled.h" #ifndef _PreComp_ # include +# include # include #endif #include "ComboView.h" -#include "BitmapFactory.h" -#include "Document.h" #include "PropertyView.h" #include "Tree.h" -#include "TaskView/TaskView.h" using namespace Gui; @@ -40,11 +38,8 @@ using namespace Gui::DockWnd; /* TRANSLATOR Gui::DockWnd::ComboView */ -ComboView::ComboView(bool showModel, Gui::Document* pcDocument, QWidget *parent) - : DockWindow(pcDocument,parent) - , oldTabIndex(0) - , modelIndex(-1) - , taskIndex(-1) +ComboView::ComboView(Gui::Document* pcDocument, QWidget *parent) + : DockWindow(pcDocument, parent) { setWindowTitle(tr("Combo View")); @@ -53,102 +48,20 @@ ComboView::ComboView(bool showModel, Gui::Document* pcDocument, QWidget *parent) pLayout->setContentsMargins ( 0, 0, 0, 0 ); // tabs to switch between Tree/Properties and TaskPanel - tabs = new QTabWidget (); - tabs->setObjectName(QString::fromUtf8("combiTab")); - tabs->setTabPosition(QTabWidget::North); - pLayout->addWidget( tabs, 0, 0 ); + auto splitter = new QSplitter(); + pLayout->addWidget( splitter, 0, 0 ); - connect(tabs, qOverload(&QTabWidget::currentChanged), - this, &ComboView::onCurrentTabChanged); - if (showModel) { - // splitter between tree and property view - auto splitter = new QSplitter(); - splitter->setOrientation(Qt::Vertical); + // splitter between tree and property view + splitter->setOrientation(Qt::Vertical); - tree = new TreePanel("ComboView", this); - splitter->addWidget(tree); + tree = new TreePanel("ComboView", this); + splitter->addWidget(tree); - // property view - prop = new PropertyView(this); - splitter->addWidget(prop); - modelIndex = tabs->addTab(splitter,tr("Model")); - } - else { - tree = nullptr; - prop = nullptr; - } - - // task panel - taskPanel = new Gui::TaskView::TaskView(this); - taskIndex = tabs->addTab(taskPanel, tr("Tasks")); - - // task panel - //projectView = new Gui::ProjectWidget(this); - //tabs->addTab(projectView, tr("Project")); + // property view + prop = new PropertyView(this); + splitter->addWidget(prop); } ComboView::~ComboView() = default; -void ComboView::showDialog(Gui::TaskView::TaskDialog *dlg) -{ - static QIcon icon = Gui::BitmapFactory().pixmap("edit-edit.svg"); - - // switch to the TaskView tab - oldTabIndex = tabs->currentIndex(); - tabs->setCurrentIndex(taskIndex); - tabs->setTabIcon(taskIndex, icon); - // set the dialog - taskPanel->showDialog(dlg); - - // force to show the combo view - if (modelIndex < 0) { - if (parentWidget()) - parentWidget()->raise(); - } -} - -void ComboView::closeDialog() -{ - // close the dialog - taskPanel->removeDialog(); -} - -void ComboView::closedDialog() -{ - static QIcon icon = QIcon(); - - // dialog has been closed - tabs->setCurrentIndex(oldTabIndex); - tabs->setTabIcon(taskIndex, icon); -} - -void ComboView::showTreeView() -{ - // switch to the tree view - tabs->setCurrentIndex(modelIndex); -} - -void ComboView::showTaskView() -{ - // switch to the task view - tabs->setCurrentIndex(taskIndex); -} - -void ComboView::changeEvent(QEvent *e) -{ - if (e->type() == QEvent::LanguageChange) { - tabs->setTabText(modelIndex, tr("Model")); - tabs->setTabText(taskIndex, tr("Tasks")); - //tabs->setTabText(2, tr("Project")); - } - - DockWindow::changeEvent(e); -} - -void ComboView::onCurrentTabChanged(int index) -{ - if (index != taskIndex) - oldTabIndex = index; -} - #include "moc_ComboView.cpp" diff --git a/src/Gui/ComboView.h b/src/Gui/ComboView.h index 195790314d..0aac485b05 100644 --- a/src/Gui/ComboView.h +++ b/src/Gui/ComboView.h @@ -56,7 +56,7 @@ namespace Gui { namespace DockWnd { /** Combo View - * is a combination of a tree, property and TaskPanel for + * is a combination of a tree and property view for * integrated user action. */ class GuiExport ComboView : public Gui::DockWindow @@ -68,7 +68,7 @@ public: * A constructor. * A more elaborate description of the constructor. */ - ComboView(bool showModel, Gui::Document* pcDocument, QWidget *parent=nullptr); + ComboView(Gui::Document* pcDocument, QWidget *parent=nullptr); /** * A destructor. @@ -76,33 +76,11 @@ public: */ ~ComboView() override; - Gui::TaskView::TaskView *getTaskPanel(){return taskPanel;} - QTabWidget* getTabPanel() const { return tabs;} - - friend class Gui::ControlSingleton; - void showTreeView(); - void showTaskView(); - -private Q_SLOTS: - void onCurrentTabChanged(int index); - -protected: - void showDialog(Gui::TaskView::TaskDialog *dlg); - void closeDialog(); - void closedDialog(); - void changeEvent(QEvent *e) override; - private: - int oldTabIndex; - int modelIndex; - int taskIndex; - QTabWidget * tabs; Gui::PropertyView * prop; Gui::TreePanel * tree; - Gui::TaskView::TaskView * taskPanel; - //Gui::ProjectWidget * projectView; }; } // namespace DockWnd diff --git a/src/Gui/Control.cpp b/src/Gui/Control.cpp index 47e21cd17b..2bfcd1ece4 100644 --- a/src/Gui/Control.cpp +++ b/src/Gui/Control.cpp @@ -37,6 +37,8 @@ #include #include "Control.h" +#include "BitmapFactory.h" +#include "Tree.h" #include "TaskView/TaskView.h" @@ -46,10 +48,10 @@ using namespace std; /* TRANSLATOR Gui::ControlSingleton */ ControlSingleton* ControlSingleton::_pcSingleton = nullptr; -static QPointer _taskPanel = nullptr; ControlSingleton::ControlSingleton() : ActiveDialog(nullptr) + , oldTabIndex(-1) { } @@ -58,37 +60,86 @@ ControlSingleton::~ControlSingleton() = default; Gui::TaskView::TaskView* ControlSingleton::taskPanel() const { - auto pcComboView = qobject_cast - (Gui::DockWindowManager::instance()->getDockWindow("Combo View")); - // should return the pointer to combo view - if (pcComboView) - return pcComboView->getTaskPanel(); - // not all workbenches have the combo view enabled - else if (_taskPanel) - return _taskPanel; - // no task panel available - else - return nullptr; + auto taskView = qobject_cast + (Gui::DockWindowManager::instance()->getDockWindow("Tasks")); + return taskView; +} + +void ControlSingleton::showDockWidget(QWidget* widget) +{ + QWidget* parent = widget->parentWidget(); + if (parent) { + parent->show(); + parent->raise(); + } +} + +QTabBar* ControlSingleton::findTabBar(QDockWidget* widget) const +{ + int count = getMainWindow()->tabifiedDockWidgets(widget).size() + 1; + if (count > 1) { + QList bars = getMainWindow()->findChildren(); + for (auto it : bars) { + if (it->count() <= count) { + for (int i = 0; i < count; i++) { + if (it->tabText(i) == widget->windowTitle()) { + return it; + } + } + } + } + } + + return nullptr; +} + +void ControlSingleton::aboutToShowDialog(QDockWidget* widget) +{ + static QIcon icon = Gui::BitmapFactory().pixmap("edit-edit.svg"); + QTabBar* bar = findTabBar(widget); + if (bar) { + oldTabIndex = bar->currentIndex(); + for (int i = 0; i < bar->count(); i++) { + if (bar->tabText(i) == widget->windowTitle()) { + bar->setTabIcon(i, icon); + break; + } + } + } + + widget->show(); + widget->raise(); +} + +void ControlSingleton::aboutToHideDialog(QDockWidget* widget) +{ + QTabBar* bar = findTabBar(widget); + if (bar) { + bar->setCurrentIndex(oldTabIndex); + for (int i = 0; i < bar->count(); i++) { + if (bar->tabText(i) == widget->windowTitle()) { + bar->setTabIcon(i, QIcon()); + break; + } + } + } } void ControlSingleton::showTaskView() { - auto pcComboView = qobject_cast - (Gui::DockWindowManager::instance()->getDockWindow("Combo View")); - if (pcComboView) - pcComboView->showTaskView(); - else if (_taskPanel) - _taskPanel->raise(); + Gui::TaskView::TaskView* taskView = taskPanel(); + if (taskView) { + showDockWidget(taskView); + } } void ControlSingleton::showModelView() { - auto pcComboView = qobject_cast - (Gui::DockWindowManager::instance()->getDockWindow("Combo View")); - if (pcComboView) - pcComboView->showTreeView(); - else if (_taskPanel) - _taskPanel->raise(); + auto treeView = qobject_cast + (Gui::DockWindowManager::instance()->getDockWindow("Tree view")); + if (treeView) { + showDockWidget(treeView); + } } void ControlSingleton::showDialog(Gui::TaskView::TaskDialog *dlg) @@ -113,14 +164,15 @@ void ControlSingleton::showDialog(Gui::TaskView::TaskDialog *dlg) // which may open a transaction but fails when auto transaction is still active. App::AutoTransaction::setEnable(false); - auto pcComboView = qobject_cast - (Gui::DockWindowManager::instance()->getDockWindow("Combo View")); + Gui::TaskView::TaskView* taskView = taskPanel(); // should return the pointer to combo view - if (pcComboView) { - pcComboView->showDialog(dlg); + if (taskView) { + taskView->showDialog(dlg); + // make sure that the combo view is shown - auto dw = qobject_cast(pcComboView->parentWidget()); + auto dw = qobject_cast(taskView->parentWidget()); if (dw) { + aboutToShowDialog(dw); dw->setVisible(true); dw->toggleViewAction()->setVisible(true); dw->setFeatures(QDockWidget::DockWidgetMovable|QDockWidget::DockWidgetFloatable); @@ -132,37 +184,6 @@ void ControlSingleton::showDialog(Gui::TaskView::TaskDialog *dlg) connect(dlg, &TaskView::TaskDialog::aboutToBeDestroyed, this, &ControlSingleton::closedDialog); } - // not all workbenches have the combo view enabled - else if (!_taskPanel) { - auto dw = new QDockWidget(); - dw->setWindowTitle(tr("Task panel")); - dw->setFeatures(QDockWidget::DockWidgetMovable); - _taskPanel = new Gui::TaskView::TaskView(dw); - dw->setWidget(_taskPanel); - _taskPanel->showDialog(dlg); - getMainWindow()->addDockWidget(Qt::LeftDockWidgetArea, dw); - connect(dlg, &TaskView::TaskDialog::destroyed, dw, &ControlSingleton::deleteLater); - - // if we have the normal tree view available then just tabify with it - QWidget* treeView = Gui::DockWindowManager::instance()->getDockWindow("Tree view"); - QDockWidget* par = treeView ? qobject_cast(treeView->parent()) : 0; - if (par && par->isVisible()) { - getMainWindow()->tabifyDockWidget(par, dw); - qApp->processEvents(); // make sure that the task panel is tabified now - dw->show(); - dw->raise(); - } - } -} - -QTabWidget* ControlSingleton::tabPanel() const -{ - Gui::DockWnd::ComboView* pcComboView = qobject_cast - (Gui::DockWindowManager::instance()->getDockWindow("Combo View")); - // should return the pointer to combo view - if (pcComboView) - return pcComboView->getTabPanel(); - return nullptr; } Gui::TaskView::TaskDialog* ControlSingleton::activeDialog() const @@ -170,22 +191,11 @@ Gui::TaskView::TaskDialog* ControlSingleton::activeDialog() const return ActiveDialog; } -Gui::TaskView::TaskView* ControlSingleton::getTaskPanel() -{ - // should return the pointer to combo view - auto pcComboView = qobject_cast - (Gui::DockWindowManager::instance()->getDockWindow("Combo View")); - if (pcComboView) - return pcComboView->getTaskPanel(); - else - return _taskPanel; -} - void ControlSingleton::accept() { - Gui::TaskView::TaskView* taskPanel = getTaskPanel(); - if (taskPanel) { - taskPanel->accept(); + Gui::TaskView::TaskView* taskView = taskPanel(); + if (taskView) { + taskView->accept(); qApp->processEvents(QEventLoop::ExcludeUserInputEvents | QEventLoop::ExcludeSocketNotifiers); } @@ -193,9 +203,9 @@ void ControlSingleton::accept() void ControlSingleton::reject() { - Gui::TaskView::TaskView* taskPanel = getTaskPanel(); - if (taskPanel) { - taskPanel->reject(); + Gui::TaskView::TaskView* taskView = taskPanel(); + if (taskView) { + taskView->reject(); qApp->processEvents(QEventLoop::ExcludeUserInputEvents | QEventLoop::ExcludeSocketNotifiers); } @@ -203,29 +213,25 @@ void ControlSingleton::reject() void ControlSingleton::closeDialog() { - auto pcComboView = qobject_cast - (Gui::DockWindowManager::instance()->getDockWindow("Combo View")); - // should return the pointer to combo view - if (pcComboView) - pcComboView->closeDialog(); - else if (_taskPanel) - _taskPanel->removeDialog(); + Gui::TaskView::TaskView* taskView = taskPanel(); + if (taskView) + taskView->removeDialog(); } void ControlSingleton::closedDialog() { ActiveDialog = nullptr; - auto pcComboView = qobject_cast - (Gui::DockWindowManager::instance()->getDockWindow("Combo View")); - // should return the pointer to combo view - assert(pcComboView); - pcComboView->closedDialog(); + Gui::TaskView::TaskView* taskView = taskPanel(); + assert(taskView); + // make sure that the combo view is shown - auto dw = qobject_cast(pcComboView->parentWidget()); - if (dw) + auto dw = qobject_cast(taskView->parentWidget()); + if (dw) { + aboutToHideDialog(dw); dw->setFeatures(QDockWidget::DockWidgetClosable | QDockWidget::DockWidgetMovable | QDockWidget::DockWidgetFloatable); + } } bool ControlSingleton::isAllowedAlterDocument() const diff --git a/src/Gui/Control.h b/src/Gui/Control.h index 7da5098ce3..fd4d3ed838 100644 --- a/src/Gui/Control.h +++ b/src/Gui/Control.h @@ -32,7 +32,8 @@ #include -class QTabWidget; +class QDockWidget; +class QTabBar; namespace App { @@ -75,8 +76,6 @@ public: Gui::TaskView::TaskView* taskPanel() const; /// raising the model view void showModelView(); - /// get the tab panel - QTabWidget* tabPanel() const; //@} /*! @@ -106,9 +105,6 @@ private Q_SLOTS: /// This get called by the TaskView when the Dialog is finished void closedDialog(); -private: - Gui::TaskView::TaskView *getTaskPanel(); - private: struct status { std::bitset<32> StatusBits; @@ -117,12 +113,17 @@ private: std::stack StatusStack; Gui::TaskView::TaskDialog *ActiveDialog; + int oldTabIndex; private: /// Construction ControlSingleton(); /// Destruction ~ControlSingleton() override; + void showDockWidget(QWidget*); + QTabBar* findTabBar(QDockWidget*) const; + void aboutToShowDialog(QDockWidget* widget); + void aboutToHideDialog(QDockWidget* widget); static ControlSingleton* _pcSingleton; }; diff --git a/src/Gui/DlgMacroExecute.ui b/src/Gui/DlgMacroExecute.ui index 084ecaf868..8b7871f8fc 100644 --- a/src/Gui/DlgMacroExecute.ui +++ b/src/Gui/DlgMacroExecute.ui @@ -77,7 +77,39 @@ - + + + + + + Find file: + + + + + + + Case-insensitive search for filenames, regular expressions supported + + + + + + + Find in files: + + + + + + + Filter by case-insensitive file content, regular expressions supported + + + + + + QTabWidget::North @@ -137,7 +169,7 @@ - + @@ -281,7 +313,7 @@ - + User macros location: @@ -307,15 +339,12 @@ Qt::StrongFocus - - Gui::FileChooser::Directory - - + diff --git a/src/Gui/DlgMacroExecuteImp.cpp b/src/Gui/DlgMacroExecuteImp.cpp index 3c4abe69c5..5c2cbc1b65 100644 --- a/src/Gui/DlgMacroExecuteImp.cpp +++ b/src/Gui/DlgMacroExecuteImp.cpp @@ -27,6 +27,7 @@ # include # include # include +# include #endif #include @@ -132,35 +133,108 @@ void DlgMacroExecuteImp::setupConnections() this, &DlgMacroExecuteImp::onSystemMacroListBoxCurrentItemChanged); connect(ui->tabMacroWidget, &QTabWidget::currentChanged, this, &DlgMacroExecuteImp::onTabMacroWidgetCurrentChanged); + connect(ui->LineEditFind, &QLineEdit::textChanged, + this, &DlgMacroExecuteImp::onLineEditFindTextChanged); + connect(ui->LineEditFindInFiles, &QLineEdit::textChanged, + this, &DlgMacroExecuteImp::onLineEditFindInFilesTextChanged); +} + +/** Take a folder and return a StringList of the filenames in it + * filtered by both filename *and* by content, if the user has + * put text in one or both of the search line edits. + * + * First filtering is done by file name, which reduces the + * number of files to open and read (relatively expensive operation). + * + * Then we filter by file content after reducing the number of files + * to open and read. But both loops are skipped if there is no text + * in either of the line edits. + * + * We do this as another function in order to reuse this code for + * doing both the User and System macro list boxes in the fillUpList() function. + */ + +QStringList DlgMacroExecuteImp::filterFiles(const QString& folder){ + QDir dir(folder, QLatin1String("*.FCMacro *.py")); + QStringList unfiltered = dir.entryList(); //all .fcmacro and .py files + QString fileFilter = ui->LineEditFind->text(); //used to search by filename + QString searchText = ui->LineEditFindInFiles->text(); //used to search in file content + + if (fileFilter.isEmpty() && searchText.isEmpty()){ //skip filtering if no filters + return unfiltered; + } + QStringList filteredByFileName; + if (fileFilter.isEmpty()){ + filteredByFileName = unfiltered; //skip the loop if no file filter + } else { + QRegularExpression regexFileName(fileFilter, QRegularExpression::CaseInsensitiveOption); + bool isValidFileFilter = regexFileName.isValid(); //check here instead of inside the loop + for (auto uf : unfiltered){ + if (isValidFileFilter){ + if (regexFileName.match(uf).hasMatch()) { + filteredByFileName.append(uf); + } + } else { //not valid, so do a simple text search + if (uf.contains(fileFilter, Qt::CaseInsensitive)) { + filteredByFileName.append(uf); + } + } + } + } + + if (searchText.isEmpty()){ //skip reading file contents if no find in file filter + return filteredByFileName; + } + + QRegularExpression regexContent(searchText, QRegularExpression::CaseInsensitiveOption); + bool isValidContentFilter = regexContent.isValid(); + QStringList filteredByContent; + for (auto fn : filteredByFileName) { + const QString &fileName = fn; + QString filePath = dir.filePath(fileName); + QFile file(filePath); + if (file.open(QIODevice::ReadOnly | QIODevice::Text)) { + QTextStream in(&file); + QString fileContent = in.readAll(); + if (isValidContentFilter){ + if (regexContent.match(fileContent).hasMatch()) { + filteredByContent.append(fileName); + } + } else { + if (fileContent.contains(searchText, Qt::CaseInsensitive)){ + filteredByContent.append(fileName); + } + } + file.close(); + } + } + return filteredByContent; } /** - * Fills up the list with all macro files found in the specified location. + * Fills up the list with macro files found in the specified location + * that have been filtered by both filename and by content */ void DlgMacroExecuteImp::fillUpList() { - // lists all files in macro path - QDir dir(this->macroPath, QLatin1String("*.FCMacro *.py")); - - // fill up with the directory + QStringList filteredByContent = this->filterFiles(this->macroPath); ui->userMacroListBox->clear(); - for (unsigned int i=0; iuserMacroListBox,false); - item->setText(0, dir[i]); + item->setText(0, fn); } QString dirstr = QString::fromStdString(App::Application::getHomePath()) + QString::fromLatin1("Macro"); - dir = QDir(dirstr, QLatin1String("*.FCMacro *.py")); + filteredByContent = this->filterFiles(dirstr); ui->systemMacroListBox->clear(); - if (dir.exists()) { - for (unsigned int i=0; isystemMacroListBox,true); - item->setText(0, dir[i]); - } + for (auto fn : filteredByContent) { + auto item = new MacroItem(ui->systemMacroListBox,true); + item->setText(0, fn); } } + /** * Selects a macro file in the list view. */ @@ -188,6 +262,16 @@ void DlgMacroExecuteImp::onUserMacroListBoxCurrentItemChanged(QTreeWidgetItem* i } } +void DlgMacroExecuteImp::onLineEditFindTextChanged(const QString &text){ + Q_UNUSED(text); + this->fillUpList(); +} + +void DlgMacroExecuteImp::onLineEditFindInFilesTextChanged(const QString &text){ + Q_UNUSED(text); + this->fillUpList(); +} + void DlgMacroExecuteImp::onSystemMacroListBoxCurrentItemChanged(QTreeWidgetItem* item) { if (item) { diff --git a/src/Gui/DlgMacroExecuteImp.h b/src/Gui/DlgMacroExecuteImp.h index 88fe36ceb7..9ad454f77b 100644 --- a/src/Gui/DlgMacroExecuteImp.h +++ b/src/Gui/DlgMacroExecuteImp.h @@ -64,9 +64,12 @@ private: void onUserMacroListBoxCurrentItemChanged(QTreeWidgetItem*); void onSystemMacroListBoxCurrentItemChanged(QTreeWidgetItem*); void onTabMacroWidgetCurrentChanged(int index); + void onLineEditFindTextChanged(const QString&); + void onLineEditFindInFilesTextChanged(const QString&); protected: void fillUpList(); + QStringList filterFiles(const QString&); protected: QString macroPath; diff --git a/src/Gui/DockWindowManager.cpp b/src/Gui/DockWindowManager.cpp index e7864e0da1..9a9f2292d6 100644 --- a/src/Gui/DockWindowManager.cpp +++ b/src/Gui/DockWindowManager.cpp @@ -175,6 +175,20 @@ QWidget* DockWindowManager::getDockWindow(const char* name) const return nullptr; } +/** + * Returns the dock widget by name. + * If it does not exist 0 is returned. + */ +QDockWidget* DockWindowManager::getDockContainer(const char* name) const +{ + for (QList::Iterator it = d->_dockedWindows.begin(); it != d->_dockedWindows.end(); ++it) { + if ((*it)->objectName() == QLatin1String(name)) + return (*it); + } + + return nullptr; +} + /** * Returns a list of all widgets inside the dock windows. */ diff --git a/src/Gui/DockWindowManager.h b/src/Gui/DockWindowManager.h index de314b6af7..366cd96738 100644 --- a/src/Gui/DockWindowManager.h +++ b/src/Gui/DockWindowManager.h @@ -86,6 +86,8 @@ public: /// returned from @ref addDockWindow. If you want to access the QDockWidget /// you get it with parentWidget() of the returned widget. QWidget* getDockWindow(const char* name) const; + /// Returns the QDockWidget container + QDockWidget* getDockContainer(const char* name) const; /// Returns a list of all widgets which set to a QDockWidget. QList getDockWindows() const; /// If the corresponding dock widget isn't visible then activate it diff --git a/src/Gui/EditableDatumLabel.cpp b/src/Gui/EditableDatumLabel.cpp new file mode 100644 index 0000000000..24c88a5e26 --- /dev/null +++ b/src/Gui/EditableDatumLabel.cpp @@ -0,0 +1,324 @@ +/// SPDX-License-Identifier: LGPL-2.1-or-later +/**************************************************************************** + * * + * Copyright (c) 2023 Ondsel * + * * + * This file is part of FreeCAD. * + * * + * FreeCAD is free software: you can redistribute it and/or modify it * + * under the terms of the GNU Lesser General Public License as * + * published by the Free Software Foundation, either version 2.1 of the * + * License, or (at your option) any later version. * + * * + * FreeCAD 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 * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with FreeCAD. If not, see * + * . * + * * + ***************************************************************************/ + +#include "PreCompiled.h" +#ifndef _PreComp_ +# include +# include +# include +# include +#endif // _PreComp_ + +#include +#include +#include + +#include "EditableDatumLabel.h" + + + +using namespace Gui; + + +struct NodeData { + EditableDatumLabel* label; +}; + +EditableDatumLabel::EditableDatumLabel(View3DInventorViewer* view, + const Base::Placement& plc, + SbColor color, + bool autoDistance) + : isSet(false) + , autoDistance(autoDistance) + , autoDistanceReverse(false) + , viewer(view) + , spinBox(nullptr) + , cameraSensor(nullptr) +{ + // NOLINTBEGIN + root = new SoAnnotation; + root->ref(); + root->renderCaching = SoSeparator::OFF; + + transform = new SoTransform(); + transform->ref(); + root->addChild(transform); + + label = new SoDatumLabel(); + label->ref(); + label->string = " "; + label->textColor = color; + label->size.setValue(17); + label->lineWidth = 2.0; + label->useAntialiasing = false; + label->datumtype = SoDatumLabel::DISTANCE; + label->param1 = 0.; + label->param2 = 0.; + if (autoDistance) { + setLabelRecommendedDistance(); + } + root->addChild(label); + + setPlacement(plc); + // NOLINTEND +} + +EditableDatumLabel::~EditableDatumLabel() +{ + deactivate(); + transform->unref(); + root->unref(); + label->unref(); +} + +void EditableDatumLabel::activate() +{ + if (!viewer) { + return; + } + + static_cast(viewer->getSceneGraph())->addChild(root); // NOLINT + + //track camera movements to update spinbox position. + auto info = new NodeData{ this }; + cameraSensor = new SoNodeSensor([](void* data, SoSensor* sensor) { + Q_UNUSED(sensor); + auto info = static_cast(data); + info->label->positionSpinbox(); + if (info->label->autoDistance) { + info->label->setLabelRecommendedDistance(); + } + }, info); + cameraSensor->attach(viewer->getCamera()); +} + +void EditableDatumLabel::deactivate() +{ + stopEdit(); + + if (cameraSensor) { + auto data = static_cast(cameraSensor->getData()); + delete data; + cameraSensor->detach(); + delete cameraSensor; + cameraSensor = nullptr; + } + + if (viewer) { + static_cast(viewer->getSceneGraph())->removeChild(root); // NOLINT + } +} + +void EditableDatumLabel::startEdit(double val, QObject* eventFilteringObj) +{ + QWidget* mdi = viewer->parentWidget(); + + label->string = " "; + + spinBox = new QuantitySpinBox(mdi); + spinBox->setUnit(Base::Unit::Length); + spinBox->setMinimum(-INT_MAX); + spinBox->setMaximum(INT_MAX); + spinBox->setButtonSymbols(QAbstractSpinBox::NoButtons); + spinBox->setKeyboardTracking(false); + if (eventFilteringObj) { + spinBox->installEventFilter(eventFilteringObj); + } + + spinBox->show(); + setSpinboxValue(val); + //Note: adjustSize apparently uses the Min/Max values to set the size. So if we don't set them to INT_MAX, the spinbox are much too big. + spinBox->adjustSize(); + setFocusToSpinbox(); + + connect(spinBox, qOverload(&QuantitySpinBox::valueChanged), + this, [this](double value) { + this->isSet = true; + Q_EMIT this->valueChanged(value); + }); +} + +void EditableDatumLabel::stopEdit() +{ + if (spinBox) { + spinBox->deleteLater(); + spinBox = nullptr; + } +} + +double EditableDatumLabel::getValue() +{ + return spinBox->rawValue(); +} + +void EditableDatumLabel::setSpinboxValue(double val) +{ + if (!spinBox) { + Base::Console().Warning("Spinbox doesn't exist in EditableDatumLabel::setSpinboxValue."); + return; + } + + QSignalBlocker block(spinBox); + spinBox->setValue(val); + positionSpinbox(); + + if (spinBox->hasFocus()) { + spinBox->selectNumber(); + } +} + +void EditableDatumLabel::setFocusToSpinbox() +{ + if (!spinBox) { + Base::Console().Warning("Spinbox doesn't exist in EditableDatumLabel::setFocusToSpinbox."); + return; + } + + spinBox->setFocus(); + spinBox->selectNumber(); +} + +void EditableDatumLabel::positionSpinbox() +{ + if (!spinBox) { + return; + } + + QSize wSize = spinBox->size(); + QPoint pxCoord = viewer->toQPoint(viewer->getPointOnViewport(getTextCenterPoint())); + pxCoord.setX(std::max(pxCoord.x() - wSize.width() / 2, 0)); + pxCoord.setY(std::max(pxCoord.y() - wSize.height() / 2, 0)); + spinBox->move(pxCoord); +} + +SbVec3f EditableDatumLabel::getTextCenterPoint() const +{ + //Here we need the 3d point and not the 2d point as are the SoLabel points. + // First we get the 2D point (on the sketch/image plane) of the middle of the text label. + SbVec3f point2D = label->textOffset; + // Get the translation and rotation values from the transform + SbVec3f translation = transform->translation.getValue(); + SbRotation rotation = transform->rotation.getValue(); + + // Calculate the inverse transformation + SbVec3f invTranslation = -translation; + SbRotation invRotation = rotation.inverse(); + + // Transform the 2D coordinates to 3D + // Plane form + SbVec3f RX(1, 0, 0); + SbVec3f RY(0, 1, 0); + + // move to position of Sketch + invRotation.multVec(RX, RX); + invRotation.multVec(RY, RY); + invRotation.multVec(invTranslation, invTranslation); + + // we use invTranslation as the Base because in setPlacement we set transform->translation using + // placement.getPosition() to fix the Zoffset. But this applies the X & Y translation too. + Base::Vector3d pos(invTranslation[0], invTranslation[1], invTranslation[2]); + Base::Vector3d RXb(RX[0], RX[1], RX[2]); + Base::Vector3d RYb(RY[0], RY[1], RY[2]); + Base::Vector3d P2D(point2D[0], point2D[1], point2D[2]); + P2D.TransformToCoordinateSystem(pos, RXb, RYb); + + return {float(P2D.x), float(P2D.y), float(P2D.z)}; +} + +void EditableDatumLabel::setPlacement(const Base::Placement& plc) +{ + double x{}, y{}, z{}, w{}; // NOLINT + plc.getRotation().getValue(x, y, z, w); + transform->rotation.setValue(x, y, z, w); // NOLINT + + Base::Vector3d pos = plc.getPosition(); + transform->translation.setValue(float(pos.x), float(pos.y), float(pos.z)); + + Base::Vector3d RN(0, 0, 1); + RN = plc.getRotation().multVec(RN); + label->norm.setValue(SbVec3f(float(RN.x), float(RN.y), float(RN.z))); +} + +// NOLINTNEXTLINE +void EditableDatumLabel::setColor(SbColor color) +{ + label->textColor = color; +} + +void EditableDatumLabel::setFocus() +{ + if (spinBox) { + spinBox->selectNumber(); + } +} + +void EditableDatumLabel::setPoints(SbVec3f p1, SbVec3f p2) +{ + label->setPoints(p1, p2); + //TODO: here the position of the spinbox is not going to be center of p1, p2 because the point given by getTextCenterPoint + // is not updated yet. it will be only on redraw so it is actually positioning on previous position. + + positionSpinbox(); + if (autoDistance) { + setLabelRecommendedDistance(); + } +} + +void EditableDatumLabel::setPoints(Base::Vector3d p1, Base::Vector3d p2) +{ + setPoints(SbVec3f(float(p1.x), float(p1.y), float(p1.z)), + SbVec3f(float(p2.x), float(p2.y), float(p2.z))); +} + +// NOLINTNEXTLINE +void EditableDatumLabel::setLabelType(SoDatumLabel::Type type) +{ + label->datumtype = type; +} + +// NOLINTNEXTLINE +void EditableDatumLabel::setLabelDistance(double distance) +{ + label->param1 = float(distance); +} + +void EditableDatumLabel::setLabelRecommendedDistance() +{ + // Takes the 3d view size, and set the label distance to a % of that, such that the distance does not depend on the zoom level. + float width = -1.; + float length = -1.; + viewer->getDimensions(width, length); + + if (width == -1. || length == -1.) { + return; + } + + label->param1 = (autoDistanceReverse ? -1.0F : 1.0F) * (width + length) * 0.03F; // NOLINT +} + +void EditableDatumLabel::setLabelAutoDistanceReverse(bool val) +{ + autoDistanceReverse = val; +} + +#include "moc_EditableDatumLabel.cpp" diff --git a/src/Gui/EditableDatumLabel.h b/src/Gui/EditableDatumLabel.h new file mode 100644 index 0000000000..f0f64f4cf1 --- /dev/null +++ b/src/Gui/EditableDatumLabel.h @@ -0,0 +1,95 @@ + /// SPDX-License-Identifier: LGPL-2.1-or-later + /**************************************************************************** + * * + * Copyright (c) 2023 Ondsel * + * * + * This file is part of FreeCAD. * + * * + * FreeCAD is free software: you can redistribute it and/or modify it * + * under the terms of the GNU Lesser General Public License as * + * published by the Free Software Foundation, either version 2.1 of the * + * License, or (at your option) any later version. * + * * + * FreeCAD 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 * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with FreeCAD. If not, see * + * . * + * * + ***************************************************************************/ + +#ifndef GUI_EDITABLEDATUMLABEL_H +#define GUI_EDITABLEDATUMLABEL_H + +#include +#include + +#include "SoDatumLabel.h" + +#include + +class SoNodeSensor; +class SoTransform; + +namespace Gui { + +class View3DInventorViewer; + + +class GuiExport EditableDatumLabel : public QObject +{ + Q_OBJECT + Q_DISABLE_COPY(EditableDatumLabel) + +public: + EditableDatumLabel(View3DInventorViewer* view, const Base::Placement& plc, SbColor color, bool autoDistance = false); + ~EditableDatumLabel() override; + + void activate(); + void deactivate(); + + void startEdit(double val, QObject* eventFilteringObj = nullptr); + void stopEdit(); + double getValue(); + void setSpinboxValue(double val); + void setPlacement(const Base::Placement& plc); + void setColor(SbColor color); + void setFocus(); + void setPoints(SbVec3f p1, SbVec3f p2); + void setPoints(Base::Vector3d p1, Base::Vector3d p2); + void setFocusToSpinbox(); + void setLabelType(SoDatumLabel::Type type); + void setLabelDistance(double distance); + void setLabelRecommendedDistance(); + void setLabelAutoDistanceReverse(bool val); + + // NOLINTBEGIN + SoDatumLabel* label; + bool isSet; + bool autoDistance; + bool autoDistanceReverse; + // NOLINTEND + +Q_SIGNALS: + void valueChanged(double val); + +private: + void positionSpinbox(); + SbVec3f getTextCenterPoint() const; + +private: + SoSeparator* root; + SoTransform* transform; + View3DInventorViewer* viewer; + QuantitySpinBox* spinBox; + SoNodeSensor* cameraSensor; + SbVec3f midpos; +}; + +} + + +#endif // GUI_EDITABLEDATUMLABEL_H diff --git a/src/Gui/FreeCADGuiInit.py b/src/Gui/FreeCADGuiInit.py index 84cebe5689..5f176d78ac 100644 --- a/src/Gui/FreeCADGuiInit.py +++ b/src/Gui/FreeCADGuiInit.py @@ -132,8 +132,8 @@ def InitApplications(): InstallFile = os.path.join(Dir,"InitGui.py") if os.path.exists(InstallFile): try: - with open(file=InstallFile, encoding="utf-8") as f: - exec(f.read()) + with open(InstallFile, 'rt', encoding='utf-8') as f: + exec(compile(f.read(), InstallFile, 'exec')) except Exception as inst: Log('Init: Initializing ' + Dir + '... failed\n') Log('-'*100+'\n') diff --git a/src/Gui/MainWindow.cpp b/src/Gui/MainWindow.cpp index fc4d9346d8..a162e7e645 100644 --- a/src/Gui/MainWindow.cpp +++ b/src/Gui/MainWindow.cpp @@ -469,15 +469,18 @@ void MainWindow::setupDockWindows() if (ht != config.end()) hiddenDockWindows = ht->second; - bool treeView = setupTreeView(hiddenDockWindows); - bool propertyView = setupPropertyView(hiddenDockWindows); + setupTreeView(hiddenDockWindows); + setupPropertyView(hiddenDockWindows); + setupTaskView(hiddenDockWindows); setupSelectionView(hiddenDockWindows); - setupComboView(hiddenDockWindows, !treeView || !propertyView); + setupComboView(hiddenDockWindows); // Report view must be created before PythonConsole! setupReportView(hiddenDockWindows); setupPythonConsole(hiddenDockWindows); setupDAGView(hiddenDockWindows); + + this->setTabPosition(Qt::LeftDockWidgetArea, QTabWidget::North); } bool MainWindow::setupTreeView(const std::string& hiddenDockWindows) @@ -489,7 +492,7 @@ bool MainWindow::setupTreeView(const std::string& hiddenDockWindows) bool enabled = group->GetBool("Enabled", true); if (enabled != group->GetBool("Enabled", false)) { enabled = App::GetApplication().GetUserParameter().GetGroup("BaseApp") - ->GetGroup("MainWindow")->GetGroup("DockWindows")->GetBool("Std_TreeView",false); + ->GetGroup("MainWindow")->GetGroup("DockWindows")->GetBool("Std_TreeView", true); } group->SetBool("Enabled", enabled); //ensure entry exists. if (enabled) { @@ -507,6 +510,23 @@ bool MainWindow::setupTreeView(const std::string& hiddenDockWindows) return false; } +bool MainWindow::setupTaskView(const std::string& hiddenDockWindows) +{ + // Task view + if (hiddenDockWindows.find("Std_TaskView") == std::string::npos) { + auto taskView = new Gui::TaskView::TaskView(this); + taskView->setObjectName + (QString::fromLatin1(QT_TRANSLATE_NOOP("QDockWidget","Tasks"))); + taskView->setMinimumWidth(210); + + DockWindowManager* pDockMgr = DockWindowManager::instance(); + pDockMgr->registerDockWindow("Std_TaskView", taskView); + return true; + } + + return false; +} + bool MainWindow::setupPropertyView(const std::string& hiddenDockWindows) { // Property view @@ -517,7 +537,7 @@ bool MainWindow::setupPropertyView(const std::string& hiddenDockWindows) bool enabled = group->GetBool("Enabled", true); if (enabled != group->GetBool("Enabled", false)) { enabled = App::GetApplication().GetUserParameter().GetGroup("BaseApp") - ->GetGroup("MainWindow")->GetGroup("DockWindows")->GetBool("Std_PropertyView",false); + ->GetGroup("MainWindow")->GetGroup("DockWindows")->GetBool("Std_PropertyView", true); } group->SetBool("Enabled", enabled); //ensure entry exists. if (enabled) { @@ -552,23 +572,23 @@ bool MainWindow::setupSelectionView(const std::string& hiddenDockWindows) return false; } -bool MainWindow::setupComboView(const std::string& hiddenDockWindows, bool enable) +bool MainWindow::setupComboView(const std::string& hiddenDockWindows) { // Combo view if (hiddenDockWindows.find("Std_ComboView") == std::string::npos) { - if (!enable) { - ParameterGrp::handle group = App::GetApplication().GetUserParameter(). - GetGroup("BaseApp")->GetGroup("Preferences")->GetGroup("DockWindows")->GetGroup("ComboView"); - enable = group->GetBool("Enabled", true); + ParameterGrp::handle group = App::GetApplication().GetUserParameter(). + GetGroup("BaseApp")->GetGroup("Preferences")->GetGroup("DockWindows")->GetGroup("ComboView"); + bool enable = group->GetBool("Enabled", false); + + if (enable) { + auto pcComboView = new ComboView(nullptr, this); + pcComboView->setObjectName(QString::fromLatin1(QT_TRANSLATE_NOOP("QDockWidget", "Model"))); + pcComboView->setMinimumWidth(150); + + DockWindowManager* pDockMgr = DockWindowManager::instance(); + pDockMgr->registerDockWindow("Std_ComboView", pcComboView); + return true; } - - auto pcComboView = new ComboView(enable, nullptr, this); - pcComboView->setObjectName(QString::fromLatin1(QT_TRANSLATE_NOOP("QDockWidget","Combo View"))); - pcComboView->setMinimumWidth(150); - - DockWindowManager* pDockMgr = DockWindowManager::instance(); - pDockMgr->registerDockWindow("Std_ComboView", pcComboView); - return true; } return false; diff --git a/src/Gui/MainWindow.h b/src/Gui/MainWindow.h index 9ac6e7b8b5..9b8405a4fb 100644 --- a/src/Gui/MainWindow.h +++ b/src/Gui/MainWindow.h @@ -284,9 +284,10 @@ protected: private: void setupDockWindows(); bool setupTreeView(const std::string&); + bool setupTaskView(const std::string&); bool setupPropertyView(const std::string&); bool setupSelectionView(const std::string&); - bool setupComboView(const std::string&, bool enable); + bool setupComboView(const std::string&); bool setupDAGView(const std::string&); bool setupReportView(const std::string&); bool setupPythonConsole(const std::string&); diff --git a/src/Gui/PreferencePages/DlgSettingsGeneral.cpp b/src/Gui/PreferencePages/DlgSettingsGeneral.cpp index 363445d93e..9ed9ebf963 100644 --- a/src/Gui/PreferencePages/DlgSettingsGeneral.cpp +++ b/src/Gui/PreferencePages/DlgSettingsGeneral.cpp @@ -243,23 +243,7 @@ void DlgSettingsGeneral::saveSettings() int blinkTime{hGrp->GetBool("EnableCursorBlinking", true) ? -1 : 0}; qApp->setCursorFlashTime(blinkTime); - hGrp = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/DockWindows"); - bool treeView=false; - bool propertyView=false; - bool comboView=true; - switch(ui->treeMode->currentIndex()) { - case 1: - treeView = propertyView = true; - comboView = false; - break; - case 2: - comboView = true; - treeView = propertyView = true; - break; - } - hGrp->GetGroup("ComboView")->SetBool("Enabled",comboView); - hGrp->GetGroup("TreeView")->SetBool("Enabled",treeView); - hGrp->GetGroup("PropertyView")->SetBool("Enabled",propertyView); + saveDockWindowVisibility(); hGrp = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/MainWindow"); hGrp->SetBool("TiledBackground", ui->tiledBackground->isChecked()); @@ -365,20 +349,7 @@ void DlgSettingsGeneral::loadSettings() ui->toolbarIconSize->setCurrentIndex(index); //TreeMode combobox setup. - ui->treeMode->clear(); - ui->treeMode->addItem(tr("Combo View")); - ui->treeMode->addItem(tr("TreeView and PropertyView")); - ui->treeMode->addItem(tr("Both")); - - hGrp = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/DockWindows"); - bool propertyView = hGrp->GetGroup("PropertyView")->GetBool("Enabled",false); - bool treeView = hGrp->GetGroup("TreeView")->GetBool("Enabled",false); - bool comboView = hGrp->GetGroup("ComboView")->GetBool("Enabled",true); - index = 0; - if(propertyView || treeView) { - index = comboView?2:1; - } - ui->treeMode->setCurrentIndex(index); + loadDockWindowVisibility(); hGrp = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/MainWindow"); ui->tiledBackground->setChecked(hGrp->GetBool("TiledBackground", false)); @@ -464,6 +435,48 @@ void DlgSettingsGeneral::changeEvent(QEvent *event) } } +void DlgSettingsGeneral::saveDockWindowVisibility() +{ + auto hGrp = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/DockWindows"); + bool treeView = hGrp->GetGroup("TreeView")->GetBool("Enabled", true); + bool propertyView = hGrp->GetGroup("PropertyView")->GetBool("Enabled", true); + bool comboView = hGrp->GetGroup("ComboView")->GetBool("Enabled", false); + switch (ui->treeMode->currentIndex()) { + case 0: + comboView = true; + treeView = propertyView = false; + break; + case 1: + treeView = propertyView = true; + comboView = false; + break; + } + + hGrp->GetGroup("ComboView")->SetBool("Enabled", comboView); + hGrp->GetGroup("TreeView")->SetBool("Enabled", treeView); + hGrp->GetGroup("PropertyView")->SetBool("Enabled", propertyView); +} + +void DlgSettingsGeneral::loadDockWindowVisibility() +{ + ui->treeMode->clear(); + ui->treeMode->addItem(tr("Combo View")); + ui->treeMode->addItem(tr("TreeView and PropertyView")); + + auto hGrp = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/DockWindows"); + bool propertyView = hGrp->GetGroup("PropertyView")->GetBool("Enabled", true); + bool treeView = hGrp->GetGroup("TreeView")->GetBool("Enabled", true); + bool comboView = hGrp->GetGroup("ComboView")->GetBool("Enabled", false); + int index = -1; + if (propertyView || treeView) { + index = 1; + } + else if (comboView) { + index = 0; + } + ui->treeMode->setCurrentIndex(index); +} + void DlgSettingsGeneral::recreatePreferencePackMenu() { ui->PreferencePacks->setRowCount(0); // Begin by clearing whatever is there diff --git a/src/Gui/PreferencePages/DlgSettingsGeneral.h b/src/Gui/PreferencePages/DlgSettingsGeneral.h index 7e7b7ba55b..6713250165 100644 --- a/src/Gui/PreferencePages/DlgSettingsGeneral.h +++ b/src/Gui/PreferencePages/DlgSettingsGeneral.h @@ -25,7 +25,7 @@ #ifndef GUI_DIALOG_DLGSETTINGSGENERAL_H #define GUI_DIALOG_DLGSETTINGSGENERAL_H - + #include #include #include @@ -73,6 +73,8 @@ public Q_SLOTS: void on_checkBox_projectUnitSystemIgnore_stateChanged(int state); private: + void saveDockWindowVisibility(); + void loadDockWindowVisibility(); void setRecentFileSize(); void saveAsNewPreferencePack(); void revertToSavedConfig(); @@ -92,4 +94,4 @@ private: } // namespace Dialog } // namespace Gui -#endif // GUI_DIALOG_DLGSETTINGSGENERAL_H +#endif // GUI_DIALOG_DLGSETTINGSGENERAL_H diff --git a/src/Gui/SoDatumLabel.cpp b/src/Gui/SoDatumLabel.cpp index 336b377ec7..340602bcec 100644 --- a/src/Gui/SoDatumLabel.cpp +++ b/src/Gui/SoDatumLabel.cpp @@ -97,6 +97,7 @@ SoDatumLabel::SoDatumLabel() this->imgWidth = 0; this->imgHeight = 0; this->glimagevalid = false; + this->textOffset = SbVec3f(0.f, 0.f, 0.f); } void SoDatumLabel::drawImage() @@ -433,19 +434,11 @@ private: void SoDatumLabel::computeBBox(SoAction * action, SbBox3f &box, SbVec3f ¢er) { - if (!this->bbox.isEmpty()) { - // Set the bounding box using stored parameters - box.setBounds(this->bbox.getMin(),this->bbox.getMax() ); - SbVec3f bbcenter = this->bbox.getCenter(); - center.setValue(bbcenter[0], bbcenter[1], bbcenter[2]); - } - else { - SoState *state = action->getState(); - float scale = getScaleFactor(state); + SoState *state = action->getState(); + float scale = getScaleFactor(state); - DatumLabelBox datumBox(scale, this); - datumBox.computeBBox(box, center); - } + DatumLabelBox datumBox(scale, this); + datumBox.computeBBox(box, center); } void SoDatumLabel::generateDistancePrimitives(SoAction * action, const SbVec3f& p1, const SbVec3f& p2) @@ -485,7 +478,7 @@ void SoDatumLabel::generateDistancePrimitives(SoAction * action, const SbVec3f& img3 = SbVec3f((img3[0] * c) - (img3[1] * s), (img3[0] * s) + (img3[1] * c), 0.f); img4 = SbVec3f((img4[0] * c) - (img4[1] * s), (img4[0] * s) + (img4[1] * c), 0.f); - SbVec3f textOffset = midpos + normal * length + dir * length2; + textOffset = midpos + normal * length + dir * length2; img1 += textOffset; img2 += textOffset; @@ -539,7 +532,7 @@ void SoDatumLabel::generateDiameterPrimitives(SoAction * action, const SbVec3f& img3 = SbVec3f((img3[0] * c) - (img3[1] * s), (img3[0] * s) + (img3[1] * c), 0.f); img4 = SbVec3f((img4[0] * c) - (img4[1] * s), (img4[0] * s) + (img4[1] * c), 0.f); - SbVec3f textOffset = pos; + textOffset = pos; img1 += textOffset; img2 += textOffset; @@ -585,7 +578,7 @@ void SoDatumLabel::generateAnglePrimitives(SoAction * action, const SbVec3f& p0) // p0 - vector for angle intersect SbVec3f v0(cos(startangle+range/2),sin(startangle+range/2),0); - SbVec3f textOffset = p0 + v0 * r; + textOffset = p0 + v0 * r; SbVec3f img1 = SbVec3f(-this->imgWidth / 2, -this->imgHeight / 2, 0.f); SbVec3f img2 = SbVec3f(-this->imgWidth / 2, this->imgHeight / 2, 0.f); @@ -821,8 +814,6 @@ void SoDatumLabel::GLRender(SoGLRenderAction * action) // Position for Datum Text Label float angle = 0; - SbVec3f textOffset; - // Get the colour const SbColor& t = textColor.getValue(); @@ -913,13 +904,13 @@ void SoDatumLabel::GLRender(SoGLRenderAction * action) } // Perp Lines glBegin(GL_LINES); - if (length != 0.) { - glVertex2f(p1[0], p1[1]); - glVertex2f(perp1[0], perp1[1]); + if (length != 0.) { + glVertex2f(p1[0], p1[1]); + glVertex2f(perp1[0], perp1[1]); - glVertex2f(p2[0], p2[1]); - glVertex2f(perp2[0], perp2[1]); - } + glVertex2f(p2[0], p2[1]); + glVertex2f(perp2[0], perp2[1]); + } glVertex2f(par1[0], par1[1]); glVertex2f(par2[0], par2[1]); @@ -946,30 +937,6 @@ void SoDatumLabel::GLRender(SoGLRenderAction * action) glVertex2f(ar3[0], ar3[1]); glVertex2f(ar4[0], ar4[1]); glEnd(); - - // BOUNDING BOX CALCULATION - IMPORTANT - // Finds the mins and maxes - std::vector corners; - corners.push_back(p1); - corners.push_back(p2); - corners.push_back(perp1); - corners.push_back(perp2); - - // Make sure that the label is inside the bounding box - corners.push_back(textOffset + dir * (this->imgWidth / 2 + margin) + normal * (srch + margin)); - corners.push_back(textOffset - dir * (this->imgWidth / 2 + margin) + normal * (srch + margin)); - corners.push_back(textOffset + dir * (this->imgWidth / 2 + margin) - normal * margin); - corners.push_back(textOffset - dir * (this->imgWidth / 2 + margin) - normal * margin); - - float minX = p1[0], minY = p1[1], maxX = p1[0] , maxY = p1[1]; - for (SbVec3f it : corners) { - minX = (it[0] < minX) ? it[0] : minX; - minY = (it[1] < minY) ? it[1] : minY; - maxX = (it[0] > maxX) ? it[0] : maxX; - maxY = (it[1] > maxY) ? it[1] : maxY; - } - //Store the bounding box - this->bbox.setBounds(SbVec3f(minX, minY, 0.f), SbVec3f (maxX, maxY, 0.f)); } else if (this->datumtype.getValue() == RADIUS || this->datumtype.getValue() == DIAMETER) { // Get the Points @@ -1039,23 +1006,6 @@ void SoDatumLabel::GLRender(SoGLRenderAction * action) } - // BOUNDING BOX CALCULATION - IMPORTANT - // Finds the mins and maxes - std::vector corners; - corners.push_back(p1); - corners.push_back(p2); - corners.push_back(pnt1); - corners.push_back(pnt2); - - float minX = p1[0], minY = p1[1], maxX = p1[0] , maxY = p1[1]; - for (SbVec3f it : corners) { - minX = (it[0] < minX) ? it[0] : minX; - minY = (it[1] < minY) ? it[1] : minY; - maxX = (it[0] > maxX) ? it[0] : maxX; - maxY = (it[1] > maxY) ? it[1] : maxY; - } - //Store the bounding box - this->bbox.setBounds(SbVec3f(minX, minY, 0.f), SbVec3f (maxX, maxY, 0.f)); } else if (this->datumtype.getValue() == ANGLE) { // Only the angle intersection point is needed SbVec3f p0 = points[0]; @@ -1125,39 +1075,6 @@ void SoDatumLabel::GLRender(SoGLRenderAction * action) glVertex2f(pnt4[0],pnt4[1]); glEnd(); - // BOUNDING BOX CALCULATION - IMPORTANT - // Finds the mins and maxes - // We may need to include the text position too - - SbVec3f img1 = SbVec3f(-this->imgWidth / 2, -this->imgHeight / 2, 0.f); - SbVec3f img2 = SbVec3f(-this->imgWidth / 2, this->imgHeight / 2, 0.f); - SbVec3f img3 = SbVec3f( this->imgWidth / 2, -this->imgHeight / 2, 0.f); - SbVec3f img4 = SbVec3f( this->imgWidth / 2, this->imgHeight / 2, 0.f); - - img1 += textOffset; - img2 += textOffset; - img3 += textOffset; - img4 += textOffset; - - std::vector corners; - corners.push_back(pnt1); - corners.push_back(pnt2); - corners.push_back(pnt3); - corners.push_back(pnt4); - corners.push_back(img1); - corners.push_back(img2); - corners.push_back(img3); - corners.push_back(img4); - - float minX = pnt1[0], minY = pnt1[1], maxX = pnt1[0] , maxY = pnt1[1]; - for (SbVec3f it : corners) { - minX = (it[0] < minX) ? it[0] : minX; - minY = (it[1] < minY) ? it[1] : minY; - maxX = (it[0] > maxX) ? it[0] : maxX; - maxY = (it[1] > maxY) ? it[1] : maxY; - } - //Store the bounding box - this->bbox.setBounds(SbVec3f(minX, minY, 0.f), SbVec3f (maxX, maxY, 0.f)); } else if (this->datumtype.getValue() == SYMMETRIC) { SbVec3f p1 = points[0]; @@ -1200,22 +1117,6 @@ void SoDatumLabel::GLRender(SoGLRenderAction * action) glVertex3f(ar3[0], ar3[1], ZCONSTR); glVertex3f(ar5[0], ar5[1], ZCONSTR); glEnd(); - - // BOUNDING BOX CALCULATION - IMPORTANT - // Finds the mins and maxes - std::vector corners; - corners.push_back(p1); - corners.push_back(p2); - - float minX = p1[0], minY = p1[1], maxX = p1[0] , maxY = p1[1]; - for (SbVec3f it : corners) { - minX = (it[0] < minX) ? it[0] : minX; - minY = (it[1] < minY) ? it[1] : minY; - maxX = (it[0] > maxX) ? it[0] : maxX; - maxY = (it[1] > maxY) ? it[1] : maxY; - } - //Store the bounding box - this->bbox.setBounds(SbVec3f(minX, minY, 0.f), SbVec3f (maxX, maxY, 0.f)); } if (hasText) { diff --git a/src/Gui/SoDatumLabel.h b/src/Gui/SoDatumLabel.h index 5ae2621cda..7ee81977d8 100644 --- a/src/Gui/SoDatumLabel.h +++ b/src/Gui/SoDatumLabel.h @@ -77,6 +77,7 @@ public: SoSFImage image; SoSFFloat lineWidth; bool useAntialiasing; + SbVec3f textOffset; protected: ~SoDatumLabel() override = default; @@ -94,7 +95,6 @@ private: private: void drawImage(); - SbBox3f bbox; float imgWidth; float imgHeight; bool glimagevalid; diff --git a/src/Gui/SoFCCSysDragger.cpp b/src/Gui/SoFCCSysDragger.cpp index 038d09f22f..a248e26455 100644 --- a/src/Gui/SoFCCSysDragger.cpp +++ b/src/Gui/SoFCCSysDragger.cpp @@ -27,11 +27,15 @@ #include #include #include +#include +#include +#include #include #include #include #include #include +#include #include #include #include @@ -45,6 +49,8 @@ #endif #include +#include "Gui/ViewParams.h" +#include "App/Color.h" #include "SoFCCSysDragger.h" #include "MainWindow.h" @@ -164,10 +170,14 @@ SoGroup* TDragger::buildGeometry() //cylinder float cylinderHeight = 10.0; - float cylinderRadius = 0.2f; + float cylinderRadius = 0.1f; auto cylinderSeparator = new SoSeparator(); root->addChild(cylinderSeparator); + auto cylinderLightModel = new SoLightModel(); + cylinderLightModel->model = SoLightModel::BASE_COLOR; + cylinderSeparator->addChild(cylinderLightModel); + auto cylinderTranslation = new SoTranslation(); cylinderTranslation->translation.setValue(0.0, cylinderHeight / 2.0, 0.0); cylinderSeparator->addChild(cylinderTranslation); @@ -178,11 +188,15 @@ SoGroup* TDragger::buildGeometry() cylinderSeparator->addChild(cylinder); //cone - float coneBottomRadius = 1.0; - float coneHeight = 2.0; + float coneBottomRadius = 0.8; + float coneHeight = 2.5; auto coneSeparator = new SoSeparator(); root->addChild(coneSeparator); + auto coneLightModel = new SoLightModel(); + coneLightModel->model = SoLightModel::BASE_COLOR; + coneSeparator->addChild(coneLightModel); + auto pickStyle = new SoPickStyle(); pickStyle->style.setValue(SoPickStyle::SHAPE); pickStyle->setOverride(TRUE); @@ -357,13 +371,292 @@ SbVec3f TDragger::roundTranslation(const SbVec3f &vecIn, float incrementIn) translationIncrementCount.setValue(yCount); SbVec3f out; - out[0] = 0.0; + out[0] = 0; out[1] = static_cast(yCount) * incrementIn; out[2] = 0.0; return out; } + +SO_KIT_SOURCE(TPlanarDragger) + +void TPlanarDragger::initClass() +{ + SO_KIT_INIT_CLASS(TPlanarDragger, SoDragger, "Dragger"); +} + +TPlanarDragger::TPlanarDragger() +{ + SO_KIT_CONSTRUCTOR(TPlanarDragger); + + SO_KIT_ADD_CATALOG_ENTRY(planarTranslatorSwitch, SoSwitch, TRUE, geomSeparator, "", TRUE); + SO_KIT_ADD_CATALOG_ENTRY(planarTranslator, SoSeparator, TRUE, planarTranslatorSwitch, "", TRUE); + SO_KIT_ADD_CATALOG_ENTRY(planarTranslatorActive, SoSeparator, TRUE, planarTranslatorSwitch, "", TRUE); + + if (SO_KIT_IS_FIRST_INSTANCE()) + buildFirstInstance(); + + SO_KIT_ADD_FIELD(translation, (0.0, 0.0, 0.0)); + SO_KIT_ADD_FIELD(translationIncrement, (1.0)); + SO_KIT_ADD_FIELD(translationIncrementXCount, (0)); + SO_KIT_ADD_FIELD(translationIncrementYCount, (0)); + SO_KIT_ADD_FIELD(autoScaleResult, (1.0)); + + SO_KIT_INIT_INSTANCE(); + + // initialize default parts. + // first is from 'SO_KIT_CATALOG_ENTRY_HEADER' macro + // second is unique name from buildFirstInstance(). + this->setPartAsDefault("planarTranslator", "CSysDynamics_TPlanarDragger_Translator"); + this->setPartAsDefault("planarTranslatorActive", "CSysDynamics_TPlanarDragger_TranslatorActive"); + + SoSwitch *sw = SO_GET_ANY_PART(this, "planarTranslatorSwitch", SoSwitch); + SoInteractionKit::setSwitchValue(sw, 0); + + this->addStartCallback(&TPlanarDragger::startCB); + this->addMotionCallback(&TPlanarDragger::motionCB); + this->addFinishCallback(&TPlanarDragger::finishCB); + + addValueChangedCallback(&TPlanarDragger::valueChangedCB); + + fieldSensor.setFunction(&TPlanarDragger::fieldSensorCB); + fieldSensor.setData(this); + fieldSensor.setPriority(0); + + this->setUpConnections(TRUE, TRUE); +} + +TPlanarDragger::~TPlanarDragger() +{ + fieldSensor.setData(nullptr); + fieldSensor.detach(); + + this->removeStartCallback(&TPlanarDragger::startCB); + this->removeMotionCallback(&TPlanarDragger::motionCB); + this->removeFinishCallback(&TPlanarDragger::finishCB); + removeValueChangedCallback(&TPlanarDragger::valueChangedCB); +} + +void TPlanarDragger::buildFirstInstance() +{ + SoGroup *geometryGroup = buildGeometry(); + + auto localTranslator = new SoSeparator(); + localTranslator->setName("CSysDynamics_TPlanarDragger_Translator"); + localTranslator->addChild(geometryGroup); + SoFCDB::getStorage()->addChild(localTranslator); + + auto localTranslatorActive = new SoSeparator(); + localTranslatorActive->setName("CSysDynamics_TPlanarDragger_TranslatorActive"); + auto colorActive = new SoBaseColor(); + colorActive->rgb.setValue(1.0, 1.0, 0.0); + localTranslatorActive->addChild(colorActive); + localTranslatorActive->addChild(geometryGroup); + SoFCDB::getStorage()->addChild(localTranslatorActive); +} + +SoGroup* TPlanarDragger::buildGeometry() +{ + auto root = new SoGroup(); + + float cubeWidthHeight = 2.0; + float cubeDepth = 0.1f; + + auto translation = new SoTranslation(); + translation->translation.setValue(cubeWidthHeight + 0.15, cubeWidthHeight + 0.15, 0.0); + root->addChild(translation); + + auto pickStyle = new SoPickStyle(); + pickStyle->style.setValue(SoPickStyle::SHAPE); + pickStyle->setOverride(TRUE); + root->addChild(pickStyle); + + auto lightModel = new SoLightModel(); + lightModel->model = SoLightModel::BASE_COLOR; + root->addChild(lightModel); + + auto cube = new SoCube(); + cube->width.setValue(cubeWidthHeight); + cube->height.setValue(cubeWidthHeight); + cube->depth.setValue(cubeDepth); + root->addChild(cube); + + return root; +} + +void TPlanarDragger::startCB(void *, SoDragger *d) +{ + auto sudoThis = static_cast(d); + assert(sudoThis); + sudoThis->dragStart(); +} + +void TPlanarDragger::motionCB(void *, SoDragger *d) +{ + auto sudoThis = static_cast(d); + assert(sudoThis); + sudoThis->drag(); +} + +void TPlanarDragger::finishCB(void *, SoDragger *d) +{ + auto sudoThis = static_cast(d); + assert(sudoThis); + sudoThis->dragFinish(); +} + +void TPlanarDragger::fieldSensorCB(void *f, SoSensor *) +{ + auto sudoThis = static_cast(f); + + if(!f) + return; + + SbMatrix matrix = sudoThis->getMotionMatrix(); // clazy:exclude=rule-of-two-soft + sudoThis->workFieldsIntoTransform(matrix); + sudoThis->setMotionMatrix(matrix); +} + +void TPlanarDragger::valueChangedCB(void *, SoDragger *d) +{ + auto sudoThis = dynamic_cast(d); + assert(sudoThis); + SbMatrix matrix = sudoThis->getMotionMatrix(); // clazy:exclude=rule-of-two-soft + + //all this just to get the translation? + SbVec3f trans, scaleDummy; + SbRotation rotationDummy, scaleOrientationDummy; + matrix.getTransform(trans, rotationDummy, scaleDummy, scaleOrientationDummy); + + sudoThis->fieldSensor.detach(); + if (sudoThis->translation.getValue() != trans) + sudoThis->translation = trans; + sudoThis->fieldSensor.attach(&sudoThis->translation); +} + +void TPlanarDragger::dragStart() +{ + SoSwitch *sw; + sw = SO_GET_ANY_PART(this, "planarTranslatorSwitch", SoSwitch); + SoInteractionKit::setSwitchValue(sw, 1); + + projector.setViewVolume(this->getViewVolume()); + projector.setWorkingSpace(this->getLocalToWorldMatrix()); + projector.setPlane(SbPlane(SbVec3f(0.0, 0.0, 0.0), SbVec3f(1.0, 0.0, 0.0), SbVec3f(0.0, 1.0, 0.0))); + SbVec3f hitPoint = projector.project(getNormalizedLocaterPosition()); + + SbMatrix localToWorld = getLocalToWorldMatrix(); + localToWorld.multVecMatrix(hitPoint, hitPoint); + setStartingPoint((hitPoint)); + + translationIncrementXCount.setValue(0); + translationIncrementYCount.setValue(0); +} +void TPlanarDragger::drag() +{ + projector.setViewVolume(this->getViewVolume()); + projector.setWorkingSpace(this->getLocalToWorldMatrix()); + + SbVec3f hitPoint = projector.project(getNormalizedLocaterPosition()); + SbVec3f startingPoint = getLocalStartingPoint(); + SbVec3f localMovement = hitPoint - startingPoint; + + //scale the increment to match local space. + float scaledIncrement = static_cast(translationIncrement.getValue()) / autoScaleResult.getValue(); + + localMovement = roundTranslation(localMovement, scaledIncrement); + //when the movement vector is null either the appendTranslation or + //the setMotionMatrix doesn't work. either way it stops translating + //back to its initial starting point. + if (localMovement.equals(SbVec3f(0.0, 0.0, 0.0), 0.00001f)) + { + setMotionMatrix(getStartMotionMatrix()); + //don't know why I need the following but if I don't have it + //it won't return to original position. + this->valueChanged(); + } + else + setMotionMatrix(appendTranslation(getStartMotionMatrix(), localMovement)); + + Base::Quantity quantityX( + static_cast(translationIncrementXCount.getValue()) * translationIncrement.getValue(), Base::Unit::Length); + Base::Quantity quantityY( + static_cast(translationIncrementYCount.getValue()) * translationIncrement.getValue(), Base::Unit::Length); + + QString message = QString::fromLatin1("%1 %2, %3") + .arg(QObject::tr("Translation XY:"), quantityX.getUserString(), quantityY.getUserString()); + getMainWindow()->showMessage(message, 3000); +} + +void TPlanarDragger::dragFinish() +{ + SoSwitch *sw; + sw = SO_GET_ANY_PART(this, "planarTranslatorSwitch", SoSwitch); + SoInteractionKit::setSwitchValue(sw, 0); +} + +SbBool TPlanarDragger::setUpConnections(SbBool onoff, SbBool doitalways) +{ + if (!doitalways && this->connectionsSetUp == onoff) + return onoff; + + SbBool oldval = this->connectionsSetUp; + + if (onoff) + { + inherited::setUpConnections(onoff, doitalways); + TPlanarDragger::fieldSensorCB(this, nullptr); + if (this->fieldSensor.getAttachedField() != &this->translation) + this->fieldSensor.attach(&this->translation); + } + else + { + if (this->fieldSensor.getAttachedField()) + this->fieldSensor.detach(); + inherited::setUpConnections(onoff, doitalways); + } + this->connectionsSetUp = onoff; + return oldval; +} + +SbVec3f TPlanarDragger::roundTranslation(const SbVec3f &vecIn, float incrementIn) +{ + int xCount = 0; + float xValue = vecIn[0]; + + if (fabs(xValue) > (incrementIn / 2.0)) + { + xCount = static_cast(xValue / incrementIn); + float remainder = fmod(xValue, incrementIn); + if (remainder >= (incrementIn / 2.0)) + xCount++; + } + + translationIncrementXCount.setValue(xCount); + + int yCount = 0; + float yValue = vecIn[1]; + + if (fabs(yValue) > (incrementIn / 2.0)) + { + yCount = static_cast(yValue / incrementIn); + float remainder = fmod(yValue, incrementIn); + if (remainder >= (incrementIn / 2.0)) + yCount++; + } + + translationIncrementYCount.setValue(yCount); + + SbVec3f out; + out[0] = static_cast(xCount) * incrementIn; + out[1] = static_cast(yCount) * incrementIn; + out[2] = 0.0; + + return out; +} + + SO_KIT_SOURCE(RDragger) void RDragger::initClass() @@ -448,7 +741,7 @@ SoGroup* RDragger::buildGeometry() //arc auto coordinates = new SoCoordinate3(); - unsigned int segments = 6; + unsigned int segments = 15; float angleIncrement = static_cast(M_PI / 2.0) / static_cast(segments); SbRotation rotation(SbVec3f(0.0, 0.0, 1.0), angleIncrement); @@ -460,6 +753,14 @@ SoGroup* RDragger::buildGeometry() } root->addChild(coordinates); + auto drawStyle = new SoDrawStyle(); + drawStyle->lineWidth = 4.0; + root->addChild(drawStyle); + + auto lightModel = new SoLightModel(); + lightModel->model = SoLightModel::BASE_COLOR; + root->addChild(lightModel); + auto lineSet = new SoLineSet(); lineSet->numVertices.setValue(segments + 1); root->addChild(lineSet); @@ -478,7 +779,7 @@ SoGroup* RDragger::buildGeometry() root->addChild(sphereTranslation); auto sphere = new SoSphere(); - sphere->radius.setValue(1.0); + sphere->radius.setValue(0.8); root->addChild(sphere); return root; @@ -656,6 +957,7 @@ SO_KIT_SOURCE(SoFCCSysDragger) void SoFCCSysDragger::initClass() { TDragger::initClass(); + TPlanarDragger::initClass(); RDragger::initClass(); SO_KIT_INIT_CLASS(SoFCCSysDragger, SoDragger, "Dragger"); } @@ -668,6 +970,8 @@ SoFCCSysDragger::SoFCCSysDragger() SO_KIT_ADD_CATALOG_ENTRY(annotation, SoAnnotation, TRUE, geomSeparator, "", TRUE); SO_KIT_ADD_CATALOG_ENTRY(scaleNode, SoScale, TRUE, annotation, "", TRUE); + // Translator + SO_KIT_ADD_CATALOG_ENTRY(xTranslatorSwitch, SoSwitch, TRUE, annotation, "", TRUE); SO_KIT_ADD_CATALOG_ENTRY(yTranslatorSwitch, SoSwitch, TRUE, annotation, "", TRUE); SO_KIT_ADD_CATALOG_ENTRY(zTranslatorSwitch, SoSwitch, TRUE, annotation, "", TRUE); @@ -688,6 +992,30 @@ SoFCCSysDragger::SoFCCSysDragger() SO_KIT_ADD_CATALOG_ENTRY(yTranslatorDragger, TDragger, TRUE, yTranslatorSeparator, "", TRUE); SO_KIT_ADD_CATALOG_ENTRY(zTranslatorDragger, TDragger, TRUE, zTranslatorSeparator, "", TRUE); + // Planar Translator + + SO_KIT_ADD_CATALOG_ENTRY(xyPlanarTranslatorSwitch, SoSwitch, TRUE, annotation, "", TRUE); + SO_KIT_ADD_CATALOG_ENTRY(yzPlanarTranslatorSwitch, SoSwitch, TRUE, annotation, "", TRUE); + SO_KIT_ADD_CATALOG_ENTRY(zxPlanarTranslatorSwitch, SoSwitch, TRUE, annotation, "", TRUE); + + SO_KIT_ADD_CATALOG_ENTRY(xyPlanarTranslatorSeparator, SoSeparator, TRUE, xyPlanarTranslatorSwitch, "", TRUE); + SO_KIT_ADD_CATALOG_ENTRY(yzPlanarTranslatorSeparator, SoSeparator, TRUE, yzPlanarTranslatorSwitch, "", TRUE); + SO_KIT_ADD_CATALOG_ENTRY(zxPlanarTranslatorSeparator, SoSeparator, TRUE, zxPlanarTranslatorSwitch, "", TRUE); + + SO_KIT_ADD_CATALOG_ENTRY(xyPlanarTranslatorColor, SoBaseColor, TRUE, xyPlanarTranslatorSeparator, "", TRUE); + SO_KIT_ADD_CATALOG_ENTRY(yzPlanarTranslatorColor, SoBaseColor, TRUE, yzPlanarTranslatorSeparator, "", TRUE); + SO_KIT_ADD_CATALOG_ENTRY(zxPlanarTranslatorColor, SoBaseColor, TRUE, zxPlanarTranslatorSeparator, "", TRUE); + + SO_KIT_ADD_CATALOG_ENTRY(xyPlanarTranslatorRotation, SoRotation, TRUE, xyPlanarTranslatorSeparator, "", TRUE); + SO_KIT_ADD_CATALOG_ENTRY(yzPlanarTranslatorRotation, SoRotation, TRUE, yzPlanarTranslatorSeparator, "", TRUE); + SO_KIT_ADD_CATALOG_ENTRY(zxPlanarTranslatorRotation, SoRotation, TRUE, zxPlanarTranslatorSeparator, "", TRUE); + + SO_KIT_ADD_CATALOG_ENTRY(xyPlanarTranslatorDragger, TPlanarDragger, TRUE, xyPlanarTranslatorSeparator, "", TRUE); + SO_KIT_ADD_CATALOG_ENTRY(yzPlanarTranslatorDragger, TPlanarDragger, TRUE, yzPlanarTranslatorSeparator, "", TRUE); + SO_KIT_ADD_CATALOG_ENTRY(zxPlanarTranslatorDragger, TPlanarDragger, TRUE, zxPlanarTranslatorSeparator, "", TRUE); + + // Rotator + SO_KIT_ADD_CATALOG_ENTRY(xRotatorSwitch, SoSwitch, TRUE, annotation, "", TRUE); SO_KIT_ADD_CATALOG_ENTRY(yRotatorSwitch, SoSwitch, TRUE, annotation, "", TRUE); SO_KIT_ADD_CATALOG_ENTRY(zRotatorSwitch, SoSwitch, TRUE, annotation, "", TRUE); @@ -708,6 +1036,8 @@ SoFCCSysDragger::SoFCCSysDragger() SO_KIT_ADD_CATALOG_ENTRY(yRotatorDragger, RDragger, TRUE, yRotatorSeparator, "", TRUE); SO_KIT_ADD_CATALOG_ENTRY(zRotatorDragger, RDragger, TRUE, zRotatorSeparator, "", TRUE); + // Other + SO_KIT_ADD_FIELD(translation, (0.0, 0.0, 0.0)); SO_KIT_ADD_FIELD(translationIncrement, (1.0)); SO_KIT_ADD_FIELD(translationIncrementCountX, (0)); @@ -725,36 +1055,76 @@ SoFCCSysDragger::SoFCCSysDragger() SO_KIT_INIT_INSTANCE(); - SoBaseColor *color; - color = SO_GET_ANY_PART(this, "xTranslatorColor", SoBaseColor); - color->rgb.setValue(1.0, 0.0, 0.0); - color = SO_GET_ANY_PART(this, "yTranslatorColor", SoBaseColor); - color->rgb.setValue(0.0, 1.0, 0.0); - color = SO_GET_ANY_PART(this, "zTranslatorColor", SoBaseColor); - color->rgb.setValue(0.0, 0.0, 1.0); - color = SO_GET_ANY_PART(this, "xRotatorColor", SoBaseColor); - color->rgb.setValue(1.0, 0.0, 0.0); - color = SO_GET_ANY_PART(this, "yRotatorColor", SoBaseColor); - color->rgb.setValue(0.0, 1.0, 0.0); - color = SO_GET_ANY_PART(this, "zRotatorColor", SoBaseColor); - color->rgb.setValue(0.0, 0.0, 1.0); + // Colors + SoBaseColor *color; + App::Color stdColor; + auto viewParams = Gui::ViewParams::instance(); + // Translator + color = SO_GET_ANY_PART(this, "xTranslatorColor", SoBaseColor); + stdColor.setPackedValue(viewParams->getAxisXColor()); + color->rgb.setValue(stdColor.r, stdColor.g, stdColor.b); + color = SO_GET_ANY_PART(this, "yTranslatorColor", SoBaseColor); + stdColor.setPackedValue(viewParams->getAxisYColor()); + color->rgb.setValue(stdColor.r, stdColor.g, stdColor.b); + color = SO_GET_ANY_PART(this, "zTranslatorColor", SoBaseColor); + stdColor.setPackedValue(viewParams->getAxisZColor()); + color->rgb.setValue(stdColor.r, stdColor.g, stdColor.b); + // Planar Translator + color = SO_GET_ANY_PART(this, "xyPlanarTranslatorColor", SoBaseColor); + stdColor.setPackedValue(viewParams->getAxisZColor()); + color->rgb.setValue(stdColor.r, stdColor.g, stdColor.b); + color = SO_GET_ANY_PART(this, "yzPlanarTranslatorColor", SoBaseColor); + stdColor.setPackedValue(viewParams->getAxisXColor()); + color->rgb.setValue(stdColor.r, stdColor.g, stdColor.b); + color = SO_GET_ANY_PART(this, "zxPlanarTranslatorColor", SoBaseColor); + stdColor.setPackedValue(viewParams->getAxisYColor()); + color->rgb.setValue(stdColor.r, stdColor.g, stdColor.b); + // Rotator + color = SO_GET_ANY_PART(this, "xRotatorColor", SoBaseColor); + stdColor.setPackedValue(viewParams->getAxisXAltColor()); + color->rgb.setValue(stdColor.r, stdColor.g, stdColor.b); + color = SO_GET_ANY_PART(this, "yRotatorColor", SoBaseColor); + stdColor.setPackedValue(viewParams->getAxisYAltColor()); + color->rgb.setValue(stdColor.r, stdColor.g, stdColor.b); + color = SO_GET_ANY_PART(this, "zRotatorColor", SoBaseColor); + stdColor.setPackedValue(viewParams->getAxisZAltColor()); + color->rgb.setValue(stdColor.r, stdColor.g, stdColor.b); + + // Increments + + // Translator TDragger *tDragger; tDragger = SO_GET_ANY_PART(this, "xTranslatorDragger", TDragger); tDragger->translationIncrement.connectFrom(&this->translationIncrement); tDragger->autoScaleResult.connectFrom(&this->autoScaleResult); translationIncrementCountX.connectFrom(&tDragger->translationIncrementCount); - tDragger = SO_GET_ANY_PART(this, "yTranslatorDragger", TDragger); tDragger->translationIncrement.connectFrom(&this->translationIncrement); tDragger->autoScaleResult.connectFrom(&this->autoScaleResult); translationIncrementCountY.connectFrom(&tDragger->translationIncrementCount); - tDragger = SO_GET_ANY_PART(this, "zTranslatorDragger", TDragger); tDragger->translationIncrement.connectFrom(&this->translationIncrement); tDragger->autoScaleResult.connectFrom(&this->autoScaleResult); translationIncrementCountZ.connectFrom(&tDragger->translationIncrementCount); - + // Planar Translator + TPlanarDragger *tPlanarDragger; + tPlanarDragger = SO_GET_ANY_PART(this, "xyPlanarTranslatorDragger", TPlanarDragger); + tPlanarDragger->translationIncrement.connectFrom(&this->translationIncrement); + tPlanarDragger->autoScaleResult.connectFrom(&this->autoScaleResult); + translationIncrementCountX.appendConnection(&tPlanarDragger->translationIncrementXCount); + translationIncrementCountY.appendConnection(&tPlanarDragger->translationIncrementYCount); + tPlanarDragger = SO_GET_ANY_PART(this, "yzPlanarTranslatorDragger", TPlanarDragger); + tPlanarDragger->translationIncrement.connectFrom(&this->translationIncrement); + tPlanarDragger->autoScaleResult.connectFrom(&this->autoScaleResult); + translationIncrementCountZ.appendConnection(&tPlanarDragger->translationIncrementXCount); + translationIncrementCountY.appendConnection(&tPlanarDragger->translationIncrementYCount); + tPlanarDragger = SO_GET_ANY_PART(this, "zxPlanarTranslatorDragger", TPlanarDragger); + tPlanarDragger->translationIncrement.connectFrom(&this->translationIncrement); + tPlanarDragger->autoScaleResult.connectFrom(&this->autoScaleResult); + translationIncrementCountX.appendConnection(&tPlanarDragger->translationIncrementXCount); + translationIncrementCountZ.appendConnection(&tPlanarDragger->translationIncrementYCount); + // Rotator RDragger *rDragger; rDragger = SO_GET_ANY_PART(this, "xRotatorDragger", RDragger); rDragger->rotationIncrement.connectFrom(&this->rotationIncrement); @@ -766,12 +1136,23 @@ SoFCCSysDragger::SoFCCSysDragger() rDragger->rotationIncrement.connectFrom(&this->rotationIncrement); rotationIncrementCountZ.connectFrom(&rDragger->rotationIncrementCount); + // Switches + + // Translator SoSwitch *sw = SO_GET_ANY_PART(this, "xTranslatorSwitch", SoSwitch); SoInteractionKit::setSwitchValue(sw, SO_SWITCH_ALL); sw = SO_GET_ANY_PART(this, "yTranslatorSwitch", SoSwitch); SoInteractionKit::setSwitchValue(sw, SO_SWITCH_ALL); sw = SO_GET_ANY_PART(this, "zTranslatorSwitch", SoSwitch); SoInteractionKit::setSwitchValue(sw, SO_SWITCH_ALL); + // Planar Translator + sw = SO_GET_ANY_PART(this, "xyPlanarTranslatorSwitch", SoSwitch); + SoInteractionKit::setSwitchValue(sw, SO_SWITCH_ALL); + sw = SO_GET_ANY_PART(this, "yzPlanarTranslatorSwitch", SoSwitch); + SoInteractionKit::setSwitchValue(sw, SO_SWITCH_ALL); + sw = SO_GET_ANY_PART(this, "zxPlanarTranslatorSwitch", SoSwitch); + SoInteractionKit::setSwitchValue(sw, SO_SWITCH_ALL); + // Rotator sw = SO_GET_ANY_PART(this, "xRotatorSwitch", SoSwitch); SoInteractionKit::setSwitchValue(sw, SO_SWITCH_ALL); sw = SO_GET_ANY_PART(this, "yRotatorSwitch", SoSwitch); @@ -779,26 +1160,34 @@ SoFCCSysDragger::SoFCCSysDragger() sw = SO_GET_ANY_PART(this, "zRotatorSwitch", SoSwitch); SoInteractionKit::setSwitchValue(sw, SO_SWITCH_ALL); + // Rotations + SoRotation *localRotation; SbRotation tempRotation; auto angle = static_cast(M_PI / 2.0); + // Translator localRotation = SO_GET_ANY_PART(this, "xTranslatorRotation", SoRotation); localRotation->rotation.setValue(SbVec3f(0.0, 0.0, -1.0), angle); localRotation = SO_GET_ANY_PART(this, "yTranslatorRotation", SoRotation); localRotation->rotation.setValue(SbRotation::identity()); localRotation = SO_GET_ANY_PART(this, "zTranslatorRotation", SoRotation); localRotation->rotation.setValue(SbVec3f(1.0, 0.0, 0.0), angle); - + // Planar Translator + localRotation = SO_GET_ANY_PART(this, "xyPlanarTranslatorRotation", SoRotation); + localRotation->rotation.setValue(SbRotation::identity()); + localRotation = SO_GET_ANY_PART(this, "yzPlanarTranslatorRotation", SoRotation); + localRotation->rotation.setValue(SbVec3f(0.0, -1.0, 0.0), angle); + localRotation = SO_GET_ANY_PART(this, "zxPlanarTranslatorRotation", SoRotation); + localRotation->rotation.setValue(SbVec3f(1.0, 0.0, 0.0), angle); + // Rotator localRotation = SO_GET_ANY_PART(this, "xRotatorRotation", SoRotation); tempRotation = SbRotation(SbVec3f(1.0, 0.0, 0.0), angle); tempRotation *= SbRotation(SbVec3f(0.0, 0.0, 1.0), angle); localRotation->rotation.setValue(tempRotation); - localRotation = SO_GET_ANY_PART(this, "yRotatorRotation", SoRotation); tempRotation = SbRotation(SbVec3f(0.0, -1.0, 0.0), angle); tempRotation *= SbRotation(SbVec3f(0.0, 0.0, -1.0), angle); localRotation->rotation.setValue(tempRotation); - localRotation = SO_GET_ANY_PART(this, "zRotatorRotation", SoRotation); localRotation->rotation.setValue(SbRotation::identity()); @@ -857,6 +1246,9 @@ SbBool SoFCCSysDragger::setUpConnections(SbBool onoff, SbBool doitalways) TDragger *tDraggerX = SO_GET_ANY_PART(this, "xTranslatorDragger", TDragger); TDragger *tDraggerY = SO_GET_ANY_PART(this, "yTranslatorDragger", TDragger); TDragger *tDraggerZ = SO_GET_ANY_PART(this, "zTranslatorDragger", TDragger); + TPlanarDragger *tPlanarDraggerXZ = SO_GET_ANY_PART(this, "xyPlanarTranslatorDragger", TPlanarDragger); + TPlanarDragger *tPlanarDraggerYZ = SO_GET_ANY_PART(this, "yzPlanarTranslatorDragger", TPlanarDragger); + TPlanarDragger *tPlanarDraggerZX = SO_GET_ANY_PART(this, "zxPlanarTranslatorDragger", TPlanarDragger); RDragger *rDraggerX = SO_GET_ANY_PART(this, "xRotatorDragger", RDragger); RDragger *rDraggerY = SO_GET_ANY_PART(this, "yRotatorDragger", RDragger); RDragger *rDraggerZ = SO_GET_ANY_PART(this, "zRotatorDragger", RDragger); @@ -868,6 +1260,9 @@ SbBool SoFCCSysDragger::setUpConnections(SbBool onoff, SbBool doitalways) registerChildDragger(tDraggerX); registerChildDragger(tDraggerY); registerChildDragger(tDraggerZ); + registerChildDragger(tPlanarDraggerXZ); + registerChildDragger(tPlanarDraggerYZ); + registerChildDragger(tPlanarDraggerZX); registerChildDragger(rDraggerX); registerChildDragger(rDraggerY); registerChildDragger(rDraggerZ); @@ -885,6 +1280,9 @@ SbBool SoFCCSysDragger::setUpConnections(SbBool onoff, SbBool doitalways) unregisterChildDragger(tDraggerX); unregisterChildDragger(tDraggerY); unregisterChildDragger(tDraggerZ); + unregisterChildDragger(tPlanarDraggerXZ); + unregisterChildDragger(tPlanarDraggerYZ); + unregisterChildDragger(tPlanarDraggerZX); unregisterChildDragger(rDraggerX); unregisterChildDragger(rDraggerY); unregisterChildDragger(rDraggerZ); @@ -1070,18 +1468,19 @@ void SoFCCSysDragger::clearIncrementCounts() rotationIncrementCountZ.setValue(0); } +// Visiblity API Functions + +// Translator void SoFCCSysDragger::showTranslationX() { SoSwitch *sw = SO_GET_ANY_PART(this, "xTranslatorSwitch", SoSwitch); SoInteractionKit::setSwitchValue(sw, SO_SWITCH_ALL); } - void SoFCCSysDragger::showTranslationY() { SoSwitch *sw = SO_GET_ANY_PART(this, "yTranslatorSwitch", SoSwitch); SoInteractionKit::setSwitchValue(sw, SO_SWITCH_ALL); } - void SoFCCSysDragger::showTranslationZ() { SoSwitch *sw = SO_GET_ANY_PART(this, "zTranslatorSwitch", SoSwitch); @@ -1093,31 +1492,125 @@ void SoFCCSysDragger::hideTranslationX() SoSwitch *sw = SO_GET_ANY_PART(this, "xTranslatorSwitch", SoSwitch); SoInteractionKit::setSwitchValue(sw, SO_SWITCH_NONE); } - void SoFCCSysDragger::hideTranslationY() { SoSwitch *sw = SO_GET_ANY_PART(this, "yTranslatorSwitch", SoSwitch); SoInteractionKit::setSwitchValue(sw, SO_SWITCH_NONE); } - void SoFCCSysDragger::hideTranslationZ() { SoSwitch *sw = SO_GET_ANY_PART(this, "zTranslatorSwitch", SoSwitch); SoInteractionKit::setSwitchValue(sw, SO_SWITCH_NONE); } +bool SoFCCSysDragger::isShownTranslationX() +{ + SoSwitch *sw = SO_GET_ANY_PART(this, "xTranslatorSwitch", SoSwitch); + return (sw->whichChild.getValue() == SO_SWITCH_ALL); +} +bool SoFCCSysDragger::isShownTranslationY() +{ + SoSwitch *sw = SO_GET_ANY_PART(this, "yTranslatorSwitch", SoSwitch); + return (sw->whichChild.getValue() == SO_SWITCH_ALL); +} +bool SoFCCSysDragger::isShownTranslationZ() +{ + SoSwitch *sw = SO_GET_ANY_PART(this, "zTranslatorSwitch", SoSwitch); + return (sw->whichChild.getValue() == SO_SWITCH_ALL); +} + +bool SoFCCSysDragger::isHiddenTranslationX() +{ + SoSwitch *sw = SO_GET_ANY_PART(this, "xTranslatorSwitch", SoSwitch); + return (sw->whichChild.getValue() == SO_SWITCH_NONE); +} +bool SoFCCSysDragger::isHiddenTranslationY() +{ + SoSwitch *sw = SO_GET_ANY_PART(this, "yTranslatorSwitch", SoSwitch); + return (sw->whichChild.getValue() == SO_SWITCH_NONE); +} +bool SoFCCSysDragger::isHiddenTranslationZ() +{ + SoSwitch *sw = SO_GET_ANY_PART(this, "zTranslatorSwitch", SoSwitch); + return (sw->whichChild.getValue() == SO_SWITCH_NONE); +} + +// Planar Translator +void SoFCCSysDragger::showPlanarTranslationXY() +{ + SoSwitch *sw = SO_GET_ANY_PART(this, "xyPlanarTranslatorSwitch", SoSwitch); + SoInteractionKit::setSwitchValue(sw, SO_SWITCH_ALL); +} +void SoFCCSysDragger::showPlanarTranslationYZ() +{ + SoSwitch *sw = SO_GET_ANY_PART(this, "yzPlanarTranslatorSwitch", SoSwitch); + SoInteractionKit::setSwitchValue(sw, SO_SWITCH_ALL); +} +void SoFCCSysDragger::showPlanarTranslationZX() +{ + SoSwitch *sw = SO_GET_ANY_PART(this, "zxPlanarTranslatorSwitch", SoSwitch); + SoInteractionKit::setSwitchValue(sw, SO_SWITCH_ALL); +} + +void SoFCCSysDragger::hidePlanarTranslationXY() +{ + SoSwitch *sw = SO_GET_ANY_PART(this, "xyPlanarTranslatorSwitch", SoSwitch); + SoInteractionKit::setSwitchValue(sw, SO_SWITCH_NONE); +} +void SoFCCSysDragger::hidePlanarTranslationYZ() +{ + SoSwitch *sw = SO_GET_ANY_PART(this, "yzPlanarTranslatorSwitch", SoSwitch); + SoInteractionKit::setSwitchValue(sw, SO_SWITCH_NONE); +} +void SoFCCSysDragger::hidePlanarTranslationZX() +{ + SoSwitch *sw = SO_GET_ANY_PART(this, "zxPlanarTranslatorSwitch", SoSwitch); + SoInteractionKit::setSwitchValue(sw, SO_SWITCH_NONE); +} + +bool SoFCCSysDragger::isShownPlanarTranslationXY() +{ + SoSwitch *sw = SO_GET_ANY_PART(this, "xyPlanarTranslatorSwitch", SoSwitch); + return (sw->whichChild.getValue() == SO_SWITCH_ALL); +} +bool SoFCCSysDragger::isShownPlanarTranslationYZ() +{ + SoSwitch *sw = SO_GET_ANY_PART(this, "yzPlanarTranslatorSwitch", SoSwitch); + return (sw->whichChild.getValue() == SO_SWITCH_ALL); +} +bool SoFCCSysDragger::isShownPlanarTranslationZX() +{ + SoSwitch *sw = SO_GET_ANY_PART(this, "zxPlanarTranslatorSwitch", SoSwitch); + return (sw->whichChild.getValue() == SO_SWITCH_ALL); +} + +bool SoFCCSysDragger::isHiddenPlanarTranslationXY() +{ + SoSwitch *sw = SO_GET_ANY_PART(this, "xyPlanarTranslatorSwitch", SoSwitch); + return (sw->whichChild.getValue() == SO_SWITCH_NONE); +} +bool SoFCCSysDragger::isHiddenPlanarTranslationYZ() +{ + SoSwitch *sw = SO_GET_ANY_PART(this, "yzPlanarTranslatorSwitch", SoSwitch); + return (sw->whichChild.getValue() == SO_SWITCH_NONE); +} +bool SoFCCSysDragger::isHiddenPlanarTranslationZX() +{ + SoSwitch *sw = SO_GET_ANY_PART(this, "zxPlanarTranslatorSwitch", SoSwitch); + return (sw->whichChild.getValue() == SO_SWITCH_NONE); +} + +// Rotator void SoFCCSysDragger::showRotationX() { SoSwitch *sw = SO_GET_ANY_PART(this, "xRotatorSwitch", SoSwitch); SoInteractionKit::setSwitchValue(sw, SO_SWITCH_ALL); } - void SoFCCSysDragger::showRotationY() { SoSwitch *sw = SO_GET_ANY_PART(this, "yRotatorSwitch", SoSwitch); SoInteractionKit::setSwitchValue(sw, SO_SWITCH_ALL); } - void SoFCCSysDragger::showRotationZ() { SoSwitch *sw = SO_GET_ANY_PART(this, "zRotatorSwitch", SoSwitch); @@ -1129,85 +1622,43 @@ void SoFCCSysDragger::hideRotationX() SoSwitch *sw = SO_GET_ANY_PART(this, "xRotatorSwitch", SoSwitch); SoInteractionKit::setSwitchValue(sw, SO_SWITCH_NONE); } - void SoFCCSysDragger::hideRotationY() { SoSwitch *sw = SO_GET_ANY_PART(this, "yRotatorSwitch", SoSwitch); SoInteractionKit::setSwitchValue(sw, SO_SWITCH_NONE); } - void SoFCCSysDragger::hideRotationZ() { SoSwitch *sw = SO_GET_ANY_PART(this, "zRotatorSwitch", SoSwitch); SoInteractionKit::setSwitchValue(sw, SO_SWITCH_NONE); } -bool SoFCCSysDragger::isShownTranslationX() -{ - SoSwitch *sw = SO_GET_ANY_PART(this, "xTranslatorSwitch", SoSwitch); - return (sw->whichChild.getValue() == SO_SWITCH_ALL); -} - -bool SoFCCSysDragger::isShownTranslationY() -{ - SoSwitch *sw = SO_GET_ANY_PART(this, "yTranslatorSwitch", SoSwitch); - return (sw->whichChild.getValue() == SO_SWITCH_ALL); -} - -bool SoFCCSysDragger::isShownTranslationZ() -{ - SoSwitch *sw = SO_GET_ANY_PART(this, "zTranslatorSwitch", SoSwitch); - return (sw->whichChild.getValue() == SO_SWITCH_ALL); -} - bool SoFCCSysDragger::isShownRotationX() { SoSwitch *sw = SO_GET_ANY_PART(this, "xRotatorSwitch", SoSwitch); return (sw->whichChild.getValue() == SO_SWITCH_ALL); } - bool SoFCCSysDragger::isShownRotationY() { SoSwitch *sw = SO_GET_ANY_PART(this, "yRotatorSwitch", SoSwitch); return (sw->whichChild.getValue() == SO_SWITCH_ALL); } - bool SoFCCSysDragger::isShownRotationZ() { SoSwitch *sw = SO_GET_ANY_PART(this, "zRotatorSwitch", SoSwitch); return (sw->whichChild.getValue() == SO_SWITCH_ALL); } -bool SoFCCSysDragger::isHiddenTranslationX() -{ - SoSwitch *sw = SO_GET_ANY_PART(this, "xTranslatorSwitch", SoSwitch); - return (sw->whichChild.getValue() == SO_SWITCH_NONE); -} - -bool SoFCCSysDragger::isHiddenTranslationY() -{ - SoSwitch *sw = SO_GET_ANY_PART(this, "yTranslatorSwitch", SoSwitch); - return (sw->whichChild.getValue() == SO_SWITCH_NONE); -} - -bool SoFCCSysDragger::isHiddenTranslationZ() -{ - SoSwitch *sw = SO_GET_ANY_PART(this, "zTranslatorSwitch", SoSwitch); - return (sw->whichChild.getValue() == SO_SWITCH_NONE); -} - bool SoFCCSysDragger::isHiddenRotationX() { SoSwitch *sw = SO_GET_ANY_PART(this, "xRotatorSwitch", SoSwitch); return (sw->whichChild.getValue() == SO_SWITCH_NONE); } - bool SoFCCSysDragger::isHiddenRotationY() { SoSwitch *sw = SO_GET_ANY_PART(this, "yRotatorSwitch", SoSwitch); return (sw->whichChild.getValue() == SO_SWITCH_NONE); } - bool SoFCCSysDragger::isHiddenRotationZ() { SoSwitch *sw = SO_GET_ANY_PART(this, "zRotatorSwitch", SoSwitch); diff --git a/src/Gui/SoFCCSysDragger.h b/src/Gui/SoFCCSysDragger.h index 66272cc916..9f76a68929 100644 --- a/src/Gui/SoFCCSysDragger.h +++ b/src/Gui/SoFCCSysDragger.h @@ -86,6 +86,56 @@ private: using inherited = SoDragger; }; +/*! @brief Planar Translation Dragger. + * + * used for translating on a plane. Set the + * translationIncrement to desired step. Use + * 'translationIncrementXCount' or + * 'translationIncrementYCount' multiplied with + * 'translationIncrement' for a full double + * precision vector scalar. + * + * @author qewer33 + */ +class TPlanarDragger : public SoDragger +{ + SO_KIT_HEADER(TDragger); + SO_KIT_CATALOG_ENTRY_HEADER(planarTranslatorSwitch); + SO_KIT_CATALOG_ENTRY_HEADER(planarTranslator); + SO_KIT_CATALOG_ENTRY_HEADER(planarTranslatorActive); +public: + static void initClass(); + TPlanarDragger(); + SoSFVec3f translation; //!< set from outside and used from outside for single precision. + SoSFDouble translationIncrement; //!< set from outside and used for rounding. + SoSFInt32 translationIncrementXCount; //!< number of steps. used from outside. + SoSFInt32 translationIncrementYCount; //!< number of steps. used from outside. + SoSFFloat autoScaleResult; //!< set from parent dragger. + +protected: + ~TPlanarDragger() override; + SbBool setUpConnections(SbBool onoff, SbBool doitalways = FALSE) override; + + static void startCB(void *, SoDragger * d); + static void motionCB(void *, SoDragger * d); + static void finishCB(void *, SoDragger * d); + static void fieldSensorCB(void *f, SoSensor *); + static void valueChangedCB(void *, SoDragger *d); + + void dragStart(); + void drag(); + void dragFinish(); + + SoFieldSensor fieldSensor; + SbPlaneProjector projector; + +private: + void buildFirstInstance(); + SbVec3f roundTranslation(const SbVec3f &vecIn, float incrementIn); + SoGroup* buildGeometry(); + using inherited = SoDragger; +}; + /*! @brief Rotation Dragger. * * used for rotating around an axis. Set the rotation @@ -149,6 +199,7 @@ class GuiExport SoFCCSysDragger : public SoDragger SO_KIT_HEADER(SoFCCSysDragger); SO_KIT_CATALOG_ENTRY_HEADER(annotation); SO_KIT_CATALOG_ENTRY_HEADER(scaleNode); + // Translator SO_KIT_CATALOG_ENTRY_HEADER(xTranslatorSwitch); SO_KIT_CATALOG_ENTRY_HEADER(yTranslatorSwitch); SO_KIT_CATALOG_ENTRY_HEADER(zTranslatorSwitch); @@ -164,6 +215,23 @@ class GuiExport SoFCCSysDragger : public SoDragger SO_KIT_CATALOG_ENTRY_HEADER(xTranslatorDragger); SO_KIT_CATALOG_ENTRY_HEADER(yTranslatorDragger); SO_KIT_CATALOG_ENTRY_HEADER(zTranslatorDragger); + // Planar Translator + SO_KIT_CATALOG_ENTRY_HEADER(xyPlanarTranslatorSwitch); + SO_KIT_CATALOG_ENTRY_HEADER(yzPlanarTranslatorSwitch); + SO_KIT_CATALOG_ENTRY_HEADER(zxPlanarTranslatorSwitch); + SO_KIT_CATALOG_ENTRY_HEADER(xyPlanarTranslatorSeparator); + SO_KIT_CATALOG_ENTRY_HEADER(yzPlanarTranslatorSeparator); + SO_KIT_CATALOG_ENTRY_HEADER(zxPlanarTranslatorSeparator); + SO_KIT_CATALOG_ENTRY_HEADER(xyPlanarTranslatorColor); + SO_KIT_CATALOG_ENTRY_HEADER(yzPlanarTranslatorColor); + SO_KIT_CATALOG_ENTRY_HEADER(zxPlanarTranslatorColor); + SO_KIT_CATALOG_ENTRY_HEADER(xyPlanarTranslatorRotation); + SO_KIT_CATALOG_ENTRY_HEADER(yzPlanarTranslatorRotation); + SO_KIT_CATALOG_ENTRY_HEADER(zxPlanarTranslatorRotation); + SO_KIT_CATALOG_ENTRY_HEADER(xyPlanarTranslatorDragger); + SO_KIT_CATALOG_ENTRY_HEADER(yzPlanarTranslatorDragger); + SO_KIT_CATALOG_ENTRY_HEADER(zxPlanarTranslatorDragger); + // Rotator SO_KIT_CATALOG_ENTRY_HEADER(xRotatorSwitch); SO_KIT_CATALOG_ENTRY_HEADER(yRotatorSwitch); SO_KIT_CATALOG_ENTRY_HEADER(zRotatorSwitch); @@ -218,6 +286,25 @@ public: void hideTranslationX(); //!< hide the x translation dragger. void hideTranslationY(); //!< hide the y translation dragger. void hideTranslationZ(); //!< hide the z translation dragger. + bool isShownTranslationX(); //!< is x translation dragger shown. + bool isShownTranslationY(); //!< is y translation dragger shown. + bool isShownTranslationZ(); //!< is z translation dragger shown. + bool isHiddenTranslationX(); //!< is x translation dragger hidden. + bool isHiddenTranslationY(); //!< is y translation dragger hidden. + bool isHiddenTranslationZ(); //!< is z translation dragger hidden. + + void showPlanarTranslationXY(); //!< show the xy planar translation dragger. + void showPlanarTranslationYZ(); //!< show the yz planar translation dragger. + void showPlanarTranslationZX(); //!< show the zx planar translation dragger. + void hidePlanarTranslationXY(); //!< hide the xy planar translation dragger. + void hidePlanarTranslationYZ(); //!< hide the yz planar translation dragger. + void hidePlanarTranslationZX(); //!< hide the zx planar translation dragger. + bool isShownPlanarTranslationXY(); //!< is xy planar translation dragger shown. + bool isShownPlanarTranslationYZ(); //!< is yz planar translation dragger shown. + bool isShownPlanarTranslationZX(); //!< is zx planar translation dragger shown. + bool isHiddenPlanarTranslationXY(); //!< is xy planar translation dragger hidden. + bool isHiddenPlanarTranslationYZ(); //!< is yz planar translation dragger hidden. + bool isHiddenPlanarTranslationZX(); //!< is zx planar translation dragger hidden. void showRotationX(); //!< show the x rotation dragger. void showRotationY(); //!< show the y rotation dragger. @@ -225,17 +312,9 @@ public: void hideRotationX(); //!< hide the x rotation dragger. void hideRotationY(); //!< hide the y rotation dragger. void hideRotationZ(); //!< hide the z rotation dragger. - - bool isShownTranslationX(); //!< is x translation dragger shown. - bool isShownTranslationY(); //!< is y translation dragger shown. - bool isShownTranslationZ(); //!< is z translation dragger shown. bool isShownRotationX(); //!< is x rotation dragger shown. bool isShownRotationY(); //!< is x rotation dragger shown. bool isShownRotationZ(); //!< is x rotation dragger shown. - - bool isHiddenTranslationX(); //!< is x translation dragger hidden. - bool isHiddenTranslationY(); //!< is y translation dragger hidden. - bool isHiddenTranslationZ(); //!< is z translation dragger hidden. bool isHiddenRotationX(); //!< is x rotation dragger hidden. bool isHiddenRotationY(); //!< is x rotation dragger hidden. bool isHiddenRotationZ(); //!< is x rotation dragger hidden. diff --git a/src/Gui/TaskView/TaskImage.cpp b/src/Gui/TaskView/TaskImage.cpp index 48038c9f26..95985ccffd 100644 --- a/src/Gui/TaskView/TaskImage.cpp +++ b/src/Gui/TaskView/TaskImage.cpp @@ -33,16 +33,12 @@ # include # include # include -# include -# include -# include -# include -# include -# include -# include #endif + +// clang-format off #include #include +// clang-format on #include #include @@ -54,6 +50,7 @@ #include #include #include +#include #include #include @@ -77,6 +74,7 @@ TaskImage::TaskImage(Image::ImagePlane* obj, QWidget* parent) initialiseTransparency(); + // NOLINTNEXTLINE aspectRatio = obj->XSize.getValue() / obj->YSize.getValue(); connectSignals(); @@ -129,6 +127,7 @@ void TaskImage::connectSignals() void TaskImage::initialiseTransparency() { + // NOLINTBEGIN auto vp = Application::Instance->getViewProvider(feature.get()); App::Property* prop = vp->getPropertyByName("Transparency"); if (prop && prop->getTypeId().isDerivedFrom(App::PropertyInteger::getClassTypeId())) { @@ -136,17 +135,18 @@ void TaskImage::initialiseTransparency() ui->spinBoxTransparency->setValue(Transparency->getValue()); ui->sliderTransparency->setValue(Transparency->getValue()); } + // NOLINTEND } void TaskImage::changeTransparency(int val) { - if (feature.expired()) + if (feature.expired()) { return; + } auto vp = Application::Instance->getViewProvider(feature.get()); App::Property* prop = vp->getPropertyByName("Transparency"); - if (prop && prop->getTypeId().isDerivedFrom(App::PropertyInteger::getClassTypeId())) { - auto Transparency = static_cast(prop); + if (auto Transparency = dynamic_cast(prop)) { Transparency->setValue(val); QSignalBlocker block(ui->spinBoxTransparency); @@ -184,7 +184,7 @@ View3DInventorViewer* TaskImage::getViewer() const { if (!feature.expired()) { auto vp = Application::Instance->getViewProvider(feature.get()); - auto doc = static_cast(vp)->getDocument(); + auto doc = static_cast(vp)->getDocument(); // NOLINT auto view = dynamic_cast(doc->getViewOfViewProvider(vp)); if (view) { return view->getViewer(); @@ -285,47 +285,45 @@ void TaskImage::onPreview() updatePlacement(); } -void TaskImage::restore(const Base::Placement& plm) +// NOLINTNEXTLINE +void TaskImage::restoreAngles(const Base::Rotation& rot) { - if (feature.expired()) - return; - - QSignalBlocker blockW(ui->spinBoxWidth); - QSignalBlocker blockH(ui->spinBoxHeight); - ui->spinBoxWidth->setValue(feature->XSize.getValue()); - ui->spinBoxHeight->setValue(feature->YSize.getValue()); - - Base::Rotation rot = plm.getRotation(); - Base::Vector3d pos = plm.getPosition(); - - double yaw, pitch, roll; + double yaw{}; + double pitch{}; + double roll{}; rot.getYawPitchRoll(yaw, pitch, roll); - double tol = 1.0e-5; bool reverse = false; + const double tol = 1.0e-5; + const double angle1 = 90.0; + const double angle2 = 180.0; + auto isTopOrBottom = [=](bool& reverse) { - if (fabs(pitch) < tol && (fabs(roll) < tol || fabs(roll - 180.) < tol)) { - if (fabs(roll - 180.) < tol) + if (fabs(pitch) < tol && (fabs(roll) < tol || fabs(roll - angle2) < tol)) { + if (fabs(roll - angle2) < tol) { reverse = true; + } return true; } return false; }; auto isFrontOrRear = [=](bool& reverse) { - if (fabs(roll - 90.) < tol && (fabs(yaw) < tol || fabs(yaw - 180.) < tol)) { - if (fabs(yaw - 180.) < tol) + if (fabs(roll - angle1) < tol && (fabs(yaw) < tol || fabs(yaw - angle2) < tol)) { + if (fabs(yaw - angle2) < tol) { reverse = true; + } return true; } return false; }; auto isRightOrLeft = [=](bool& reverse) { - if (fabs(roll - 90.) < tol && (fabs(yaw - 90.) < tol || fabs(yaw + 90.) < tol)) { - if (fabs(yaw + 90.) < tol) + if (fabs(roll - angle1) < tol && (fabs(yaw - angle1) < tol || fabs(yaw + angle1) < tol)) { + if (fabs(yaw + angle1) < tol) { reverse = true; + } return true; } @@ -346,8 +344,27 @@ void TaskImage::restore(const Base::Placement& plm) ui->spinBoxRotation->setValue(-pitch); } ui->Reverse_checkBox->setChecked(reverse); +} - Base::Vector3d R0(0, 0, 0), RX(1, 0, 0), RY(0, 1, 0); +void TaskImage::restore(const Base::Placement& plm) +{ + if (feature.expired()) { + return; + } + + QSignalBlocker blockW(ui->spinBoxWidth); + QSignalBlocker blockH(ui->spinBoxHeight); + ui->spinBoxWidth->setValue(feature->XSize.getValue()); + ui->spinBoxHeight->setValue(feature->YSize.getValue()); + + Base::Rotation rot = plm.getRotation(); // NOLINT + Base::Vector3d pos = plm.getPosition(); + + restoreAngles(rot); + + Base::Vector3d R0(0, 0, 0); + Base::Vector3d RX(1, 0, 0); + Base::Vector3d RY(0, 1, 0); RX = rot.multVec(RX); RY = rot.multVec(RY); @@ -364,6 +381,7 @@ void TaskImage::updatePlacement() double angle = ui->spinBoxRotation->value().getValue(); bool reverse = ui->Reverse_checkBox->isChecked(); + // NOLINTBEGIN Base::Placement Pos; Base::Rotation rot; double dir = reverse ? 180. : 0.; @@ -378,6 +396,7 @@ void TaskImage::updatePlacement() else if (ui->YZ_radioButton->isChecked()) { rot.setYawPitchRoll(90. - dir, -angle, 90.); } + // NOLINTEND Base::Vector3d offset = Base::Vector3d(ui->spinBoxX->value().getValue(), ui->spinBoxY->value().getValue(), ui->spinBoxZ->value().getValue()); offset = rot.multVec(offset); @@ -385,8 +404,9 @@ void TaskImage::updatePlacement() if (!feature.expired()) { feature->Placement.setValue(Pos); - if(scale) + if (scale) { scale->setPlacement(feature->globalPlacement()); + } } } @@ -411,69 +431,26 @@ void TaskImage::updateIcon() // ---------------------------------------------------------------------------- - -struct NodeData { - InteractiveScale* scale; -}; - -InteractiveScale::InteractiveScale(View3DInventorViewer* view, ViewProvider* vp, Base::Placement plc) +InteractiveScale::InteractiveScale(View3DInventorViewer* view, + ViewProvider* vp, + const Base::Placement& plc) // NOLINT : active(false) , placement(plc) , viewer(view) , viewProv(vp) , midPoint(SbVec3f(0,0,0)) { - root = new SoAnnotation; - root->ref(); - root->renderCaching = SoSeparator::OFF; - - measureLabel = new SoDatumLabel(); - measureLabel->ref(); - measureLabel->string = ""; - measureLabel->textColor = SbColor(1.0f, 0.149f, 0.0f); - measureLabel->size.setValue(17); - measureLabel->lineWidth = 2.0; - measureLabel->useAntialiasing = false; - measureLabel->param1 = 0.; - measureLabel->param2 = 0.; - - transform = new SoTransform(); - root->addChild(transform); - setPlacement(placement); - - QWidget* mdi = view->parentWidget(); - - distanceBox = new QuantitySpinBox(mdi); - distanceBox->setUnit(Base::Unit::Length); - distanceBox->setMinimum(0.0); - distanceBox->setMaximum(INT_MAX); - distanceBox->setButtonSymbols(QAbstractSpinBox::NoButtons); - distanceBox->setToolTip(tr("Enter desired distance between the points")); - distanceBox->setKeyboardTracking(false); - distanceBox->installEventFilter(this); - - //track camera movements to update spinbox position. - NodeData* info = new NodeData{ this }; - cameraSensor = new SoNodeSensor([](void* data, SoSensor* sensor) { - Q_UNUSED(sensor) - NodeData* info = static_cast(data); - info->scale->positionWidget(); - }, info); - cameraSensor->attach(viewer->getCamera()); + measureLabel = new EditableDatumLabel(viewer, placement, SbColor(1.0F, 0.149F, 0.0F)); //NOLINT } InteractiveScale::~InteractiveScale() { - root->unref(); - measureLabel->unref(); - distanceBox->deleteLater(); - cameraSensor->detach(); + delete measureLabel; } void InteractiveScale::activate() { if (viewer) { - static_cast(viewer->getSceneGraph())->addChild(root); viewer->setEditing(true); viewer->addEventCallback(SoLocation2Event::getClassTypeId(), InteractiveScale::getMousePosition, this); viewer->addEventCallback(SoButtonEvent::getClassTypeId(), InteractiveScale::soEventFilter, this); @@ -486,10 +463,8 @@ void InteractiveScale::activate() void InteractiveScale::deactivate() { if (viewer) { - distanceBox->hide(); points.clear(); - root->removeChild(measureLabel); - static_cast(viewer->getSceneGraph())->removeChild(root); + measureLabel->deactivate(); viewer->setEditing(false); viewer->removeEventCallback(SoLocation2Event::getClassTypeId(), InteractiveScale::getMousePosition, this); viewer->removeEventCallback(SoButtonEvent::getClassTypeId(), InteractiveScale::soEventFilter, this); @@ -501,16 +476,18 @@ void InteractiveScale::deactivate() double InteractiveScale::getScaleFactor() const { - if ((points[0] - points[1]).length() == 0.) + if ((points[0] - points[1]).length() == 0.) { return 1.0; + } - return distanceBox->value().getValue() / (points[0] - points[1]).length(); + return measureLabel->getValue() / (points[0] - points[1]).length(); } double InteractiveScale::getDistance(const SbVec3f& pt) const { - if (points.empty()) + if (points.empty()) { return 0.0; + } return (points[0] - pt).length(); } @@ -522,19 +499,20 @@ void InteractiveScale::setDistance(const SbVec3f& pos3d) quantity.setUnit(Base::Unit::Length); //Update the displayed distance - double factor; - QString unitStr, valueStr; + double factor{}; + QString unitStr; + QString valueStr; valueStr = quantity.getUserString(factor, unitStr); - measureLabel->string = SbString(valueStr.toUtf8().constData()); - measureLabel->setPoints(getCoordsOnImagePlane(points[0]), getCoordsOnImagePlane(pos3d)); + measureLabel->label->string = SbString(valueStr.toUtf8().constData()); + measureLabel->label->setPoints(getCoordsOnImagePlane(points[0]), getCoordsOnImagePlane(pos3d)); } void InteractiveScale::findPointOnImagePlane(SoEventCallback * ecb) { - const SoMouseButtonEvent * mbe = static_cast(ecb->getEvent()); - Gui::View3DInventorViewer* view = static_cast(ecb->getUserData()); + const SoEvent * mbe = ecb->getEvent(); + auto view = static_cast(ecb->getUserData()); std::unique_ptr pp(view->getPointOnRay(mbe->getPosition(), viewProv)); - if (pp.get()) { + if (pp) { auto pos3d = pp->getPoint(); collectPoint(pos3d); @@ -546,8 +524,8 @@ void InteractiveScale::collectPoint(const SbVec3f& pos3d) if (points.empty()) { points.push_back(pos3d); - measureLabel->setPoints(getCoordsOnImagePlane(pos3d), getCoordsOnImagePlane(pos3d)); - root->addChild(measureLabel); + measureLabel->label->setPoints(getCoordsOnImagePlane(pos3d), getCoordsOnImagePlane(pos3d)); + measureLabel->activate(); } else if (points.size() == 1) { double distance = getDistance(pos3d); @@ -556,8 +534,7 @@ void InteractiveScale::collectPoint(const SbVec3f& pos3d) midPoint = (points[0] + points[1]) / 2; - measureLabel->string = ""; - showDistanceField(); + measureLabel->startEdit(getDistance(points[1]), this); Q_EMIT enableApplyBtn(); } @@ -567,37 +544,17 @@ void InteractiveScale::collectPoint(const SbVec3f& pos3d) } } -void InteractiveScale::showDistanceField() -{ - distanceBox->show(); - QSignalBlocker block(distanceBox); - distanceBox->setValue(getDistance(points[1])); - distanceBox->adjustSize(); - positionWidget(); - distanceBox->selectNumber(); - distanceBox->setFocus(); -} - -void InteractiveScale::positionWidget() -{ - QSize wSize = distanceBox->size(); - QPoint pxCoord = viewer->toQPoint(viewer->getPointOnViewport(midPoint)); - pxCoord.setX(std::max(pxCoord.x() - wSize.width() / 2, 0)); - pxCoord.setY(std::max(pxCoord.y() - wSize.height() / 2, 0)); - distanceBox->move(pxCoord); -} - void InteractiveScale::getMousePosition(void * ud, SoEventCallback * ecb) { - InteractiveScale* scale = static_cast(ud); - const SoLocation2Event * l2e = static_cast(ecb->getEvent()); - Gui::View3DInventorViewer* view = static_cast(ecb->getUserData()); + auto scale = static_cast(ud); + const SoEvent* l2e = ecb->getEvent(); + auto view = static_cast(ecb->getUserData()); if (scale->points.size() == 1) { ecb->setHandled(); std::unique_ptr pp(view->getPointOnRay(l2e->getPosition(), scale->viewProv)); - if (pp.get()) { + if (pp) { SbVec3f pos3d = pp->getPoint(); scale->setDistance(pos3d); } @@ -606,12 +563,12 @@ void InteractiveScale::getMousePosition(void * ud, SoEventCallback * ecb) void InteractiveScale::soEventFilter(void* ud, SoEventCallback* ecb) { - InteractiveScale* scale = static_cast(ud); + auto scale = static_cast(ud); const SoEvent* soEvent = ecb->getEvent(); if (soEvent->isOfType(SoKeyboardEvent::getClassTypeId())) { /* If user presses escape, then we cancel the tool.*/ - const auto kbe = static_cast(soEvent); + const auto kbe = static_cast(soEvent); // NOLINT if (kbe->getKey() == SoKeyboardEvent::ESCAPE && kbe->getState() == SoButtonEvent::UP) { ecb->setHandled(); @@ -619,7 +576,7 @@ void InteractiveScale::soEventFilter(void* ud, SoEventCallback* ecb) } } else if (soEvent->isOfType(SoMouseButtonEvent::getClassTypeId())) { - const auto mbe = static_cast(soEvent); + const auto mbe = static_cast(soEvent); // NOLINT if (mbe->getButton() == SoMouseButtonEvent::BUTTON1 && mbe->getState() == SoButtonEvent::DOWN) { @@ -637,7 +594,7 @@ void InteractiveScale::soEventFilter(void* ud, SoEventCallback* ecb) bool InteractiveScale::eventFilter(QObject* object, QEvent* event) { if (event->type() == QEvent::KeyRelease) { - QKeyEvent* keyEvent = static_cast(event); + auto keyEvent = static_cast(event); // NOLINT /* If user press enter in the spinbox, then we validate the tool.*/ if ((keyEvent->key() == Qt::Key_Enter || keyEvent->key() == Qt::Key_Return) @@ -653,24 +610,17 @@ bool InteractiveScale::eventFilter(QObject* object, QEvent* event) return false; } -void InteractiveScale::setPlacement(Base::Placement plc) +void InteractiveScale::setPlacement(const Base::Placement& plc) { placement = plc; - double x, y, z, w; - placement.getRotation().getValue(x, y, z, w); - transform->rotation.setValue(x, y, z, w); - Base::Vector3d pos = placement.getPosition(); - transform->translation.setValue(pos.x, pos.y, pos.z); - - Base::Vector3d RN(0, 0, 1); - RN = placement.getRotation().multVec(RN); - measureLabel->norm.setValue(SbVec3f(RN.x, RN.y, RN.z)); + measureLabel->setPlacement(plc); } SbVec3f InteractiveScale::getCoordsOnImagePlane(const SbVec3f& point) { // Plane form - Base::Vector3d RX(1, 0, 0), RY(0, 1, 0); + Base::Vector3d RX(1, 0, 0); + Base::Vector3d RY(0, 1, 0); // move to position of Sketch Base::Rotation tmp(placement.getRotation()); @@ -680,10 +630,10 @@ SbVec3f InteractiveScale::getCoordsOnImagePlane(const SbVec3f& point) // we use pos as the Base because in setPlacement we set transform->translation using // placement.getPosition() to fix the Zoffset. But this applies the X & Y translation too. - Base::Vector3d S(point[0], point[1], point[2]); - S.TransformToCoordinateSystem(pos, RX, RY); + Base::Vector3d pnt(point[0], point[1], point[2]); + pnt.TransformToCoordinateSystem(pos, RX, RY); - return SbVec3f(S.x, S.y, 0.); + return {float(pnt.x), float(pnt.y), 0.0F}; } // ---------------------------------------------------------------------------- @@ -691,7 +641,7 @@ SbVec3f InteractiveScale::getCoordsOnImagePlane(const SbVec3f& point) TaskImageDialog::TaskImageDialog(Image::ImagePlane* obj) { widget = new TaskImage(obj); - Gui::TaskView::TaskBox* taskbox = new Gui::TaskView::TaskBox( + auto taskbox = new Gui::TaskView::TaskBox( Gui::BitmapFactory().pixmap("image-plane"), widget->windowTitle(), true, nullptr); taskbox->groupLayout()->addWidget(widget); Content.push_back(taskbox); diff --git a/src/Gui/TaskView/TaskImage.h b/src/Gui/TaskView/TaskImage.h index 720452238a..e4dbca966c 100644 --- a/src/Gui/TaskView/TaskImage.h +++ b/src/Gui/TaskView/TaskImage.h @@ -27,7 +27,6 @@ #include #include #include -#include #include #include #include @@ -35,10 +34,7 @@ class SbVec3f; class SoEventCallback; -class SoSeparator; -class SoDatumLabel; -class SoNodeSensor; -class SoTransform; +class EditableDatumLabel; namespace Gui { @@ -47,9 +43,10 @@ class ViewProvider; class InteractiveScale : public QObject { Q_OBJECT + Q_DISABLE_COPY(InteractiveScale) public: - explicit InteractiveScale(View3DInventorViewer* view, ViewProvider* vp, Base::Placement plc); + explicit InteractiveScale(View3DInventorViewer* view, ViewProvider* vp, const Base::Placement& plc); ~InteractiveScale() override; bool eventFilter(QObject* object, QEvent* event) override; @@ -60,15 +57,13 @@ public: } double getScaleFactor() const; double getDistance(const SbVec3f&) const; - void setPlacement(Base::Placement plc); + void setPlacement(const Base::Placement& plc); private: static void soEventFilter(void * ud, SoEventCallback * ecb); static void getMousePosition(void * ud, SoEventCallback * ecb); void findPointOnImagePlane(SoEventCallback * ecb); void collectPoint(const SbVec3f&); - void positionWidget(); - void showDistanceField(); void setDistance(const SbVec3f&); /// give the coordinates of a line on the image plane in imagePlane (2D) coordinates @@ -82,21 +77,18 @@ Q_SIGNALS: private: bool active; Base::Placement placement; - SoSeparator* root; - SoDatumLabel* measureLabel; - SoTransform* transform; + EditableDatumLabel* measureLabel; QPointer viewer; ViewProvider* viewProv; std::vector points; SbVec3f midPoint; - QuantitySpinBox* distanceBox; - SoNodeSensor* cameraSensor; }; class Ui_TaskImage; class TaskImage : public QWidget { Q_OBJECT + Q_DISABLE_COPY(TaskImage) public: explicit TaskImage(Image::ImagePlane* obj, QWidget* parent = nullptr); @@ -119,6 +111,7 @@ private: void enableApplyBtn(); void restore(const Base::Placement&); + void restoreAngles(const Base::Rotation&); void onPreview(); void updateIcon(); void updatePlacement(); diff --git a/src/Gui/ViewParams.h b/src/Gui/ViewParams.h index 654af67bb9..91d8a2ceec 100644 --- a/src/Gui/ViewParams.h +++ b/src/Gui/ViewParams.h @@ -63,6 +63,13 @@ public: FC_VIEW_PARAM(EnablePropertyViewForInactiveDocument,bool,Bool,true) \ FC_VIEW_PARAM(ShowSelectionBoundingBox,bool,Bool,false) \ FC_VIEW_PARAM(PropertyViewTimer, unsigned long, Unsigned, 100) \ + FC_VIEW_PARAM(AxisXColor,unsigned long,Unsigned,0xCC333300) \ + FC_VIEW_PARAM(AxisXAltColor,unsigned long,Unsigned,0xCC4C4C00) \ + FC_VIEW_PARAM(AxisYColor,unsigned long,Unsigned,0x33CC3300) \ + FC_VIEW_PARAM(AxisYAltColor,unsigned long,Unsigned,0x4CCC4C00) \ + FC_VIEW_PARAM(AxisZColor,unsigned long,Unsigned,0x3333CC00) \ + FC_VIEW_PARAM(AxisZAltColor,unsigned long,Unsigned,0x4C4CCC00) \ + #undef FC_VIEW_PARAM #define FC_VIEW_PARAM(_name,_ctype,_type,_def) \ diff --git a/src/Gui/ViewProviderDragger.cpp b/src/Gui/ViewProviderDragger.cpp index a26179e874..42171bcd04 100644 --- a/src/Gui/ViewProviderDragger.cpp +++ b/src/Gui/ViewProviderDragger.cpp @@ -243,7 +243,7 @@ void ViewProviderDragger::updatePlacementFromDragger(ViewProviderDragger* sudoTh int rCountY = draggerIn->rotationIncrementCountY.getValue(); int rCountZ = draggerIn->rotationIncrementCountZ.getValue(); - //just as a little sanity check make sure only 1 field has changed. + //just as a little sanity check make sure only 1 or 2 fields has changed. int numberOfFieldChanged = 0; if (tCountX) numberOfFieldChanged++; if (tCountY) numberOfFieldChanged++; @@ -253,7 +253,7 @@ void ViewProviderDragger::updatePlacementFromDragger(ViewProviderDragger* sudoTh if (rCountZ) numberOfFieldChanged++; if (numberOfFieldChanged == 0) return; - assert(numberOfFieldChanged == 1); + assert(numberOfFieldChanged == 1 || numberOfFieldChanged == 2); //helper lambdas. auto getVectorX = [&pMatrix]() {return Base::Vector3d(pMatrix[0], pMatrix[4], pMatrix[8]);}; @@ -267,35 +267,35 @@ void ViewProviderDragger::updatePlacementFromDragger(ViewProviderDragger* sudoTh freshPlacement.move(movementVector); geoFeature->Placement.setValue(freshPlacement); } - else if (tCountY) + if (tCountY) { Base::Vector3d movementVector(getVectorY()); movementVector *= (tCountY * translationIncrement); freshPlacement.move(movementVector); geoFeature->Placement.setValue(freshPlacement); } - else if (tCountZ) + if (tCountZ) { Base::Vector3d movementVector(getVectorZ()); movementVector *= (tCountZ * translationIncrement); freshPlacement.move(movementVector); geoFeature->Placement.setValue(freshPlacement); } - else if (rCountX) + if (rCountX) { Base::Vector3d rotationVector(getVectorX()); Base::Rotation rotation(rotationVector, rCountX * rotationIncrement); freshPlacement.setRotation(rotation * freshPlacement.getRotation()); geoFeature->Placement.setValue(freshPlacement); } - else if (rCountY) + if (rCountY) { Base::Vector3d rotationVector(getVectorY()); Base::Rotation rotation(rotationVector, rCountY * rotationIncrement); freshPlacement.setRotation(rotation * freshPlacement.getRotation()); geoFeature->Placement.setValue(freshPlacement); } - else if (rCountZ) + if (rCountZ) { Base::Vector3d rotationVector(getVectorZ()); Base::Rotation rotation(rotationVector, rCountZ * rotationIncrement); diff --git a/src/Gui/Workbench.cpp b/src/Gui/Workbench.cpp index eac08c3872..b1230a6101 100644 --- a/src/Gui/Workbench.cpp +++ b/src/Gui/Workbench.cpp @@ -837,6 +837,7 @@ DockWindowItems* StdWorkbench::setupDockWindows() const //root->addDockWidget("Std_HelpView", Qt::RightDockWidgetArea, true, false); root->addDockWidget("Std_TreeView", Qt::LeftDockWidgetArea, true, false); root->addDockWidget("Std_PropertyView", Qt::LeftDockWidgetArea, true, false); + root->addDockWidget("Std_TaskView", Qt::LeftDockWidgetArea, true, true); root->addDockWidget("Std_SelectionView", Qt::LeftDockWidgetArea, false, false); root->addDockWidget("Std_ComboView", Qt::LeftDockWidgetArea, false, false); root->addDockWidget("Std_ReportView", Qt::BottomDockWidgetArea, true, true); diff --git a/src/Mod/Arch/ArchFence.py b/src/Mod/Arch/ArchFence.py index 94b0fd045c..3e8ae34741 100644 --- a/src/Mod/Arch/ArchFence.py +++ b/src/Mod/Arch/ArchFence.py @@ -158,15 +158,9 @@ class _Fence(ArchComponent.Component): # We want to center the posts on the path. So move them the half width in transformationVector = FreeCAD.Vector(0, - postWidth / 2, 0) - placements = patharray.placements_on_path(rotation, pathwire, - obj.NumberOfSections + 1, - transformationVector, True) - - # The placement of the last object is always the second entry in the list. - # So we move it to the end - placements.append(placements.pop(1)) - - return placements + return patharray.placements_on_path(rotation, pathwire, + obj.NumberOfSections + 1, + transformationVector, True) def calculatePosts(self, obj, postPlacements): posts = [] diff --git a/src/Mod/Arch/exportIFC.py b/src/Mod/Arch/exportIFC.py index a47648003c..c10938cd90 100644 --- a/src/Mod/Arch/exportIFC.py +++ b/src/Mod/Arch/exportIFC.py @@ -2344,7 +2344,10 @@ def getRepresentation( i = 0 rgbt = [] for sol in obj.Shape.Solids: - rgbt.append(diffusecolor[i]) + if i < len(diffusecolor): + rgbt.append(diffusecolor[i]) + else: + rgbt.append(diffusecolor[0]) i += len(sol.Faces) for i,shape in enumerate(colorshapes): if i < len(rgbt): diff --git a/src/Mod/Assembly/Gui/Resources/icons/Assembly_CreateJointBall.svg b/src/Mod/Assembly/Gui/Resources/icons/Assembly_CreateJointBall.svg index 7a383d4773..dedbdbb807 100644 --- a/src/Mod/Assembly/Gui/Resources/icons/Assembly_CreateJointBall.svg +++ b/src/Mod/Assembly/Gui/Resources/icons/Assembly_CreateJointBall.svg @@ -7,7 +7,7 @@ id="svg2784" sodipodi:version="0.32" inkscape:version="1.3 (0e150ed6c4, 2023-07-21)" - sodipodi:docname="Joint_Ball.svg" + sodipodi:docname="Assembly_CreateJointBall.svg" inkscape:output_extension="org.inkscape.output.svg.inkscape" version="1.1" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" @@ -110,9 +110,9 @@ borderopacity="1.0" inkscape:pageopacity="0.0" inkscape:pageshadow="2" - inkscape:zoom="9.0727665" - inkscape:cx="46.788375" - inkscape:cy="12.620186" + inkscape:zoom="12.830829" + inkscape:cx="35.344558" + inkscape:cy="26.225896" inkscape:current-layer="layer1" showgrid="true" inkscape:document-units="px" @@ -184,7 +184,7 @@ + transform="matrix(0.93353917,0,0,0.93353917,3.1649726,2.1267463)"> + transform="matrix(0.6694159,0,0,0.6694159,4.2205539,10.00682)"> diff --git a/src/Mod/Assembly/Gui/Resources/icons/Assembly_CreateJointFixed.svg b/src/Mod/Assembly/Gui/Resources/icons/Assembly_CreateJointFixed.svg index fd8d1c3ff5..88f85fe801 100644 --- a/src/Mod/Assembly/Gui/Resources/icons/Assembly_CreateJointFixed.svg +++ b/src/Mod/Assembly/Gui/Resources/icons/Assembly_CreateJointFixed.svg @@ -7,7 +7,7 @@ id="svg2821" sodipodi:version="0.32" inkscape:version="1.3 (0e150ed6c4, 2023-07-21)" - sodipodi:docname="Joint_Fixed_Alt.svg" + sodipodi:docname="Assembly_CreateJointFixed.svg" inkscape:output_extension="org.inkscape.output.svg.inkscape" version="1.1" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" @@ -183,10 +183,10 @@ borderopacity="1.0" inkscape:pageopacity="0.0" inkscape:pageshadow="2" - inkscape:zoom="7.2080075" - inkscape:cx="59.309039" - inkscape:cy="27.955021" - inkscape:current-layer="g3" + inkscape:zoom="10.193662" + inkscape:cx="30.950604" + inkscape:cy="29.184801" + inkscape:current-layer="layer1" showgrid="true" inkscape:document-units="px" inkscape:grid-bbox="true" @@ -252,109 +252,114 @@ inkscape:label="Layer 1" inkscape:groupmode="layer"> - - - - - - - - - - - - + id="g2" + inkscape:label="Main" + transform="matrix(1.0416665,0,0,1.0416665,-1.3333273,-2.3320947)"> + id="g1" + inkscape:label="Part" + transform="translate(3.6192085e-6,-0.89630564)"> - - + style="fill:#fce94f;stroke:#302b00;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.5;stroke-dashoffset:20.4;stroke-opacity:1" + d="m 56.000001,52.8038 c 0,4.418278 -10.745166,8 -24,8 -13.254833,0 -23.9999985,-3.581722 -23.9999985,-8 l -2e-6,-18.217405 H 56 Z" + id="path2994-3" + inkscape:connector-curvature="0" + sodipodi:nodetypes="sscccs" /> + + + + + + + + + + + + + + + + + + + + - - - - diff --git a/src/Mod/Assembly/Gui/Resources/icons/Assembly_CreateJointParallel.svg b/src/Mod/Assembly/Gui/Resources/icons/Assembly_CreateJointParallel.svg index 69b8572e07..074eaf590c 100644 --- a/src/Mod/Assembly/Gui/Resources/icons/Assembly_CreateJointParallel.svg +++ b/src/Mod/Assembly/Gui/Resources/icons/Assembly_CreateJointParallel.svg @@ -7,7 +7,7 @@ id="svg2821" sodipodi:version="0.32" inkscape:version="1.3 (0e150ed6c4, 2023-07-21)" - sodipodi:docname="Joint_Parallel_Alt.svg" + sodipodi:docname="Assembly_CreateJointParallel.svg" inkscape:output_extension="org.inkscape.output.svg.inkscape" version="1.1" xml:space="preserve" @@ -172,10 +172,10 @@ borderopacity="1.0" inkscape:pageopacity="0.0" inkscape:pageshadow="2" - inkscape:zoom="11.313708" - inkscape:cx="29.565902" - inkscape:cy="26.295533" - inkscape:current-layer="g7" + inkscape:zoom="7.9999996" + inkscape:cx="33.562501" + inkscape:cy="26.812501" + inkscape:current-layer="layer1" showgrid="true" inkscape:document-units="px" inkscape:grid-bbox="true" @@ -206,7 +206,7 @@ inkscape:groupmode="layer"> + transform="matrix(1.0798517,0,0,1.0798517,-2.5552547,-2.5552547)"> - - - - - - - - - + id="layer1-6" + transform="matrix(0.40022634,0,0,0.40022634,38.233689,0.9278826)"> + + + + + + + + + diff --git a/src/Mod/Assembly/Gui/Resources/icons/Assembly_Joint.svg b/src/Mod/Assembly/Gui/Resources/icons/Assembly_Joint.svg new file mode 100644 index 0000000000..d087e33125 --- /dev/null +++ b/src/Mod/Assembly/Gui/Resources/icons/Assembly_Joint.svg @@ -0,0 +1,331 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + [wmayer] + + + Part_Cylinder + 2011-10-10 + http://www.freecad.org/wiki/index.php?title=Artwork + + + FreeCAD + + + FreeCAD/src/Mod/Part/Gui/Resources/icons/Part_Cylinder.svg + + + FreeCAD LGPL2+ + + + https://www.gnu.org/copyleft/lesser.html + + + [agryson] Alexander Gryson + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Mod/Draft/draftguitools/gui_edit.py b/src/Mod/Draft/draftguitools/gui_edit.py index c62650eea4..7109d56282 100644 --- a/src/Mod/Draft/draftguitools/gui_edit.py +++ b/src/Mod/Draft/draftguitools/gui_edit.py @@ -498,7 +498,7 @@ class Edit(gui_base_original.Modifier): orthoConstrain = True snappedPos = Gui.Snapper.snap((pos[0],pos[1]),self.node[-1], constrain=orthoConstrain) self.trackers[self.obj.Name][self.editing].set(snappedPos) - self.ui.displayPoint(snappedPos, self.node[-1]) + self.ui.displayPoint(snappedPos, self.node[-1], mask=Gui.Snapper.affinity) if self.ghost: self.updateGhost(obj=self.obj, node_idx=self.editing, v=snappedPos) diff --git a/src/Mod/Draft/draftobjects/shape2dview.py b/src/Mod/Draft/draftobjects/shape2dview.py index 6fafe03a59..53ca3afc91 100644 --- a/src/Mod/Draft/draftobjects/shape2dview.py +++ b/src/Mod/Draft/draftobjects/shape2dview.py @@ -241,12 +241,12 @@ class Shape2DView(DraftObject): else: shtypes.setdefault(o.Material.Name if (hasattr(o,"Material") and o.Material) - else "None",[]).append(o.Shape.copy()) + else "None",[]).extend(o.Shape.SubShapes) elif hasattr(o,'Shape'): if onlysolids: shapes.extend(o.Shape.Solids) else: - shapes.append(o.Shape.copy()) + shapes.extend(o.Shape.SubShapes) for k, v in shtypes.items(): v1 = v.pop() if v: @@ -264,14 +264,14 @@ class Shape2DView(DraftObject): shapes.extend(v1.Solids) else: print("Shape2DView: Fusing Arch objects produced non-solid results") - shapes.append(v1) + shapes.extend(v1.SubShapes) else: for o in objs: if hasattr(o,'Shape'): if onlysolids: shapes.extend(o.Shape.Solids) else: - shapes.append(o.Shape.copy()) + shapes.extend(o.Shape.SubShapes) clip = False if hasattr(obj.Base,"Clip"): clip = obj.Base.Clip @@ -302,12 +302,12 @@ class Shape2DView(DraftObject): if onlysolids: cuts.extend(c.Solids) else: - cuts.append(c) + cuts.extend(c.SubShapes) else: if onlysolids: cuts.extend(sh.Solids) else: - cuts.append(sh.copy()) + cuts.extend(sh.SubShapes) comp = Part.makeCompound(cuts) obj.Shape = self.getProjected(obj,comp,proj) elif obj.ProjectionMode in ["Cutlines", "Cutfaces"]: @@ -339,9 +339,7 @@ class Shape2DView(DraftObject): objs = self.excludeNames(obj,groups.get_group_contents(obj.Base)) for o in objs: if hasattr(o,'Shape'): - if o.Shape: - if not o.Shape.isNull(): - shapes.append(o.Shape) + shapes.extend(o.Shape.SubShapes) if shapes: import Part comp = Part.makeCompound(shapes) diff --git a/src/Mod/Draft/draftviewproviders/view_dimension.py b/src/Mod/Draft/draftviewproviders/view_dimension.py index e43eea499f..e3ea371979 100644 --- a/src/Mod/Draft/draftviewproviders/view_dimension.py +++ b/src/Mod/Draft/draftviewproviders/view_dimension.py @@ -502,6 +502,9 @@ class ViewProviderLinearDimension(ViewProviderDimensionBase): rot1[2], rot1[3])) self.transDimOvershoot2.rotation.setValue((rot1[0], rot1[1], rot1[2], rot1[3])) + self.trot = rot1 + else: + self.trot = (0, 0, 0, 1) if hasattr(vobj, "FlipArrows") and vobj.FlipArrows: u = u.negative() @@ -535,7 +538,6 @@ class ViewProviderLinearDimension(ViewProviderDimensionBase): else: offset = DraftVecUtils.scaleTo(v1, 0.05) - self.trot = rot1 if hasattr(vobj, "FlipText") and vobj.FlipText: _rott = App.Rotation(self.trot[0], self.trot[1], self.trot[2], self.trot[3]) self.trot = _rott.multiply(App.Rotation(App.Vector(0, 0, 1), 180)).Q diff --git a/src/Mod/Part/App/Geometry.cpp b/src/Mod/Part/App/Geometry.cpp index 00b1ca65b5..a461fe6eca 100644 --- a/src/Mod/Part/App/Geometry.cpp +++ b/src/Mod/Part/App/Geometry.cpp @@ -103,6 +103,7 @@ # include #endif //_PreComp_ +#include #include #include #include @@ -232,16 +233,21 @@ void Geometry::Restore(Base::XMLReader &reader) if(strcmp(reader.localName(),"GeoExtensions") == 0) { // new format - int count = reader.getAttributeAsInteger("count"); + long count = reader.getAttributeAsInteger("count"); - for (int i = 0; i < count; i++) { + for (long i = 0; i < count; i++) { reader.readElement("GeoExtension"); const char* TypeName = reader.getAttribute("type"); Base::Type type = Base::Type::fromName(TypeName); GeometryPersistenceExtension *newE = static_cast(type.createInstance()); - newE->Restore(reader); + if (newE) { + newE->Restore(reader); - extensions.push_back(std::shared_ptr(newE)); + extensions.push_back(std::shared_ptr(newE)); + } + else { + Base::Console().Warning("Cannot restore geometry extension of type: %s\n", TypeName); + } } reader.readEndElement("GeoExtensions"); diff --git a/src/Mod/Sketcher/App/SketchObjectPy.xml b/src/Mod/Sketcher/App/SketchObjectPy.xml index ff6fc48cc4..d47884a050 100644 --- a/src/Mod/Sketcher/App/SketchObjectPy.xml +++ b/src/Mod/Sketcher/App/SketchObjectPy.xml @@ -11,129 +11,354 @@ FatherNamespace="Part"> - With this objects you can handle sketches + Represents a sketch object - solve the actual set of geometry and constraints + +Solve the sketch and update the geometry. + +solve() + + Returns: + 0 in case of success, otherwise the following codes in this order of + priority: + -4 if over-constrained, + -3 if conflicting constraints, + -5 if malformed constraints + -1 if solver error, + -2 if redundant constraints. + - add a geometric object to the sketch + +Add geometric objects to the sketch. + +addGeometry(geo:Geometry, isConstruction=False) -> int + Add a single geometric object to the sketch. + + Args: + geo: The geometry to add. e.g. a Part.LineSegement + isConstruction: Whether the added geometry is a "construction geometry". + Defaults to `False`, i.e. by omitting, a regular geometry is added. + + Returns: + The zero-based index of the newly added geometry. + +addGeometry(geo:List(Geometry), isConstruction=False) -> Tuple(int) + Add many geometric objects to the sketch. + + Args: + geo: The geometry to add. + isConstruction: see above. + + Returns: + A tuple of zero-based indices of all newly added geometry. + - delete a geometric object from the sketch + +Delete a geometric object from the sketch. + +delGeometry(geoId:int) + + Args: + geoId: The zero-based index of the geometry to delete. + Any internal alignment geometry thereof will be deleted, too. + - delete a list of geometric objects from the sketch, including any internal alignment geometry thereof + +Delete a list of geometric objects from the sketch. + +delGeometries(geoIds:List(int)) + + Args: + geoId: A list of zero-based indices of the geometry to delete. + Any internal alignment geometry thereof will be deleted, too. + - delete all the geometry objects and constraints from the sketch except external geometry + +Delete all the geometry objects from the sketch, except external geometry. + +deleteAllGeometry() + - delete all the constraints from the sketch + +Delete all the constraints from the sketch. + +deleteAllConstraints() + - switch a geometry to a construction line + +Toggles a geometry between regular and construction. + +toggleConstruction(geoId:int) + + Args: + geoId: The zero-based index of the geometry to toggle. + - set construction mode of a geometry on or off + +Set construction mode of a geometry. + +setConstruction(geoId:int, state:bool) + + Args: + geoId: The zero-based index of the geometry to configure. + state: `True` configures the geometry to "construction geometry", + `False` configures it to regular geometry. + - returns the construction mode of a geometry + +Determine whether the given geometry is a "construction geometry". + +getConstruction(geoId:int) + + Args: + geoId: The zero-based index of the geometry to query. + + Returns: + `True` if the geometry is "construction geometry" and + `False` if it s a regular geometry. + - add a constraint to the sketch + +Add constraints to the sketch. + +addConstraint(constraint:Constraint) -> int + Add a single constraint to the sketch and solves it. + + Returns: + The zero-based index of the newly added constraint. + +addConstraint(constraints:List(Constraint)) -> Tuple(int) + Add many constraints to the sketch without solving. + + Returns: + A tuple of zero-based indices of all newly added constraints. + - delete a constraint from the sketch + +Delete a constraint from the sketch. + +delConstraint(constraintIndex:int) + + Args: + constraintIndex: The zero-based index of the constraint to delete. + - Rename a constraint of the sketch + +Rename a constraint in the sketch. + +renameConstraint(constraintIndex:int, name:str) + + Args: + constraintIndex: The zero-based index of the constraint to rename. + name: The new name for the constraint. + An empty string makes the constraint "unnamed" again. + -Get the index of the constraint by name. -If there is no such constraint an exception is raised. +Get the index of a constraint by name. + +getIndexByName(name:str) + + Args: + name: The name for the constraint to look up. + If there is no such constraint an exception is raised. - copy another sketch's geometry and constraints + +Copy another sketch's geometry and constraints into this sketch. + +carbonCopy(objName:str, asConstruction=True) + + Args: + ObjName: The name of the sketch object to copy from. + asConstruction: Whether to copy the geometry as "construction geometry". + - add a link to an external geometry to use it in a constraint + +Add a link to an external geometry. + +addExternal(objName:str, subName:str) + + Args: + objName: The name of the document object to reference. + subName: The name of the sub-element of the object's shape to link as + "external geometry". + - delete a external geometry link from the sketch + +Delete an external geometry link from the sketch. + +delExternal(extGeoId:int) + + Args: + extGeoId: The zero-based index of the external geometry to remove. + - delete coincident constraints associated with a sketch point + +Delete coincident constraints associated with a sketch point. + +delConstraintOnPoint(vertexId:int) + + Args: + vertexId: A zero-based index of the shape's vertices. + +delConstraintOnPoint(geoId:int, pointPos:int) + + Args: + geoId: The zero-based index of the geometry that contains the point. + pointPos: Enum denoting which point on the geometry is meant: + 1: the start of a line or bounded curve. + 2: the end of a line or bounded curve. + 3: the center of a circle or ellipse. + - set the Datum of a Distance or Angle constraint + +Set the value of a datum constraint (e.g. Distance or Angle) + +setDatum(constraint, value) + + Args: + constraint (int or str): The index or name of the constraint to set. + value (float or Quantity): The value to set for the constraint. When + using floats, values for linear dimensions are interpreted as + millimeter, angular ones as radians. + - Get the value of a datum constraint + +Get the value of a datum constraint (e.g. Distance or Angle) + +getDatum(constraint) -> Quantity + + Args: + constraint (int or str): The index or name of the constraint to query. + + Returns: + The value of the constraint. + - set the Driving status of a datum constraint + +Set the Driving status of a datum constraint. + +setDriving(constraintIndex:int, state:bool) + + Args: + constraintIndex: The zero-based index of the constraint to configure. + state: `True` sets the constraint to driving, + `False` configures it as non-driving, i.e. reference. + - set the Driving status of datum constraints + +Set the Driving status of all datum constraints. + +setDatumsDriving(state:bool) + + Args: + state: `True` set all datum constraints to driving, + `False` configures them as non-driving, i.e. reference. + - Moves all datum constraints to the end of the constraint list + +Moves all datum constraints to the end of the constraint list. + +moveDatumsToEnd() + + Warning: This method reorders the constraint indices. Previously hold + numeric references to constraints may reference different constraints + after this operation. + - Get the Driving status of a datum constraint + +Get the Driving status of a datum constraint. + +getDriving(constraintIndex:int) + + Args: + constraintIndex: The zero-based index of the constraint to query. + + Returns: + `True` if the constraint is driving, + `False` if it is non-driving, i.e. reference. + - toggle the Driving status of a datum constraint + +Toggle the Driving status of a datum constraint. + +toggleDriving(constraintIndex:int) + + Args: + constraintIndex: The zero-based index of the constraint to toggle. + @@ -153,17 +378,44 @@ If there is no such constraint an exception is raised. - sets the constraint on/off (enforced or not) + +Activates or deactivates a constraint (enforce it or not). + +setActive(constraintIndex:int, state:bool) + + Args: + constraintIndex: The zero-based index of the constraint to configure. + state: `True` sets the constraint to active i.e. enforced, + `False` configures it as inactive, i.e. not enforced. + - Get the constraint status (enforced or not) + +Get whether a constraint is active, i.e. enforced, or not. + +getActive(constraintIndex:int) + + Args: + constraintIndex: The zero-based index of the constraint to query. + + Returns: + `True` if the constraint is active, i.e. enforced, + `False` if it is inactive, i.e. not enforced. + - toggle the active status of constraint (enforced or not) + +Toggle the constraint between active (enforced) and inactive. + +toggleActive(constraintIndex:int) + + Args: + constraintIndex: The zero-based index of the constraint to toggle. + diff --git a/src/Mod/Sketcher/Gui/CommandConstraints.cpp b/src/Mod/Sketcher/Gui/CommandConstraints.cpp index 6fc7f6b1d2..b9ef7c96d4 100644 --- a/src/Mod/Sketcher/Gui/CommandConstraints.cpp +++ b/src/Mod/Sketcher/Gui/CommandConstraints.cpp @@ -138,7 +138,8 @@ void finishDatumConstraint(Gui::Command* cmd, if (lastConstraintType == Radius || lastConstraintType == Diameter) { const Part::Geometry* geo = sketch->getGeometry(ConStr[i]->First); - if (geo && geo->getTypeId() == Part::GeomCircle::getClassTypeId()) { + + if (geo && isCircle(*geo)) { ConStr[i]->LabelPosition = labelPosition; } } @@ -182,13 +183,7 @@ void showNoConstraintBetweenFixedGeometry(const App::DocumentObject* obj) bool isGeoConcentricCompatible(const Part::Geometry* geo) { - if (geo->getTypeId() == Part::GeomEllipse::getClassTypeId() - || geo->getTypeId() == Part::GeomArcOfEllipse::getClassTypeId() - || geo->getTypeId() == Part::GeomCircle::getClassTypeId() - || geo->getTypeId() == Part::GeomArcOfCircle::getClassTypeId()) { - return true; - } - return false; + return (isEllipse(*geo) || isArcOfEllipse(*geo) || isCircle(*geo) || isArcOfCircle(*geo)); } /// Makes a simple tangency constraint using extra point + tangent via point @@ -213,16 +208,16 @@ void SketcherGui::makeTangentToEllipseviaNewPoint(Sketcher::SketchObject* Obj, Base::Vector3d center2; - if (geom2->getTypeId() == Part::GeomEllipse::getClassTypeId()) { + if (isEllipse(*geom2)) { center2 = (static_cast(geom2))->getCenter(); } - else if (geom2->getTypeId() == Part::GeomArcOfEllipse::getClassTypeId()) { + else if (isArcOfEllipse(*geom2)) { center2 = (static_cast(geom2))->getCenter(); } - else if (geom2->getTypeId() == Part::GeomCircle::getClassTypeId()) { + else if (isCircle(*geom2)) { center2 = (static_cast(geom2))->getCenter(); } - else if (geom2->getTypeId() == Part::GeomArcOfCircle::getClassTypeId()) { + else if (isArcOfCircle(*geom2)) { center2 = (static_cast(geom2))->getCenter(); } @@ -296,13 +291,13 @@ void SketcherGui::makeTangentToArcOfEllipseviaNewPoint(Sketcher::SketchObject* O Base::Vector3d center2; - if (geom2->getTypeId() == Part::GeomArcOfEllipse::getClassTypeId()) { + if (isArcOfEllipse(*geom2)) { center2 = (static_cast(geom2))->getCenter(); } - else if (geom2->getTypeId() == Part::GeomCircle::getClassTypeId()) { + else if (isCircle(*geom2)) { center2 = (static_cast(geom2))->getCenter(); } - else if (geom2->getTypeId() == Part::GeomArcOfCircle::getClassTypeId()) { + else if (isArcOfCircle(*geom2)) { center2 = (static_cast(geom2))->getCenter(); } @@ -379,28 +374,28 @@ void SketcherGui::makeTangentToArcOfHyperbolaviaNewPoint(Sketcher::SketchObject* Base::Vector3d center2; - if (geom2->getTypeId() == Part::GeomArcOfHyperbola::getClassTypeId()) { - const Part::GeomArcOfHyperbola* aoh2 = static_cast(geom2); + if (isArcOfHyperbola(*geom2)) { + auto aoh2 = static_cast(geom2); Base::Vector3d dirmaj2 = aoh2->getMajorAxisDir(); double majord2 = aoh2->getMajorRadius(); double minord2 = aoh2->getMinorRadius(); double df2 = sqrt(majord2 * majord2 + minord2 * minord2); center2 = aoh2->getCenter() + df2 * dirmaj2;// positive focus } - else if (geom2->getTypeId() == Part::GeomArcOfEllipse::getClassTypeId()) { + else if (isArcOfEllipse(*geom2)) { center2 = (static_cast(geom2))->getCenter(); } - else if (geom2->getTypeId() == Part::GeomEllipse::getClassTypeId()) { + else if (isEllipse(*geom2)) { center2 = (static_cast(geom2))->getCenter(); } - else if (geom2->getTypeId() == Part::GeomCircle::getClassTypeId()) { + else if (isCircle(*geom2)) { center2 = (static_cast(geom2))->getCenter(); } - else if (geom2->getTypeId() == Part::GeomArcOfCircle::getClassTypeId()) { + else if (isArcOfCircle(*geom2)) { center2 = (static_cast(geom2))->getCenter(); } - else if (geom2->getTypeId() == Part::GeomLineSegment::getClassTypeId()) { - const Part::GeomLineSegment* l2 = static_cast(geom2); + else if (isLineSegment(*geom2)) { + auto l2 = static_cast(geom2); center2 = (l2->getStartPoint() + l2->getEndPoint()) / 2; } @@ -470,31 +465,31 @@ void SketcherGui::makeTangentToArcOfParabolaviaNewPoint(Sketcher::SketchObject* Base::Vector3d center2; - if (geom2->getTypeId() == Part::GeomArcOfParabola::getClassTypeId()) { + if (isArcOfParabola(*geom2)) { center2 = (static_cast(geom2))->getFocus(); } - else if (geom2->getTypeId() == Part::GeomArcOfHyperbola::getClassTypeId()) { - const Part::GeomArcOfHyperbola* aoh2 = static_cast(geom2); + else if (isArcOfHyperbola(*geom2)) { + auto aoh2 = static_cast(geom2); Base::Vector3d dirmaj2 = aoh2->getMajorAxisDir(); double majord2 = aoh2->getMajorRadius(); double minord2 = aoh2->getMinorRadius(); double df2 = sqrt(majord2 * majord2 + minord2 * minord2); center2 = aoh2->getCenter() + df2 * dirmaj2;// positive focus } - else if (geom2->getTypeId() == Part::GeomArcOfEllipse::getClassTypeId()) { + else if (isArcOfEllipse(*geom2)) { center2 = (static_cast(geom2))->getCenter(); } - else if (geom2->getTypeId() == Part::GeomEllipse::getClassTypeId()) { + else if (isEllipse(*geom2)) { center2 = (static_cast(geom2))->getCenter(); } - else if (geom2->getTypeId() == Part::GeomCircle::getClassTypeId()) { + else if (isCircle(*geom2)) { center2 = (static_cast(geom2))->getCenter(); } - else if (geom2->getTypeId() == Part::GeomArcOfCircle::getClassTypeId()) { + else if (isArcOfCircle(*geom2)) { center2 = (static_cast(geom2))->getCenter(); } - else if (geom2->getTypeId() == Part::GeomLineSegment::getClassTypeId()) { - const Part::GeomLineSegment* l2 = static_cast(geom2); + else if (isLineSegment(*geom2)) { + auto l2 = static_cast(geom2); center2 = (l2->getStartPoint() + l2->getEndPoint()) / 2; } @@ -552,11 +547,8 @@ void SketcherGui::doEndpointTangency(Sketcher::SketchObject* Obj, const Part::Geometry* geom1 = Obj->getGeometry(GeoId1); const Part::Geometry* geom2 = Obj->getGeometry(GeoId2); - if (geom1 && geom2 - && (geom1->getTypeId() == Part::GeomBSplineCurve::getClassTypeId() - || geom2->getTypeId() == Part::GeomBSplineCurve::getClassTypeId())) { - - if (geom1->getTypeId() != Part::GeomBSplineCurve::getClassTypeId()) { + if (geom1 && geom2 && (isBSplineCurve(*geom1) || isBSplineCurve(*geom2))) { + if (! isBSplineCurve(*geom1)) { std::swap(GeoId1, GeoId2); std::swap(PosId1, PosId2); } @@ -1114,7 +1106,6 @@ public: s_pts(s_pts), s_lns(s_lns), s_cir(s_cir), s_ell(s_ell) {} ~GeomSelectionSizes() {} - bool hasPoints() const { return s_pts > 0; } bool hasLines() const { return s_lns > 0; } bool hasCirclesOrArcs() const { return s_cir > 0; } @@ -1332,7 +1323,6 @@ public: } } - if (selIdPair.GeoId == GeoEnum::GeoUndef) { // If mouse is released on "blank" space, finalize and start over finalizeCommand(); @@ -1554,20 +1544,21 @@ protected: void makeCts_1Point(bool& selAllowed, Base::Vector2d onSketchPos) { - //Lock, autodistance + //distance, lock if (availableConstraint == AvailableConstraint::FIRST) { + restartCommand(QT_TRANSLATE_NOOP("Command", "Add 'Distance to origin' constraint")); + createDistanceConstrain(selPoints[0].GeoId, selPoints[0].PosId, Sketcher::GeoEnum::RtPnt, Sketcher::PointPos::start, onSketchPos); + selAllowed = true; + } + if (availableConstraint == AvailableConstraint::SECOND) { restartCommand(QT_TRANSLATE_NOOP("Command", "Add lock constraint")); specialConstraint = SpecialConstraint::Block; createDistanceXYConstrain(Sketcher::DistanceX, selPoints[0].GeoId, selPoints[0].PosId, Sketcher::GeoEnum::RtPnt, Sketcher::PointPos::start, onSketchPos); createDistanceXYConstrain(Sketcher::DistanceY, selPoints[0].GeoId, selPoints[0].PosId, Sketcher::GeoEnum::RtPnt, Sketcher::PointPos::start, onSketchPos); - selAllowed = true; - } - if (availableConstraint == AvailableConstraint::SECOND) { - restartCommand(QT_TRANSLATE_NOOP("Command", "Add 'Distance to origin' constraint")); - createDistanceConstrain(selPoints[0].GeoId, selPoints[0].PosId, Sketcher::GeoEnum::RtPnt, Sketcher::PointPos::start, onSketchPos); availableConstraint = AvailableConstraint::RESET; } } + void makeCts_2Point(bool& selAllowed, Base::Vector2d onSketchPos) { //distance, horizontal, vertical @@ -1586,6 +1577,7 @@ protected: availableConstraint = AvailableConstraint::RESET; } } + void makeCts_1Point1Line(bool& selAllowed, Base::Vector2d onSketchPos) { //distance, Symmetry @@ -1600,6 +1592,7 @@ protected: availableConstraint = AvailableConstraint::RESET; } } + void makeCts_3Point(bool& selAllowed, size_t s_pts) { //Horizontal, vertical, symmetry @@ -1622,6 +1615,7 @@ protected: availableConstraint = AvailableConstraint::RESET; } } + void makeCts_4MorePoint(bool& selAllowed, size_t s_pts) { //Horizontal, vertical @@ -1640,6 +1634,7 @@ protected: availableConstraint = AvailableConstraint::RESET; } } + void makeCts_2Point1Line(bool& selAllowed, Base::Vector2d onSketchPos, size_t s_pts) { //symmetry, distances @@ -1656,6 +1651,7 @@ protected: availableConstraint = AvailableConstraint::RESET; } } + void makeCts_3MorePoint1Line(bool& selAllowed, Base::Vector2d onSketchPos, size_t s_pts) { //distances @@ -1668,17 +1664,20 @@ protected: availableConstraint = AvailableConstraint::RESET; } } + void makeCts_1Point1Circle(bool& selAllowed, Base::Vector2d onSketchPos) { //Distance. For now only circles not arcs! const Part::Geometry* geom = Obj->getGeometry(selCircleArc[0].GeoId); - if (availableConstraint == AvailableConstraint::FIRST && geom->getTypeId() == Part::GeomCircle::getClassTypeId()) { + + if (availableConstraint == AvailableConstraint::FIRST && isCircle(*geom)) { restartCommand(QT_TRANSLATE_NOOP("Command", "Add length constraint")); createDistanceConstrain(selPoints[0].GeoId, selPoints[0].PosId, selCircleArc[0].GeoId, selCircleArc[0].PosId, onSketchPos); selAllowed = true; availableConstraint = AvailableConstraint::RESET; } } + void makeCts_1MorePoint1Ellipse(bool& selAllowed) { Q_UNUSED(selAllowed) @@ -1724,6 +1723,7 @@ protected: selAllowed = true; } } + void makeCts_2Line(bool& selAllowed, Base::Vector2d onSketchPos) { //angle (if parallel: Distance (see in createAngleConstrain)), equal. @@ -1743,8 +1743,8 @@ protected: } availableConstraint = AvailableConstraint::RESET; } - } + void makeCts_3MoreLine(bool& selAllowed, size_t s_lns) { //equality. @@ -1757,17 +1757,20 @@ protected: availableConstraint = AvailableConstraint::RESET; } } + void makeCts_1Line1Circle(bool& selAllowed, Base::Vector2d onSketchPos) { //Distance. For now only circles not arcs! const Part::Geometry* geom = Obj->getGeometry(selCircleArc[0].GeoId); - if (availableConstraint == AvailableConstraint::FIRST && geom->getTypeId() == Part::GeomCircle::getClassTypeId()) { + + if (availableConstraint == AvailableConstraint::FIRST && isCircle(*geom)) { restartCommand(QT_TRANSLATE_NOOP("Command", "Add length constraint")); createDistanceConstrain(selCircleArc[0].GeoId, selCircleArc[0].PosId, selLine[0].GeoId, selLine[0].PosId, onSketchPos); //Line second parameter selAllowed = true; availableConstraint = AvailableConstraint::RESET; } } + void makeCts_1Line2Circle(bool& selAllowed) { //symmetry. @@ -1778,6 +1781,7 @@ protected: availableConstraint = AvailableConstraint::RESET; } } + void makeCts_1Line1Ellipse(bool& selAllowed) { Q_UNUSED(selAllowed) @@ -1795,6 +1799,7 @@ protected: createRadiusDiameterConstrain(selCircleArc[0].GeoId, onSketchPos); selAllowed = true; } + void makeCts_2Circle(bool& selAllowed, Base::Vector2d onSketchPos) { //Distance, radial distance, equality @@ -1802,7 +1807,7 @@ protected: const Part::Geometry* geom = Obj->getGeometry(selCircleArc[0].GeoId); const Part::Geometry* geom2 = Obj->getGeometry(selCircleArc[1].GeoId); if (availableConstraint == AvailableConstraint::FIRST) { - if (geom->getTypeId() == Part::GeomCircle::getClassTypeId() && geom2->getTypeId() == Part::GeomCircle::getClassTypeId()) { + if (isCircle(*geom) && isCircle(*geom2)) { restartCommand(QT_TRANSLATE_NOOP("Command", "Add length constraint")); createDistanceConstrain(selCircleArc[0].GeoId, selCircleArc[0].PosId, selCircleArc[1].GeoId, selCircleArc[1].PosId, onSketchPos); } @@ -1826,8 +1831,8 @@ protected: createEqualityConstrain(selCircleArc[0].GeoId, selCircleArc[1].GeoId); availableConstraint = AvailableConstraint::RESET; } - } + void makeCts_3MoreCircle(bool& selAllowed, size_t s_cir) { //equality. @@ -1840,6 +1845,7 @@ protected: availableConstraint = AvailableConstraint::RESET; } } + void makeCts_1Circle1Ellipse(bool& selAllowed) { Q_UNUSED(selAllowed) @@ -1855,6 +1861,7 @@ protected: //One ellipse or arc of ellipse/hyperbola/parabola - no constrain to attribute selAllowed = true; } + void makeCts_2MoreEllipse(bool& selAllowed, size_t s_ell) { //only ellipse or arc of of same kind, then equality of all radius. @@ -1889,15 +1896,16 @@ protected: Base::Vector3d pnt = Obj->getPoint(GeoId1, PosId1); double ActDist = 0.; const Part::Geometry* geom = Obj->getGeometry(GeoId2); - if (geom->getTypeId() == Part::GeomLineSegment::getClassTypeId()) { - const Part::GeomLineSegment* lineSeg = static_cast(geom); + + if (isLineSegment(*geom)) { + auto lineSeg = static_cast(geom); Base::Vector3d pnt1 = lineSeg->getStartPoint(); Base::Vector3d pnt2 = lineSeg->getEndPoint(); Base::Vector3d d = pnt2 - pnt1; ActDist = std::abs(-pnt.x * d.y + pnt.y * d.x + pnt1.x * pnt2.y - pnt2.x * pnt1.y) / d.Length(); } - else if (geom->getTypeId() == Part::GeomCircle::getClassTypeId()) { - const Part::GeomCircle* circle = static_cast(geom); + else if (isCircle(*geom)) { + auto circle = static_cast(geom); Base::Vector3d ct = circle->getCenter(); Base::Vector3d di = ct - pnt; ActDist = std::abs(di.Length() - circle->getRadius()); @@ -1910,8 +1918,7 @@ protected: const Part::Geometry* geo1 = Obj->getGeometry(GeoId1); const Part::Geometry* geo2 = Obj->getGeometry(GeoId2); - if (geo1->getTypeId() == Part::GeomCircle::getClassTypeId() - && geo2->getTypeId() == Part::GeomLineSegment::getClassTypeId()) { // Circle - line case + if (isCircle(*geo1) && isLineSegment(*geo2)) { // Circle - line case auto circleSeg = static_cast(geo1); double radius = circleSeg->getRadius(); Base::Vector3d center = circleSeg->getCenter(); @@ -1928,8 +1935,7 @@ protected: Gui::cmdAppObjectArgs(Obj, "addConstraint(Sketcher.Constraint('Distance',%d,%d,%f))", GeoId1, GeoId2, ActDist); } - else if (geo1->getTypeId() == Part::GeomCircle::getClassTypeId() - && geo2->getTypeId() == Part::GeomCircle::getClassTypeId()) { // Circle - circle case + else if (isCircle(*geo1) && isCircle(*geo2)) { // Circle - circle case auto circleSeg1 = static_cast(geo1); double radius1 = circleSeg1->getRadius(); Base::Vector3d center1 = circleSeg1->getCenter(); @@ -2017,16 +2023,17 @@ protected: void createRadiusDiameterConstrain(int GeoId, Base::Vector2d onSketchPos) { double radius = 0.0; - bool isCircle = true; + bool isCircleGeom = true; const Part::Geometry* geom = Obj->getGeometry(GeoId); - if (geom && geom->getTypeId() == Part::GeomArcOfCircle::getClassTypeId()) { - const Part::GeomArcOfCircle* arc = static_cast(geom); + + if (geom && isArcOfCircle(*geom)) { + auto arc = static_cast(geom); radius = arc->getRadius(); - isCircle = false; + isCircleGeom = false; } - else if (geom && geom->getTypeId() == Part::GeomCircle::getClassTypeId()) { - const Part::GeomCircle* circle = static_cast(geom); + else if (geom && isCircle(*geom)) { + auto circle = static_cast(geom); radius = circle->getRadius(); } @@ -2047,8 +2054,8 @@ protected: if ((firstCstr && dimensioningRadius && !dimensioningDiameter) || (!firstCstr && !dimensioningRadius && dimensioningDiameter) || - (firstCstr && dimensioningRadius && dimensioningDiameter && !isCircle) || - (!firstCstr && dimensioningRadius && dimensioningDiameter && isCircle) ) { + (firstCstr && dimensioningRadius && dimensioningDiameter && !isCircleGeom) || + (!firstCstr && dimensioningRadius && dimensioningDiameter && isCircleGeom) ) { Gui::cmdAppObjectArgs(Obj, "addConstraint(Sketcher.Constraint('Radius',%d,%f)) ", GeoId, radius); } @@ -2096,14 +2103,12 @@ protected: const Part::Geometry* geo1 = Obj->getGeometry(GeoId1); const Part::Geometry* geo2 = Obj->getGeometry(GeoId2); - if ((geo1->getTypeId() == Part::GeomLineSegment::getClassTypeId() && geo2->getTypeId() != Part::GeomLineSegment::getClassTypeId()) || - (geo1->getTypeId() == Part::GeomArcOfHyperbola::getClassTypeId() && geo2->getTypeId() != Part::GeomArcOfHyperbola::getClassTypeId()) || - (geo1->getTypeId() == Part::GeomArcOfParabola::getClassTypeId() && geo2->getTypeId() != Part::GeomArcOfParabola::getClassTypeId()) || - (isBsplinePole(geo1) && !isBsplinePole(geo2)) || - ((geo1->getTypeId() == Part::GeomCircle::getClassTypeId() || geo1->getTypeId() == Part::GeomArcOfCircle::getClassTypeId()) && - !(geo2->getTypeId() == Part::GeomCircle::getClassTypeId() || geo2->getTypeId() == Part::GeomArcOfCircle::getClassTypeId())) || - ((geo1->getTypeId() == Part::GeomEllipse::getClassTypeId() || geo1->getTypeId() == Part::GeomArcOfEllipse::getClassTypeId()) && - !(geo2->getTypeId() == Part::GeomEllipse::getClassTypeId() || geo2->getTypeId() == Part::GeomArcOfEllipse::getClassTypeId()))) { + if ((isLineSegment(*geo1) && ! isLineSegment(*geo2)) + || (isArcOfHyperbola(*geo1) && ! isArcOfHyperbola(*geo2)) + || (isArcOfParabola(*geo1) && ! isArcOfParabola(*geo2)) + || (isBsplinePole(geo1) && !isBsplinePole(geo2)) + || ((isCircle(*geo1) || isArcOfCircle(*geo1)) && !(isCircle(*geo2) || isArcOfCircle(*geo2))) + || ((isEllipse(*geo1) || isArcOfEllipse(*geo1)) && !(isEllipse(*geo2) || isArcOfEllipse(*geo2)))) { Gui::TranslatedUserWarning(Obj, QObject::tr("Wrong selection"), @@ -2119,10 +2124,10 @@ protected: void createAngleConstrain(int GeoId1, int GeoId2, Base::Vector2d onSketchPos) { const Part::Geometry* geom1 = Obj->getGeometry(GeoId1); const Part::Geometry* geom2 = Obj->getGeometry(GeoId2); - if (geom1->getTypeId() == Part::GeomLineSegment::getClassTypeId() && - geom2->getTypeId() == Part::GeomLineSegment::getClassTypeId()) { - const Part::GeomLineSegment* lineSeg1 = static_cast(geom1); - const Part::GeomLineSegment* lineSeg2 = static_cast(geom2); + + if (isLineSegment(*geom1) && isLineSegment(*geom2)) { + auto lineSeg1 = static_cast(geom1); + auto lineSeg2 = static_cast(geom2); // find the two closest line ends Sketcher::PointPos PosId1 = Sketcher::PointPos::none; @@ -2211,7 +2216,6 @@ protected: void createVerticalConstrain(int GeoId1, Sketcher::PointPos PosId1, int GeoId2, Sketcher::PointPos PosId2) { if (selLine.size() == 1) { Gui::cmdAppObjectArgs(sketchgui->getObject(), "addConstraint(Sketcher.Constraint('Vertical',%d)) ", GeoId1); - } else { //2points if (areBothPointsOrSegmentsFixed(Obj, GeoId1, GeoId2)) { @@ -2237,12 +2241,14 @@ protected: numberOfConstraintsCreated++; tryAutoRecompute(Obj); } + void createBlockConstrain(int GeoId) { Gui::cmdAppObjectArgs(sketchgui->getObject(), "addConstraint(Sketcher.Constraint('Block',%d)) ", GeoId); numberOfConstraintsCreated++; tryAutoRecompute(Obj); } + bool isHorizontalVerticalBlock(int GeoId) { const std::vector< Sketcher::Constraint* >& vals = Obj->Constraints.getValues(); @@ -2272,7 +2278,8 @@ protected: } const Part::Geometry* geom = Obj->getGeometry(GeoId3); - if (geom->getTypeId() == Part::GeomLineSegment::getClassTypeId()) { + + if (isLineSegment(*geom)) { if (GeoId1 == GeoId2 && GeoId2 == GeoId3) { Gui::TranslatedUserWarning(Obj, QObject::tr("Wrong selection"), @@ -2373,7 +2380,6 @@ protected: else { createDistanceConstrain(selPoints[0].GeoId, selPoints[0].PosId, selPoints[1].GeoId, selPoints[1].PosId, onSketchPos); } - } if (addedOrigin) { @@ -2525,10 +2531,10 @@ void CmdSketcherConstrainHorizontal::activated(int iMsg) Sketcher::PointPos PosId; getIdsFromName((*it), Obj, GeoId, PosId); - if (isEdge(GeoId, PosId)) {// it is an edge const Part::Geometry* geo = Obj->getGeometry(GeoId); - if (geo->getTypeId() != Part::GeomLineSegment::getClassTypeId()) { + + if (! isLineSegment(*geo)) { Gui::TranslatedUserWarning(Obj, QObject::tr("Impossible constraint"), QObject::tr("The selected edge is not a line segment.")); @@ -2646,7 +2652,8 @@ void CmdSketcherConstrainHorizontal::applyConstraint(std::vector& sel int CrvId = selSeq.front().GeoId; if (CrvId != -1) { const Part::Geometry* geo = Obj->getGeometry(CrvId); - if (geo->getTypeId() != Part::GeomLineSegment::getClassTypeId()) { + + if (! isLineSegment(*geo)) { Gui::TranslatedUserWarning( Obj, QObject::tr("Impossible constraint"), @@ -2812,10 +2819,10 @@ void CmdSketcherConstrainVertical::activated(int iMsg) Sketcher::PointPos PosId; getIdsFromName((*it), Obj, GeoId, PosId); - if (isEdge(GeoId, PosId)) {// it is an edge const Part::Geometry* geo = Obj->getGeometry(GeoId); - if (geo->getTypeId() != Part::GeomLineSegment::getClassTypeId()) { + + if (! isLineSegment(*geo)) { Gui::TranslatedUserWarning(Obj, QObject::tr("Impossible constraint"), QObject::tr("The selected edge is not a line segment.")); @@ -2933,7 +2940,8 @@ void CmdSketcherConstrainVertical::applyConstraint(std::vector& selSe int CrvId = selSeq.front().GeoId; if (CrvId != -1) { const Part::Geometry* geo = Obj->getGeometry(CrvId); - if (geo->getTypeId() != Part::GeomLineSegment::getClassTypeId()) { + + if (! isLineSegment(*geo)) { Gui::TranslatedUserWarning( Obj, QObject::tr("Impossible constraint"), @@ -3575,7 +3583,6 @@ public: return true; } - if (GeoId1 == GeoEnum::GeoUndef) { GeoId1 = GeoId_temp; PosId1 = PosId_temp; @@ -3743,7 +3750,6 @@ bool CmdSketcherConstrainCoincident::substituteConstraintCombinations(SketchObje } } - return false; } @@ -4099,9 +4105,9 @@ void CmdSketcherConstrainDistance::activated(int iMsg) } Base::Vector3d pnt = Obj->getPoint(GeoId1, PosId1); const Part::Geometry* geom = Obj->getGeometry(GeoId2); - if (geom->getTypeId() == Part::GeomLineSegment::getClassTypeId()) { - const Part::GeomLineSegment* lineSeg; - lineSeg = static_cast(geom); + + if (isLineSegment(*geom)) { + auto lineSeg = static_cast(geom); Base::Vector3d pnt1 = lineSeg->getStartPoint(); Base::Vector3d pnt2 = lineSeg->getEndPoint(); Base::Vector3d d = pnt2 - pnt1; @@ -4134,9 +4140,8 @@ void CmdSketcherConstrainDistance::activated(int iMsg) return; } - else if (geom->getTypeId() == Part::GeomCircle::getClassTypeId()) { - const Part::GeomCircle* circleSeg; - circleSeg = static_cast(geom); + else if (isCircle(*geom)) { + auto circleSeg = static_cast(geom); Base::Vector3d ct = circleSeg->getCenter(); Base::Vector3d d = ct - pnt; double ActDist = std::abs(d.Length() - circleSeg->getRadius()); @@ -4170,9 +4175,8 @@ void CmdSketcherConstrainDistance::activated(int iMsg) else if (isEdge(GeoId1, PosId1) && isEdge(GeoId2, PosId2)) { const Part::Geometry* geom1 = Obj->getGeometry(GeoId1); const Part::Geometry* geom2 = Obj->getGeometry(GeoId2); - if (geom1->getTypeId() == Part::GeomCircle::getClassTypeId() - && geom2->getTypeId() - == Part::GeomCircle::getClassTypeId()) {// circle to circle distance + + if (isCircle(*geom1) && isCircle(*geom2)) {// circle to circle distance auto circleSeg1 = static_cast(geom1); double radius1 = circleSeg1->getRadius(); Base::Vector3d center1 = circleSeg1->getCenter(); @@ -4221,13 +4225,10 @@ void CmdSketcherConstrainDistance::activated(int iMsg) return; } - else if ((geom1->getTypeId() == Part::GeomCircle::getClassTypeId() - && geom2->getTypeId() == Part::GeomLineSegment::getClassTypeId()) - || (geom1->getTypeId() == Part::GeomLineSegment::getClassTypeId() - && geom2->getTypeId() - == Part::GeomCircle::getClassTypeId())) {// circle to line distance + else if ((isCircle(*geom1) && isLineSegment(*geom2)) + || (isLineSegment(*geom1) && isCircle(*geom2))) {// circle to line distance - if (geom1->getTypeId() == Part::GeomLineSegment::getClassTypeId()) { + if (isLineSegment(*geom1)) { std::swap(geom1, geom2);// Assume circle is first std::swap(GeoId1, GeoId2); } @@ -4281,9 +4282,9 @@ void CmdSketcherConstrainDistance::activated(int iMsg) arebothpointsorsegmentsfixed = isPointOrSegmentFixed(Obj, GeoId1); const Part::Geometry* geom = Obj->getGeometry(GeoId1); - if (geom->getTypeId() == Part::GeomLineSegment::getClassTypeId()) { - const Part::GeomLineSegment* lineSeg; - lineSeg = static_cast(geom); + + if (isLineSegment(*geom)) { + auto lineSeg = static_cast(geom); double ActLength = (lineSeg->getEndPoint() - lineSeg->getStartPoint()).Length(); openCommand(QT_TRANSLATE_NOOP("Command", "Add length constraint")); @@ -4405,9 +4406,9 @@ void CmdSketcherConstrainDistance::applyConstraint(std::vector& selSe arebothpointsorsegmentsfixed = isPointOrSegmentFixed(Obj, GeoId1); const Part::Geometry* geom = Obj->getGeometry(GeoId1); - if (geom->getTypeId() == Part::GeomLineSegment::getClassTypeId()) { - const Part::GeomLineSegment* lineSeg; - lineSeg = static_cast(geom); + + if (isLineSegment(*geom)) { + auto lineSeg = static_cast(geom); double ActLength = (lineSeg->getEndPoint() - lineSeg->getStartPoint()).Length(); openCommand(QT_TRANSLATE_NOOP("Command", "Add length constraint")); @@ -4428,7 +4429,7 @@ void CmdSketcherConstrainDistance::applyConstraint(std::vector& selSe finishDatumConstraint(this, Obj, true); } } - else if (geom->getTypeId() == Part::GeomCircle::getClassTypeId()) { + else if (isCircle(*geom)) { // allow this selection but do nothing as it needs 2 circles or 1 circle and 1 line } else { @@ -4452,9 +4453,9 @@ void CmdSketcherConstrainDistance::applyConstraint(std::vector& selSe Base::Vector3d pnt = Obj->getPoint(GeoId1, PosId1); const Part::Geometry* geom = Obj->getGeometry(GeoId2); - if (geom->getTypeId() == Part::GeomLineSegment::getClassTypeId()) { - const Part::GeomLineSegment* lineSeg; - lineSeg = static_cast(geom); + + if (isLineSegment(*geom)) { + auto lineSeg = static_cast(geom); Base::Vector3d pnt1 = lineSeg->getStartPoint(); Base::Vector3d pnt2 = lineSeg->getEndPoint(); Base::Vector3d d = pnt2 - pnt1; @@ -4490,9 +4491,8 @@ void CmdSketcherConstrainDistance::applyConstraint(std::vector& selSe GeoId2 = selSeq.at(1).GeoId; const Part::Geometry* geom1 = Obj->getGeometry(GeoId1); const Part::Geometry* geom2 = Obj->getGeometry(GeoId2); - if (geom1->getTypeId() == Part::GeomCircle::getClassTypeId() - && geom2->getTypeId() - == Part::GeomCircle::getClassTypeId()) {// circle to circle distance + + if (isCircle(*geom1) && isCircle(*geom2)) {// circle to circle distance auto circleSeg1 = static_cast(geom1); double radius1 = circleSeg1->getRadius(); Base::Vector3d center1 = circleSeg1->getCenter(); @@ -4947,7 +4947,8 @@ void CmdSketcherConstrainDistanceX::activated(int iMsg) arebothpointsorsegmentsfixed = isPointOrSegmentFixed(Obj, GeoId1); const Part::Geometry* geom = Obj->getGeometry(GeoId1); - if (geom->getTypeId() == Part::GeomLineSegment::getClassTypeId()) { + + if (isLineSegment(*geom)) { // convert to as if two endpoints of the line have been selected PosId1 = Sketcher::PointPos::start; GeoId2 = GeoId1; @@ -5017,7 +5018,6 @@ void CmdSketcherConstrainDistanceX::activated(int iMsg) static_cast(PosId1), ActX); - if (arebothpointsorsegmentsfixed || constraintCreationMode == Reference) { // it is a constraint on a external line, make it non-driving const std::vector& ConStr = Obj->Constraints.getValues(); @@ -5039,7 +5039,6 @@ void CmdSketcherConstrainDistanceX::activated(int iMsg) Obj, QObject::tr("Wrong selection"), QObject::tr("Select exactly one line or up to two points from the sketch.")); - return; } @@ -5070,7 +5069,8 @@ void CmdSketcherConstrainDistanceX::applyConstraint(std::vector& selS PosId2 = Sketcher::PointPos::end; const Part::Geometry* geom = Obj->getGeometry(GeoId1); - if (geom->getTypeId() != Part::GeomLineSegment::getClassTypeId()) { + + if (! isLineSegment(*geom)) { Gui::TranslatedUserWarning( Obj, QObject::tr("Wrong selection"), @@ -5248,7 +5248,8 @@ void CmdSketcherConstrainDistanceY::activated(int iMsg) arebothpointsorsegmentsfixed = isPointOrSegmentFixed(Obj, GeoId1); const Part::Geometry* geom = Obj->getGeometry(GeoId1); - if (geom->getTypeId() == Part::GeomLineSegment::getClassTypeId()) { + + if (isLineSegment(*geom)) { // convert to as if two endpoints of the line have been selected PosId1 = Sketcher::PointPos::start; GeoId2 = GeoId1; @@ -5339,7 +5340,6 @@ void CmdSketcherConstrainDistanceY::activated(int iMsg) Obj, QObject::tr("Wrong selection"), QObject::tr("Select exactly one line or up to two points from the sketch.")); - return; } @@ -5370,7 +5370,8 @@ void CmdSketcherConstrainDistanceY::applyConstraint(std::vector& selS PosId2 = Sketcher::PointPos::end; const Part::Geometry* geom = Obj->getGeometry(GeoId1); - if (geom->getTypeId() != Part::GeomLineSegment::getClassTypeId()) { + + if (! isLineSegment(*geom)) { Gui::TranslatedUserWarning( Obj, QObject::tr("Wrong selection"), @@ -5541,11 +5542,11 @@ void CmdSketcherConstrainParallel::activated(int iMsg) // Check that the curve is a line segment const Part::Geometry* geo = Obj->getGeometry(GeoId); - if (geo->getTypeId() != Part::GeomLineSegment::getClassTypeId()) { + + if (! isLineSegment(*geo)) { Gui::TranslatedUserWarning(Obj, QObject::tr("Wrong selection"), QObject::tr("The selected edge is not a valid line.")); - return; } ids.push_back(GeoId); @@ -5583,9 +5584,7 @@ void CmdSketcherConstrainParallel::applyConstraint(std::vector& selSe int GeoId1 = selSeq.at(0).GeoId, GeoId2 = selSeq.at(1).GeoId; // Check that the curves are line segments - if (Obj->getGeometry(GeoId1)->getTypeId() != Part::GeomLineSegment::getClassTypeId() - || Obj->getGeometry(GeoId2)->getTypeId() - != Part::GeomLineSegment::getClassTypeId()) { + if (! isLineSegment(*(Obj->getGeometry(GeoId1))) || ! isLineSegment(*(Obj->getGeometry(GeoId2)))) { Gui::TranslatedUserWarning(Obj, QObject::tr("Wrong selection"), QObject::tr("The selected edge is not a valid line.")); @@ -5801,7 +5800,6 @@ void CmdSketcherConstrainPerpendicular::activated(int iMsg) QObject::tr("With 3 objects, there must be 2 curves and 1 point.")); } else if (SubNames.size() == 2) { - if (isVertex(GeoId1, PosId1) && isVertex(GeoId2, PosId2)) {// endpoint-to-endpoint perpendicularity @@ -5818,11 +5816,8 @@ void CmdSketcherConstrainPerpendicular::activated(int iMsg) const Part::Geometry* geom1 = Obj->getGeometry(GeoId1); const Part::Geometry* geom2 = Obj->getGeometry(GeoId2); - if (geom1 && geom2 - && (geom1->getTypeId() == Part::GeomBSplineCurve::getClassTypeId() - || geom2->getTypeId() == Part::GeomBSplineCurve::getClassTypeId())) { - - if (geom1->getTypeId() != Part::GeomBSplineCurve::getClassTypeId()) { + if (geom1 && geom2 && (isBSplineCurve(*geom1) || isBSplineCurve(*geom2))) { + if (! isBSplineCurve(*geom1)) { std::swap(GeoId1, GeoId2); std::swap(PosId1, PosId2); } @@ -5860,7 +5855,7 @@ void CmdSketcherConstrainPerpendicular::activated(int iMsg) const Part::Geometry* geom2 = Obj->getGeometry(GeoId2); - if (geom2 && geom2->getTypeId() == Part::GeomBSplineCurve::getClassTypeId()) { + if (geom2 && isBSplineCurve(*geom2)) { // unsupported until normal to B-spline at any point implemented. Gui::TranslatedUserWarning( Obj, @@ -5898,8 +5893,7 @@ void CmdSketcherConstrainPerpendicular::activated(int iMsg) return; } - if (geo1->getTypeId() != Part::GeomLineSegment::getClassTypeId() - && geo2->getTypeId() != Part::GeomLineSegment::getClassTypeId()) { + if (! isLineSegment(*geo1) && ! isLineSegment(*geo2)) { Gui::TranslatedUserWarning( Obj, QObject::tr("Wrong selection"), @@ -5907,9 +5901,7 @@ void CmdSketcherConstrainPerpendicular::activated(int iMsg) return; } - if (geo1->getTypeId() == Part::GeomBSplineCurve::getClassTypeId() - || geo2->getTypeId() == Part::GeomBSplineCurve::getClassTypeId()) { - + if (isBSplineCurve(*geo1) || isBSplineCurve(*geo2)) { // unsupported until tangent to B-spline at any point implemented. Gui::TranslatedUserWarning( Obj, @@ -5918,7 +5910,7 @@ void CmdSketcherConstrainPerpendicular::activated(int iMsg) return; } - if (geo1->getTypeId() == Part::GeomLineSegment::getClassTypeId()) { + if (isLineSegment(*geo1)) { std::swap(GeoId1, GeoId2); } @@ -5934,11 +5926,7 @@ void CmdSketcherConstrainPerpendicular::activated(int iMsg) geo1 = Obj->getGeometry(GeoId1); geo2 = Obj->getGeometry(GeoId2); - if (geo1->getTypeId() == Part::GeomEllipse::getClassTypeId() - || geo1->getTypeId() == Part::GeomArcOfEllipse::getClassTypeId() - || geo1->getTypeId() == Part::GeomArcOfHyperbola::getClassTypeId() - || geo1->getTypeId() == Part::GeomArcOfParabola::getClassTypeId()) { - + if (isEllipse(*geo1) || isArcOfEllipse(*geo1) || isArcOfHyperbola(*geo1) || isArcOfParabola(*geo1)) { Base::Vector3d center; Base::Vector3d majdir; Base::Vector3d focus; @@ -5946,39 +5934,32 @@ void CmdSketcherConstrainPerpendicular::activated(int iMsg) double minord = 0; double phi = 0; - if (geo1->getTypeId() == Part::GeomEllipse::getClassTypeId()) { - const Part::GeomEllipse* ellipse = static_cast(geo1); - + if (isEllipse(*geo1)) { + auto ellipse = static_cast(geo1); center = ellipse->getCenter(); majord = ellipse->getMajorRadius(); minord = ellipse->getMinorRadius(); majdir = ellipse->getMajorAxisDir(); phi = atan2(majdir.y, majdir.x); } - else if (geo1->getTypeId() == Part::GeomArcOfEllipse::getClassTypeId()) { - const Part::GeomArcOfEllipse* aoe = - static_cast(geo1); - + else if (isArcOfEllipse(*geo1)) { + auto aoe = static_cast(geo1); center = aoe->getCenter(); majord = aoe->getMajorRadius(); minord = aoe->getMinorRadius(); majdir = aoe->getMajorAxisDir(); phi = atan2(majdir.y, majdir.x); } - else if (geo1->getTypeId() == Part::GeomArcOfHyperbola::getClassTypeId()) { - const Part::GeomArcOfHyperbola* aoh = - static_cast(geo1); - + else if (isArcOfHyperbola(*geo1)) { + auto aoh = static_cast(geo1); center = aoh->getCenter(); majord = aoh->getMajorRadius(); minord = aoh->getMinorRadius(); majdir = aoh->getMajorAxisDir(); phi = atan2(majdir.y, majdir.x); } - else if (geo1->getTypeId() == Part::GeomArcOfParabola::getClassTypeId()) { - const Part::GeomArcOfParabola* aop = - static_cast(geo1); - + else if (isArcOfParabola(*geo1)) { + auto aop = static_cast(geo1); center = aop->getCenter(); focus = aop->getFocus(); } @@ -5988,7 +5969,7 @@ void CmdSketcherConstrainPerpendicular::activated(int iMsg) Base::Vector3d point1 = line->getStartPoint(); Base::Vector3d PoO; - if (geo1->getTypeId() == Part::GeomArcOfHyperbola::getClassTypeId()) { + if (isArcOfHyperbola(*geo1)) { double df = sqrt(majord * majord + minord * minord); Base::Vector3d direction = point1 - (center + majdir * df);// towards the focus double tapprox = atan2(direction.y, direction.x) - phi; @@ -5999,7 +5980,7 @@ void CmdSketcherConstrainPerpendicular::activated(int iMsg) + minord * sinh(tapprox) * cos(phi), 0); } - else if (geo1->getTypeId() == Part::GeomArcOfParabola::getClassTypeId()) { + else if (isArcOfParabola(*geo1)) { Base::Vector3d direction = point1 - focus;// towards the focus PoO = point1 + direction / 2; @@ -6039,7 +6020,6 @@ void CmdSketcherConstrainPerpendicular::activated(int iMsg) GeoIdPoint, static_cast(Sketcher::PointPos::start), GeoId2); - // add constraint: Perpendicular-via-point Gui::cmdAppObjectArgs( Obj, @@ -6114,8 +6094,7 @@ void CmdSketcherConstrainPerpendicular::applyConstraint(std::vector& return; } - if (geo1->getTypeId() != Part::GeomLineSegment::getClassTypeId() - && geo2->getTypeId() != Part::GeomLineSegment::getClassTypeId()) { + if (! isLineSegment(*geo1) && ! isLineSegment(*geo2)) { Gui::TranslatedUserWarning( Obj, QObject::tr("Wrong selection"), @@ -6123,19 +6102,16 @@ void CmdSketcherConstrainPerpendicular::applyConstraint(std::vector& return; } - if (geo1->getTypeId() == Part::GeomBSplineCurve::getClassTypeId() - || geo2->getTypeId() == Part::GeomBSplineCurve::getClassTypeId()) { - + if (isBSplineCurve(*geo1) || isBSplineCurve(*geo2)) { // unsupported until tangent to B-spline at any point implemented. Gui::TranslatedUserWarning( Obj, QObject::tr("Wrong selection"), QObject::tr("Perpendicular to B-spline edge currently unsupported.")); - return; } - if (geo1->getTypeId() == Part::GeomLineSegment::getClassTypeId()) { + if (isLineSegment(*geo1)) { std::swap(GeoId1, GeoId2); } @@ -6151,11 +6127,7 @@ void CmdSketcherConstrainPerpendicular::applyConstraint(std::vector& geo1 = Obj->getGeometry(GeoId1); geo2 = Obj->getGeometry(GeoId2); - if (geo1->getTypeId() == Part::GeomEllipse::getClassTypeId() - || geo1->getTypeId() == Part::GeomArcOfEllipse::getClassTypeId() - || geo1->getTypeId() == Part::GeomArcOfHyperbola::getClassTypeId() - || geo1->getTypeId() == Part::GeomArcOfParabola::getClassTypeId()) { - + if (isEllipse(*geo1) || isArcOfEllipse(*geo1) || isArcOfHyperbola(*geo1) || isArcOfParabola(*geo1)) { Base::Vector3d center; Base::Vector3d majdir; Base::Vector3d focus; @@ -6163,39 +6135,32 @@ void CmdSketcherConstrainPerpendicular::applyConstraint(std::vector& double minord = 0; double phi = 0; - if (geo1->getTypeId() == Part::GeomEllipse::getClassTypeId()) { - const Part::GeomEllipse* ellipse = static_cast(geo1); - + if (isEllipse(*geo1)) { + auto ellipse = static_cast(geo1); center = ellipse->getCenter(); majord = ellipse->getMajorRadius(); minord = ellipse->getMinorRadius(); majdir = ellipse->getMajorAxisDir(); phi = atan2(majdir.y, majdir.x); } - else if (geo1->getTypeId() == Part::GeomArcOfEllipse::getClassTypeId()) { - const Part::GeomArcOfEllipse* aoe = - static_cast(geo1); - + else if (isArcOfEllipse(*geo1)) { + auto aoe = static_cast(geo1); center = aoe->getCenter(); majord = aoe->getMajorRadius(); minord = aoe->getMinorRadius(); majdir = aoe->getMajorAxisDir(); phi = atan2(majdir.y, majdir.x); } - else if (geo1->getTypeId() == Part::GeomArcOfHyperbola::getClassTypeId()) { - const Part::GeomArcOfHyperbola* aoh = - static_cast(geo1); - + else if (isArcOfHyperbola(*geo1)) { + auto aoh = static_cast(geo1); center = aoh->getCenter(); majord = aoh->getMajorRadius(); minord = aoh->getMinorRadius(); majdir = aoh->getMajorAxisDir(); phi = atan2(majdir.y, majdir.x); } - else if (geo1->getTypeId() == Part::GeomArcOfParabola::getClassTypeId()) { - const Part::GeomArcOfParabola* aop = - static_cast(geo1); - + else if (isArcOfParabola(*geo1)) { + auto aop = static_cast(geo1); center = aop->getCenter(); focus = aop->getFocus(); } @@ -6205,7 +6170,7 @@ void CmdSketcherConstrainPerpendicular::applyConstraint(std::vector& Base::Vector3d point1 = line->getStartPoint(); Base::Vector3d PoO; - if (geo1->getTypeId() == Part::GeomArcOfHyperbola::getClassTypeId()) { + if (isArcOfHyperbola(*geo1)) { double df = sqrt(majord * majord + minord * minord); Base::Vector3d direction = point1 - (center + majdir * df);// towards the focus double tapprox = atan2(direction.y, direction.x) - phi; @@ -6216,7 +6181,7 @@ void CmdSketcherConstrainPerpendicular::applyConstraint(std::vector& + minord * sinh(tapprox) * cos(phi), 0); } - else if (geo1->getTypeId() == Part::GeomArcOfParabola::getClassTypeId()) { + else if (isArcOfParabola(*geo1)) { Base::Vector3d direction = point1 - focus;// towards the focus PoO = point1 + direction / 2; @@ -6275,7 +6240,6 @@ void CmdSketcherConstrainPerpendicular::applyConstraint(std::vector& Gui::Command::abortCommand(); } - tryAutoRecompute(Obj); getSelection().clearSelection(); @@ -6335,7 +6299,6 @@ void CmdSketcherConstrainPerpendicular::applyConstraint(std::vector& Obj, QObject::tr("Wrong selection"), QObject::tr("Select an edge that is not a B-spline weight.")); - return; } @@ -6557,7 +6520,6 @@ void CmdSketcherConstrainTangent::activated(int iMsg) Gui::TranslatedUserWarning(Obj, QObject::tr("Wrong selection"), QObject::tr("Wrong number of selected objects!")); - return; } @@ -6592,7 +6554,6 @@ void CmdSketcherConstrainTangent::activated(int iMsg) Obj, QObject::tr("Wrong selection"), QObject::tr("Select an edge that is not a B-spline weight.")); - return; } @@ -6671,13 +6632,13 @@ void CmdSketcherConstrainTangent::activated(int iMsg) if (isBsplineKnot(Obj, GeoId1)) { const Part::Geometry* geom2 = Obj->getGeometry(GeoId2); - if (!geom2 || geom2->getTypeId() != Part::GeomLineSegment::getClassTypeId()) { + + if (! geom2 || ! isLineSegment(*geom2)) { Gui::TranslatedUserWarning( Obj, QObject::tr("Wrong selection"), QObject::tr("Tangent constraint at B-spline knot is only supported " "with lines!")); - return; } } @@ -6686,7 +6647,6 @@ void CmdSketcherConstrainTangent::activated(int iMsg) Obj, QObject::tr("Wrong selection"), QObject::tr("Cannot add a tangency constraint at an unconnected point!")); - return; } } @@ -6710,7 +6670,8 @@ void CmdSketcherConstrainTangent::activated(int iMsg) if (isSimpleVertex(Obj, GeoId1, PosId1)) { if (isBsplineKnot(Obj, GeoId1)) { const Part::Geometry* geom2 = Obj->getGeometry(GeoId2); - if (!geom2 || geom2->getTypeId() != Part::GeomLineSegment::getClassTypeId()) { + + if (!geom2 || ! isLineSegment(*geom2)) { Gui::TranslatedUserWarning( Obj, QObject::tr("Wrong selection"), @@ -6724,20 +6685,18 @@ void CmdSketcherConstrainTangent::activated(int iMsg) Obj, QObject::tr("Wrong selection"), QObject::tr("Cannot add a tangency constraint at an unconnected point!")); - return; } } const Part::Geometry* geom2 = Obj->getGeometry(GeoId2); - if (geom2 && geom2->getTypeId() == Part::GeomBSplineCurve::getClassTypeId()) { + if (geom2 && isBSplineCurve(*geom2)) { // unsupported until tangent to B-spline at any point implemented. Gui::TranslatedUserWarning( Obj, QObject::tr("Wrong selection"), QObject::tr("Tangency to B-spline edge currently unsupported.")); - return; } @@ -6746,7 +6705,6 @@ void CmdSketcherConstrainTangent::activated(int iMsg) Obj, QObject::tr("Wrong selection"), QObject::tr("Select an edge that is not a B-spline weight.")); - return; } @@ -6768,16 +6726,12 @@ void CmdSketcherConstrainTangent::activated(int iMsg) const Part::Geometry* geom1 = Obj->getGeometry(GeoId1); const Part::Geometry* geom2 = Obj->getGeometry(GeoId2); - if (geom1 && geom2 - && (geom1->getTypeId() == Part::GeomBSplineCurve::getClassTypeId() - || geom2->getTypeId() == Part::GeomBSplineCurve::getClassTypeId())) { - + if (geom1 && geom2 && (isBSplineCurve(*geom1) || isBSplineCurve(*geom2))) { // unsupported until tangent to B-spline at any point implemented. Gui::TranslatedUserWarning( Obj, QObject::tr("Wrong selection"), QObject::tr("Tangency to B-spline edge currently unsupported.")); - return; } @@ -6786,7 +6740,6 @@ void CmdSketcherConstrainTangent::activated(int iMsg) Obj, QObject::tr("Wrong selection"), QObject::tr("Select an edge that is not a B-spline weight.")); - return; } @@ -6798,11 +6751,8 @@ void CmdSketcherConstrainTangent::activated(int iMsg) return; } - if (geom1 && geom2 - && (geom1->getTypeId() == Part::GeomEllipse::getClassTypeId() - || geom2->getTypeId() == Part::GeomEllipse::getClassTypeId())) { - - if (geom1->getTypeId() != Part::GeomEllipse::getClassTypeId()) { + if (geom1 && geom2 && (isEllipse(*geom1) || isEllipse(*geom2))) { + if (! isEllipse(*geom1)) { std::swap(GeoId1, GeoId2); } @@ -6810,11 +6760,7 @@ void CmdSketcherConstrainTangent::activated(int iMsg) geom1 = Obj->getGeometry(GeoId1); geom2 = Obj->getGeometry(GeoId2); - if (geom2->getTypeId() == Part::GeomEllipse::getClassTypeId() - || geom2->getTypeId() == Part::GeomArcOfEllipse::getClassTypeId() - || geom2->getTypeId() == Part::GeomCircle::getClassTypeId() - || geom2->getTypeId() == Part::GeomArcOfCircle::getClassTypeId()) { - + if (isEllipse(*geom2) || isArcOfEllipse(*geom2) || isCircle(*geom2) || isArcOfCircle(*geom2)) { Gui::Command::openCommand( QT_TRANSLATE_NOOP("Command", "Add tangent constraint point")); makeTangentToEllipseviaNewPoint(Obj, @@ -6825,7 +6771,7 @@ void CmdSketcherConstrainTangent::activated(int iMsg) getSelection().clearSelection(); return; } - else if (geom2->getTypeId() == Part::GeomArcOfHyperbola::getClassTypeId()) { + else if (isArcOfHyperbola(*geom2)) { Gui::Command::openCommand( QT_TRANSLATE_NOOP("Command", "Add tangent constraint point")); makeTangentToArcOfHyperbolaviaNewPoint( @@ -6837,7 +6783,7 @@ void CmdSketcherConstrainTangent::activated(int iMsg) getSelection().clearSelection(); return; } - else if (geom2->getTypeId() == Part::GeomArcOfParabola::getClassTypeId()) { + else if (isArcOfParabola(*geom2)) { Gui::Command::openCommand( QT_TRANSLATE_NOOP("Command", "Add tangent constraint point")); makeTangentToArcOfParabolaviaNewPoint( @@ -6850,11 +6796,8 @@ void CmdSketcherConstrainTangent::activated(int iMsg) return; } } - else if (geom1 && geom2 - && (geom1->getTypeId() == Part::GeomArcOfEllipse::getClassTypeId() - || geom2->getTypeId() == Part::GeomArcOfEllipse::getClassTypeId())) { - - if (geom1->getTypeId() != Part::GeomArcOfEllipse::getClassTypeId()) { + else if (geom1 && geom2 && (isArcOfEllipse(*geom1) || isArcOfEllipse(*geom2))) { + if (! isArcOfEllipse(*geom1)) { std::swap(GeoId1, GeoId2); } @@ -6862,11 +6805,8 @@ void CmdSketcherConstrainTangent::activated(int iMsg) geom1 = Obj->getGeometry(GeoId1); geom2 = Obj->getGeometry(GeoId2); - if (geom2->getTypeId() == Part::GeomArcOfHyperbola::getClassTypeId() - || geom2->getTypeId() == Part::GeomArcOfEllipse::getClassTypeId() - || geom2->getTypeId() == Part::GeomCircle::getClassTypeId() - || geom2->getTypeId() == Part::GeomArcOfCircle::getClassTypeId() - || geom2->getTypeId() == Part::GeomLineSegment::getClassTypeId()) { + if (isArcOfHyperbola(*geom2) || isArcOfEllipse(*geom2) + || isCircle(*geom2) || isArcOfCircle(*geom2) || isLineSegment(*geom2)) { Gui::Command::openCommand( QT_TRANSLATE_NOOP("Command", "Add tangent constraint point")); @@ -6880,7 +6820,7 @@ void CmdSketcherConstrainTangent::activated(int iMsg) getSelection().clearSelection(); return; } - else if (geom2->getTypeId() == Part::GeomArcOfParabola::getClassTypeId()) { + else if (isArcOfParabola(*geom2)) { Gui::Command::openCommand( QT_TRANSLATE_NOOP("Command", "Add tangent constraint point")); makeTangentToArcOfParabolaviaNewPoint( @@ -6893,11 +6833,8 @@ void CmdSketcherConstrainTangent::activated(int iMsg) return; } } - else if (geom1 && geom2 - && (geom1->getTypeId() == Part::GeomArcOfHyperbola::getClassTypeId() - || geom2->getTypeId() == Part::GeomArcOfHyperbola::getClassTypeId())) { - - if (geom1->getTypeId() != Part::GeomArcOfHyperbola::getClassTypeId()) { + else if (geom1 && geom2 && (isArcOfHyperbola(*geom1) || isArcOfHyperbola(*geom2))) { + if (! isArcOfHyperbola(*geom1)) { std::swap(GeoId1, GeoId2); } @@ -6905,11 +6842,8 @@ void CmdSketcherConstrainTangent::activated(int iMsg) geom1 = Obj->getGeometry(GeoId1); geom2 = Obj->getGeometry(GeoId2); - if (geom2->getTypeId() == Part::GeomArcOfHyperbola::getClassTypeId() - || geom2->getTypeId() == Part::GeomArcOfEllipse::getClassTypeId() - || geom2->getTypeId() == Part::GeomCircle::getClassTypeId() - || geom2->getTypeId() == Part::GeomArcOfCircle::getClassTypeId() - || geom2->getTypeId() == Part::GeomLineSegment::getClassTypeId()) { + if (isArcOfHyperbola(*geom2) || isArcOfEllipse(*geom2) || isCircle(*geom2) + || isArcOfCircle(*geom2) || isLineSegment(*geom2)) { Gui::Command::openCommand( QT_TRANSLATE_NOOP("Command", "Add tangent constraint point")); @@ -6922,7 +6856,7 @@ void CmdSketcherConstrainTangent::activated(int iMsg) getSelection().clearSelection(); return; } - else if (geom2->getTypeId() == Part::GeomArcOfParabola::getClassTypeId()) { + else if (isArcOfParabola(*geom2)) { Gui::Command::openCommand( QT_TRANSLATE_NOOP("Command", "Add tangent constraint point")); makeTangentToArcOfParabolaviaNewPoint( @@ -6935,11 +6869,8 @@ void CmdSketcherConstrainTangent::activated(int iMsg) return; } } - else if (geom1 && geom2 - && (geom1->getTypeId() == Part::GeomArcOfParabola::getClassTypeId() - || geom2->getTypeId() == Part::GeomArcOfParabola::getClassTypeId())) { - - if (geom1->getTypeId() != Part::GeomArcOfParabola::getClassTypeId()) { + else if (geom1 && geom2 && (isArcOfParabola(*geom1) || isArcOfParabola(*geom2))) { + if (! isArcOfParabola(*geom1)) { std::swap(GeoId1, GeoId2); } @@ -6947,12 +6878,9 @@ void CmdSketcherConstrainTangent::activated(int iMsg) geom1 = Obj->getGeometry(GeoId1); geom2 = Obj->getGeometry(GeoId2); - if (geom2->getTypeId() == Part::GeomArcOfParabola::getClassTypeId() - || geom2->getTypeId() == Part::GeomArcOfHyperbola::getClassTypeId() - || geom2->getTypeId() == Part::GeomArcOfEllipse::getClassTypeId() - || geom2->getTypeId() == Part::GeomCircle::getClassTypeId() - || geom2->getTypeId() == Part::GeomArcOfCircle::getClassTypeId() - || geom2->getTypeId() == Part::GeomLineSegment::getClassTypeId()) { + if (isArcOfParabola(*geom2) || isArcOfHyperbola(*geom2) + || isArcOfEllipse(*geom2) || isCircle(*geom2) + || isArcOfCircle(*geom2) || isLineSegment(*geom2)) { Gui::Command::openCommand( QT_TRANSLATE_NOOP("Command", "Add tangent constraint point")); @@ -7011,16 +6939,12 @@ void CmdSketcherConstrainTangent::applyConstraint(std::vector& selSeq const Part::Geometry* geom1 = Obj->getGeometry(GeoId1); const Part::Geometry* geom2 = Obj->getGeometry(GeoId2); - if (geom1 && geom2 - && (geom1->getTypeId() == Part::GeomBSplineCurve::getClassTypeId() - || geom2->getTypeId() == Part::GeomBSplineCurve::getClassTypeId())) { - + if (geom1 && geom2 && (isBSplineCurve(*geom1) || isBSplineCurve(*geom2))) { // unsupported until tangent to B-spline at any point implemented. Gui::TranslatedUserWarning( Obj, QObject::tr("Wrong selection"), QObject::tr("Tangency to B-spline edge currently unsupported.")); - return; } @@ -7029,7 +6953,6 @@ void CmdSketcherConstrainTangent::applyConstraint(std::vector& selSeq Obj, QObject::tr("Wrong selection"), QObject::tr("Select an edge that is not a B-spline weight.")); - return; } @@ -7041,11 +6964,8 @@ void CmdSketcherConstrainTangent::applyConstraint(std::vector& selSeq return; } - if (geom1 && geom2 - && (geom1->getTypeId() == Part::GeomEllipse::getClassTypeId() - || geom2->getTypeId() == Part::GeomEllipse::getClassTypeId())) { - - if (geom1->getTypeId() != Part::GeomEllipse::getClassTypeId()) { + if (geom1 && geom2 && (isEllipse(*geom1) || isEllipse(*geom2))) { + if (! isEllipse(*geom1)) { std::swap(GeoId1, GeoId2); } @@ -7053,10 +6973,8 @@ void CmdSketcherConstrainTangent::applyConstraint(std::vector& selSeq geom1 = Obj->getGeometry(GeoId1); geom2 = Obj->getGeometry(GeoId2); - if (geom2->getTypeId() == Part::GeomEllipse::getClassTypeId() - || geom2->getTypeId() == Part::GeomArcOfEllipse::getClassTypeId() - || geom2->getTypeId() == Part::GeomCircle::getClassTypeId() - || geom2->getTypeId() == Part::GeomArcOfCircle::getClassTypeId()) { + if (isEllipse(*geom2) || isArcOfEllipse(*geom2) + || isCircle(*geom2) || isArcOfCircle(*geom2)) { Gui::Command::openCommand( QT_TRANSLATE_NOOP("Command", "Add tangent constraint point")); @@ -7068,7 +6986,7 @@ void CmdSketcherConstrainTangent::applyConstraint(std::vector& selSeq getSelection().clearSelection(); return; } - else if (geom2->getTypeId() == Part::GeomArcOfHyperbola::getClassTypeId()) { + else if (isArcOfHyperbola(*geom2)) { Gui::Command::openCommand( QT_TRANSLATE_NOOP("Command", "Add tangent constraint point")); makeTangentToArcOfHyperbolaviaNewPoint( @@ -7080,7 +6998,7 @@ void CmdSketcherConstrainTangent::applyConstraint(std::vector& selSeq getSelection().clearSelection(); return; } - else if (geom2->getTypeId() == Part::GeomArcOfParabola::getClassTypeId()) { + else if (isArcOfParabola(*geom2)) { Gui::Command::openCommand( QT_TRANSLATE_NOOP("Command", "Add tangent constraint point")); makeTangentToArcOfParabolaviaNewPoint( @@ -7093,11 +7011,8 @@ void CmdSketcherConstrainTangent::applyConstraint(std::vector& selSeq return; } } - else if (geom1 && geom2 - && (geom1->getTypeId() == Part::GeomArcOfHyperbola::getClassTypeId() - || geom2->getTypeId() == Part::GeomArcOfHyperbola::getClassTypeId())) { - - if (geom1->getTypeId() != Part::GeomArcOfHyperbola::getClassTypeId()) { + else if (geom1 && geom2 && (isArcOfHyperbola(*geom1) || isArcOfHyperbola(*geom2))) { + if (! isArcOfHyperbola(*geom1)) { std::swap(GeoId1, GeoId2); } @@ -7105,11 +7020,8 @@ void CmdSketcherConstrainTangent::applyConstraint(std::vector& selSeq geom1 = Obj->getGeometry(GeoId1); geom2 = Obj->getGeometry(GeoId2); - if (geom2->getTypeId() == Part::GeomArcOfHyperbola::getClassTypeId() - || geom2->getTypeId() == Part::GeomArcOfEllipse::getClassTypeId() - || geom2->getTypeId() == Part::GeomCircle::getClassTypeId() - || geom2->getTypeId() == Part::GeomArcOfCircle::getClassTypeId() - || geom2->getTypeId() == Part::GeomLineSegment::getClassTypeId()) { + if (isArcOfHyperbola(*geom2) || isArcOfEllipse(*geom2) || isCircle(*geom2) + || isArcOfCircle(*geom2) || isLineSegment(*geom2)) { Gui::Command::openCommand( QT_TRANSLATE_NOOP("Command", "Add tangent constraint point")); @@ -7122,7 +7034,7 @@ void CmdSketcherConstrainTangent::applyConstraint(std::vector& selSeq getSelection().clearSelection(); return; } - else if (geom2->getTypeId() == Part::GeomArcOfParabola::getClassTypeId()) { + else if (isArcOfParabola(*geom2)) { Gui::Command::openCommand( QT_TRANSLATE_NOOP("Command", "Add tangent constraint point")); makeTangentToArcOfParabolaviaNewPoint( @@ -7135,11 +7047,8 @@ void CmdSketcherConstrainTangent::applyConstraint(std::vector& selSeq return; } } - else if (geom1 && geom2 - && (geom1->getTypeId() == Part::GeomArcOfParabola::getClassTypeId() - || geom2->getTypeId() == Part::GeomArcOfParabola::getClassTypeId())) { - - if (geom1->getTypeId() != Part::GeomArcOfParabola::getClassTypeId()) { + else if (geom1 && geom2 && (isArcOfParabola(*geom1) || isArcOfParabola(*geom2))) { + if (! isArcOfParabola(*geom1)) { std::swap(GeoId1, GeoId2); } @@ -7147,12 +7056,8 @@ void CmdSketcherConstrainTangent::applyConstraint(std::vector& selSeq geom1 = Obj->getGeometry(GeoId1); geom2 = Obj->getGeometry(GeoId2); - if (geom2->getTypeId() == Part::GeomArcOfParabola::getClassTypeId() - || geom2->getTypeId() == Part::GeomArcOfHyperbola::getClassTypeId() - || geom2->getTypeId() == Part::GeomArcOfEllipse::getClassTypeId() - || geom2->getTypeId() == Part::GeomCircle::getClassTypeId() - || geom2->getTypeId() == Part::GeomArcOfCircle::getClassTypeId() - || geom2->getTypeId() == Part::GeomLineSegment::getClassTypeId()) { + if (isArcOfParabola(*geom2) || isArcOfHyperbola(*geom2) || isArcOfEllipse(*geom2) + || isCircle(*geom2) || isArcOfCircle(*geom2) || isLineSegment(*geom2)) { Gui::Command::openCommand( QT_TRANSLATE_NOOP("Command", "Add tangent constraint point")); @@ -7222,7 +7127,6 @@ void CmdSketcherConstrainTangent::applyConstraint(std::vector& selSeq Obj, QObject::tr("Wrong selection"), QObject::tr("Cannot add a tangency constraint at an unconnected point!")); - return; } @@ -7230,11 +7134,8 @@ void CmdSketcherConstrainTangent::applyConstraint(std::vector& selSeq const Part::Geometry* geom1 = Obj->getGeometry(GeoId1); const Part::Geometry* geom2 = Obj->getGeometry(GeoId2); - if (geom1 && geom2 - && (geom1->getTypeId() == Part::GeomBSplineCurve::getClassTypeId() - || geom2->getTypeId() == Part::GeomBSplineCurve::getClassTypeId())) { - - if (geom1->getTypeId() != Part::GeomBSplineCurve::getClassTypeId()) { + if (geom1 && geom2 && (isBSplineCurve(*geom1) || isBSplineCurve(*geom2))) { + if (! isBSplineCurve(*geom1)) { std::swap(GeoId1, GeoId2); std::swap(PosId1, PosId2); } @@ -7271,7 +7172,6 @@ void CmdSketcherConstrainTangent::applyConstraint(std::vector& selSeq Obj, QObject::tr("Wrong selection"), QObject::tr("Select an edge that is not a B-spline weight.")); - return; } @@ -7432,8 +7332,8 @@ void CmdSketcherConstrainRadius::activated(int iMsg) const Part::Geometry* geom = Obj->getGeometry(GeoId); - if (geom && geom->getTypeId() == Part::GeomArcOfCircle::getClassTypeId()) { - const Part::GeomArcOfCircle* arc = static_cast(geom); + if (geom && isArcOfCircle(*geom)) { + auto arc = static_cast(geom); double radius = arc->getRadius(); if (issegmentfixed) { @@ -7445,8 +7345,8 @@ void CmdSketcherConstrainRadius::activated(int iMsg) nonpoles = true; } - else if (geom && geom->getTypeId() == Part::GeomCircle::getClassTypeId()) { - const Part::GeomCircle* circle = static_cast(geom); + else if (geom && isCircle(*geom)) { + auto circle = static_cast(geom); double radius = circle->getRadius(); if (issegmentfixed) { @@ -7470,7 +7370,6 @@ void CmdSketcherConstrainRadius::activated(int iMsg) Obj, QObject::tr("Wrong selection"), QObject::tr("Select one or more arcs or circles from the sketch.")); - return; } @@ -7480,7 +7379,6 @@ void CmdSketcherConstrainRadius::activated(int iMsg) QObject::tr("Wrong selection"), QObject::tr("Select either only one or more B-Spline poles or only one or more arcs or " "circles from the sketch, but not mixed.")); - return; } @@ -7521,7 +7419,6 @@ void CmdSketcherConstrainRadius::activated(int iMsg) "False"); } - finishDatumConstraint(this, Obj, false, externalGeoIdRadiusMap.size()); commitNeeded = true; @@ -7623,12 +7520,13 @@ void CmdSketcherConstrainRadius::applyConstraint(std::vector& selSeq, case 1:// {SelExternalEdge} { const Part::Geometry* geom = Obj->getGeometry(GeoId); - if (geom && geom->getTypeId() == Part::GeomArcOfCircle::getClassTypeId()) { - const Part::GeomArcOfCircle* arc = static_cast(geom); + + if (geom && isArcOfCircle(*geom)) { + auto arc = static_cast(geom); radius = arc->getRadius(); } - else if (geom && geom->getTypeId() == Part::GeomCircle::getClassTypeId()) { - const Part::GeomCircle* circle = static_cast(geom); + else if (geom && isCircle(*geom)) { + auto circle = static_cast(geom); radius = circle->getRadius(); } else { @@ -7636,7 +7534,6 @@ void CmdSketcherConstrainRadius::applyConstraint(std::vector& selSeq, Obj, QObject::tr("Wrong selection"), QObject::tr("Constraint only applies to arcs or circles.")); - return; } @@ -7770,7 +7667,6 @@ void CmdSketcherConstrainDiameter::activated(int iMsg) Obj, QObject::tr("Wrong selection"), QObject::tr("Select one or more arcs or circles from the sketch.")); - return; } @@ -7797,8 +7693,8 @@ void CmdSketcherConstrainDiameter::activated(int iMsg) const Part::Geometry* geom = Obj->getGeometry(GeoId); - if (geom && geom->getTypeId() == Part::GeomArcOfCircle::getClassTypeId()) { - const Part::GeomArcOfCircle* arc = static_cast(geom); + if (geom && isArcOfCircle(*geom)) { + auto arc = static_cast(geom); double radius = arc->getRadius(); if (issegmentfixed) { @@ -7808,8 +7704,8 @@ void CmdSketcherConstrainDiameter::activated(int iMsg) geoIdDiameterMap.emplace_back(GeoId, 2 * radius); } } - else if (geom && geom->getTypeId() == Part::GeomCircle::getClassTypeId()) { - const Part::GeomCircle* circle = static_cast(geom); + else if (geom && isCircle(*geom)) { + auto circle = static_cast(geom); double radius = circle->getRadius(); if (isBsplinePole(geom)) { @@ -7835,7 +7731,6 @@ void CmdSketcherConstrainDiameter::activated(int iMsg) Obj, QObject::tr("Wrong selection"), QObject::tr("Select one or more arcs or circles from the sketch.")); - return; } @@ -7866,7 +7761,6 @@ void CmdSketcherConstrainDiameter::activated(int iMsg) finishDatumConstraint(this, Obj, false, externalGeoIdDiameterMap.size()); - commitNeeded = true; updateNeeded = true; } @@ -7949,12 +7843,13 @@ void CmdSketcherConstrainDiameter::applyConstraint(std::vector& selSe case 1:// {SelExternalEdge} { const Part::Geometry* geom = Obj->getGeometry(GeoId); - if (geom && geom->getTypeId() == Part::GeomArcOfCircle::getClassTypeId()) { - const Part::GeomArcOfCircle* arc = static_cast(geom); + + if (geom && isArcOfCircle(*geom)) { + auto arc = static_cast(geom); diameter = 2 * arc->getRadius(); } - else if (geom && geom->getTypeId() == Part::GeomCircle::getClassTypeId()) { - const Part::GeomCircle* circle = static_cast(geom); + else if (geom && isCircle(*geom)) { + auto circle = static_cast(geom); diameter = 2 * circle->getRadius(); } else { @@ -7962,7 +7857,6 @@ void CmdSketcherConstrainDiameter::applyConstraint(std::vector& selSe Obj, QObject::tr("Wrong selection"), QObject::tr("Constraint only applies to arcs or circles.")); - return; } @@ -7971,7 +7865,6 @@ void CmdSketcherConstrainDiameter::applyConstraint(std::vector& selSe Obj, QObject::tr("Wrong selection"), QObject::tr("Select an edge that is not a B-spline weight.")); - return; } @@ -8094,7 +7987,6 @@ void CmdSketcherConstrainRadiam::activated(int iMsg) Obj, QObject::tr("Wrong selection"), QObject::tr("Select one or more arcs or circles from the sketch.")); - return; } @@ -8125,13 +8017,13 @@ void CmdSketcherConstrainRadiam::activated(int iMsg) const Part::Geometry* geom = Obj->getGeometry(GeoId); double radius; - if (geom && geom->getTypeId() == Part::GeomArcOfCircle::getClassTypeId()) { - const Part::GeomArcOfCircle* arcir = static_cast(geom); + if (geom && isArcOfCircle(*geom)) { + auto arcir = static_cast(geom); radius = arcir->getRadius(); nonpoles = true; } - else if (geom && geom->getTypeId() == Part::GeomCircle::getClassTypeId()) { - const Part::GeomCircle* arcir = static_cast(geom); + else if (geom && isCircle(*geom)) { + auto arcir = static_cast(geom); radius = arcir->getRadius(); if (isBsplinePole(geom)) { poles = true; @@ -8157,7 +8049,6 @@ void CmdSketcherConstrainRadiam::activated(int iMsg) Obj, QObject::tr("Wrong selection"), QObject::tr("Select one or more arcs or circles from the sketch.")); - return; } @@ -8167,7 +8058,6 @@ void CmdSketcherConstrainRadiam::activated(int iMsg) QObject::tr("Wrong selection"), QObject::tr("Select either only one or more B-Spline poles or only one or more arcs or " "circles from the sketch, but not mixed.")); - return; } @@ -8184,8 +8074,7 @@ void CmdSketcherConstrainRadiam::activated(int iMsg) for (std::vector>::iterator it = externalGeoIdRadiamMap.begin(); it != externalGeoIdRadiamMap.end(); ++it) { - if (Obj->getGeometry(it->first)->getTypeId() - == Part::GeomArcOfCircle::getClassTypeId()) { + if (isArcOfCircle(*(Obj->getGeometry(it->first)))) { if (nonpoles) { Gui::cmdAppObjectArgs(Obj, "addConstraint(Sketcher.Constraint('Radius',%d,%f))", @@ -8245,8 +8134,7 @@ void CmdSketcherConstrainRadiam::activated(int iMsg) refGeoId, radiam); } - else if (Obj->getGeometry(refGeoId)->getTypeId() - == Part::GeomCircle::getClassTypeId()) { + else if (isCircle(*(Obj->getGeometry(refGeoId)))) { Gui::cmdAppObjectArgs(Obj, "addConstraint(Sketcher.Constraint('Diameter',%d,%f))", refGeoId, @@ -8273,8 +8161,7 @@ void CmdSketcherConstrainRadiam::activated(int iMsg) it->first, it->second); } - else if (Obj->getGeometry(it->first)->getTypeId() - == Part::GeomCircle::getClassTypeId()) { + else if (isCircle(*(Obj->getGeometry(it->first)))){ Gui::cmdAppObjectArgs(Obj, "addConstraint(Sketcher.Constraint('Diameter',%d,%f))", it->first, @@ -8322,7 +8209,7 @@ void CmdSketcherConstrainRadiam::applyConstraint(std::vector& selSeq, bool updateNeeded = false; - bool isCircle = false; + bool isCircleGeom = false; bool isPole = false; switch (seqIndex) { @@ -8330,14 +8217,15 @@ void CmdSketcherConstrainRadiam::applyConstraint(std::vector& selSeq, case 1:// {SelExternalEdge} { const Part::Geometry* geom = Obj->getGeometry(GeoId); - if (geom && geom->getTypeId() == Part::GeomArcOfCircle::getClassTypeId()) { - const Part::GeomArcOfCircle* arc = static_cast(geom); + + if (geom && isArcOfCircle(*geom)) { + auto arc = static_cast(geom); radiam = arc->getRadius(); } - else if (geom && geom->getTypeId() == Part::GeomCircle::getClassTypeId()) { - const Part::GeomCircle* circle = static_cast(geom); + else if (geom && isCircle(*geom)) { + auto circle = static_cast(geom); radiam = circle->getRadius(); - isCircle = true; + isCircleGeom= true; if (isBsplinePole(geom)) { isPole = true; } @@ -8347,7 +8235,6 @@ void CmdSketcherConstrainRadiam::applyConstraint(std::vector& selSeq, Obj, QObject::tr("Wrong selection"), QObject::tr("Constraint only applies to arcs or circles.")); - return; } @@ -8360,7 +8247,7 @@ void CmdSketcherConstrainRadiam::applyConstraint(std::vector& selSeq, GeoId, radiam); } - else if (isCircle) { + else if (isCircleGeom) { Gui::cmdAppObjectArgs(Obj, "addConstraint(Sketcher.Constraint('Diameter',%d,%f))", GeoId, @@ -8645,11 +8532,9 @@ void CmdSketcherConstrainAngle::activated(int iMsg) QObject::tr("Wrong selection"), QObject::tr( "Select one or two lines from the sketch. Or select two edges and a point.")); - return; } - int GeoId1, GeoId2 = GeoEnum::GeoUndef, GeoId3 = GeoEnum::GeoUndef; Sketcher::PointPos PosId1, PosId2 = Sketcher::PointPos::none, PosId3 = Sketcher::PointPos::none; getIdsFromName(SubNames[0], Obj, GeoId1, PosId1); @@ -8774,7 +8659,6 @@ void CmdSketcherConstrainAngle::activated(int iMsg) Obj, QObject::tr("Wrong selection"), QObject::tr("Select an edge that is not a B-spline weight.")); - return; } @@ -8782,12 +8666,10 @@ void CmdSketcherConstrainAngle::activated(int iMsg) const Part::Geometry* geom1 = Obj->getGeometry(GeoId1); const Part::Geometry* geom2 = Obj->getGeometry(GeoId2); - if (geom1->getTypeId() == Part::GeomLineSegment::getClassTypeId() - && geom2->getTypeId() == Part::GeomLineSegment::getClassTypeId()) { - const Part::GeomLineSegment* lineSeg1 = - static_cast(geom1); - const Part::GeomLineSegment* lineSeg2 = - static_cast(geom2); + + if (isLineSegment(*geom1) && isLineSegment(*geom2)) { + auto lineSeg1 = static_cast(geom1); + auto lineSeg2 = static_cast(geom2); // find the two closest line ends Sketcher::PointPos PosId1 = Sketcher::PointPos::none; @@ -8851,7 +8733,6 @@ void CmdSketcherConstrainAngle::activated(int iMsg) QObject::tr("Parallel lines"), QObject::tr( "An angle constraint cannot be set for two parallel lines.")); - return; } } @@ -8897,14 +8778,13 @@ void CmdSketcherConstrainAngle::activated(int iMsg) Obj, QObject::tr("Wrong selection"), QObject::tr("Cannot add an angle constraint on an axis!")); - return; } const Part::Geometry* geom = Obj->getGeometry(GeoId1); - if (geom->getTypeId() == Part::GeomLineSegment::getClassTypeId()) { - const Part::GeomLineSegment* lineSeg; - lineSeg = static_cast(geom); + + if (isLineSegment(*geom)) { + auto lineSeg = static_cast(geom); Base::Vector3d dir = lineSeg->getEndPoint() - lineSeg->getStartPoint(); double ActAngle = atan2(dir.y, dir.x); @@ -8930,9 +8810,8 @@ void CmdSketcherConstrainAngle::activated(int iMsg) return; } - else if (geom->getTypeId() == Part::GeomArcOfCircle::getClassTypeId()) { - const Part::GeomArcOfCircle* arc; - arc = static_cast(geom); + else if (isArcOfCircle(*geom)) { + auto arc = static_cast(geom); double startangle, endangle; arc->getRange(startangle, endangle, /*EmulateCCWXY=*/true); double angle = endangle - startangle; @@ -8966,7 +8845,6 @@ void CmdSketcherConstrainAngle::activated(int iMsg) Obj, QObject::tr("Wrong selection"), QObject::tr("Select one or two lines from the sketch. Or select two edges and a point.")); - return; } @@ -8992,12 +8870,10 @@ void CmdSketcherConstrainAngle::applyConstraint(std::vector& selSeq, const Part::Geometry* geom1 = Obj->getGeometry(GeoId1); const Part::Geometry* geom2 = Obj->getGeometry(GeoId2); - if (geom1->getTypeId() == Part::GeomLineSegment::getClassTypeId() - && geom2->getTypeId() == Part::GeomLineSegment::getClassTypeId()) { - const Part::GeomLineSegment* lineSeg1 = - static_cast(geom1); - const Part::GeomLineSegment* lineSeg2 = - static_cast(geom2); + + if (isLineSegment(*geom1) && isLineSegment(*geom2)) { + auto lineSeg1 = static_cast(geom1); + auto lineSeg2 = static_cast(geom2); // find the two closest line ends Sketcher::PointPos PosId1 = Sketcher::PointPos::none; @@ -9061,7 +8937,6 @@ void CmdSketcherConstrainAngle::applyConstraint(std::vector& selSeq, QObject::tr("Parallel lines"), QObject::tr( "An angle constraint cannot be set for two parallel lines.")); - return; } } @@ -9125,7 +9000,6 @@ void CmdSketcherConstrainAngle::applyConstraint(std::vector& selSeq, } } - bool bothexternal = areBothPointsOrSegmentsFixed(Obj, GeoId1, GeoId2); if (isEdge(GeoId1, PosId1) && isEdge(GeoId2, PosId2) && isVertex(GeoId3, PosId3)) { @@ -9135,7 +9009,6 @@ void CmdSketcherConstrainAngle::applyConstraint(std::vector& selSeq, Obj, QObject::tr("Wrong selection"), QObject::tr("Select an edge that is not a B-spline weight.")); - return; } @@ -9293,7 +9166,6 @@ void CmdSketcherConstrainEqual::activated(int iMsg) Gui::TranslatedUserWarning(Obj, QObject::tr("Wrong selection"), QObject::tr("Select at least two lines from the sketch.")); - return; } @@ -9313,7 +9185,6 @@ void CmdSketcherConstrainEqual::activated(int iMsg) Gui::TranslatedUserWarning(Obj, QObject::tr("Wrong selection"), QObject::tr("Select two or more compatible edges.")); - return; } else if (GeoId == Sketcher::GeoEnum::HAxis || GeoId == Sketcher::GeoEnum::VAxis) { @@ -9321,7 +9192,6 @@ void CmdSketcherConstrainEqual::activated(int iMsg) Obj, QObject::tr("Wrong selection"), QObject::tr("Sketch axes cannot be used in equality constraints.")); - return; } else if (isPointOrSegmentFixed(Obj, GeoId)) { @@ -9337,23 +9207,22 @@ void CmdSketcherConstrainEqual::activated(int iMsg) const Part::Geometry* geo = Obj->getGeometry(GeoId); - if (geo->getTypeId() == Part::GeomBSplineCurve::getClassTypeId()) { + if (isBSplineCurve(*geo)) { // unsupported as they are generally hereogeneus shapes Gui::TranslatedUserWarning( Obj, QObject::tr("Wrong selection"), QObject::tr("Equality for B-spline edge currently unsupported.")); - return; } - if (geo->getTypeId() == Part::GeomLineSegment::getClassTypeId()) { + if (isLineSegment(*geo)) { lineSel = true; } - else if (geo->getTypeId() == Part::GeomArcOfCircle::getClassTypeId()) { + else if (isArcOfCircle(*geo)) { arcSel = true; } - else if (geo->getTypeId() == Part::GeomCircle::getClassTypeId()) { + else if (isCircle(*geo)) { if (isBsplinePole(geo)) { weightSel = true; } @@ -9361,23 +9230,22 @@ void CmdSketcherConstrainEqual::activated(int iMsg) circSel = true; } } - else if (geo->getTypeId() == Part::GeomEllipse::getClassTypeId()) { + else if (isEllipse(*geo)) { ellipsSel = true; } - else if (geo->getTypeId() == Part::GeomArcOfEllipse::getClassTypeId()) { + else if (isArcOfEllipse(*geo)) { arcEllipsSel = true; } - else if (geo->getTypeId() == Part::GeomArcOfHyperbola::getClassTypeId()) { + else if (isArcOfHyperbola(*geo)) { hyperbSel = true; } - else if (geo->getTypeId() == Part::GeomArcOfParabola::getClassTypeId()) { + else if (isArcOfParabola(*geo)) { parabSel = true; } else { Gui::TranslatedUserWarning(Obj, QObject::tr("Wrong selection"), QObject::tr("Select two or more edges of similar type.")); - return; } @@ -9386,17 +9254,14 @@ void CmdSketcherConstrainEqual::activated(int iMsg) // Check for heterogeneous groups in selection if ((lineSel - && ((arcSel || circSel) || (ellipsSel || arcEllipsSel) || hyperbSel || parabSel - || weightSel)) - || ((arcSel || circSel) - && ((ellipsSel || arcEllipsSel) || hyperbSel || parabSel || weightSel)) + && ((arcSel || circSel) || (ellipsSel || arcEllipsSel) || hyperbSel || parabSel || weightSel)) + || ((arcSel || circSel) && ((ellipsSel || arcEllipsSel) || hyperbSel || parabSel || weightSel)) || ((ellipsSel || arcEllipsSel) && (hyperbSel || parabSel || weightSel)) || (hyperbSel && (parabSel || weightSel)) || (parabSel && weightSel)) { Gui::TranslatedUserWarning(Obj, QObject::tr("Wrong selection"), QObject::tr("Select two or more edges of similar type.")); - return; } @@ -9441,27 +9306,17 @@ void CmdSketcherConstrainEqual::applyConstraint(std::vector& selSeq, const Part::Geometry* geo1 = Obj->getGeometry(GeoId1); const Part::Geometry* geo2 = Obj->getGeometry(GeoId2); - if ((geo1->getTypeId() == Part::GeomLineSegment::getClassTypeId() - && geo2->getTypeId() != Part::GeomLineSegment::getClassTypeId()) - || (geo1->getTypeId() == Part::GeomArcOfHyperbola::getClassTypeId() - && geo2->getTypeId() != Part::GeomArcOfHyperbola::getClassTypeId()) - || (geo1->getTypeId() == Part::GeomArcOfParabola::getClassTypeId() - && geo2->getTypeId() != Part::GeomArcOfParabola::getClassTypeId()) + if ((isLineSegment(*geo1) && ! isLineSegment(*geo2)) + || (isArcOfHyperbola(*geo1) && ! isArcOfHyperbola(*geo2)) + || (isArcOfParabola(*geo1) && ! isArcOfParabola(*geo2)) || (isBsplinePole(geo1) && !isBsplinePole(geo2)) - || ((geo1->getTypeId() == Part::GeomCircle::getClassTypeId() - || geo1->getTypeId() == Part::GeomArcOfCircle::getClassTypeId()) - && !(geo2->getTypeId() == Part::GeomCircle::getClassTypeId() - || geo2->getTypeId() == Part::GeomArcOfCircle::getClassTypeId())) - || ((geo1->getTypeId() == Part::GeomEllipse::getClassTypeId() - || geo1->getTypeId() == Part::GeomArcOfEllipse::getClassTypeId()) - && !(geo2->getTypeId() == Part::GeomEllipse::getClassTypeId() - || geo2->getTypeId() == Part::GeomArcOfEllipse::getClassTypeId()))) { + || ((isCircle(*geo1) || isArcOfCircle(*geo1)) && !(isCircle(*geo2) || isArcOfCircle(*geo2))) + || ((isEllipse(*geo1) || isArcOfEllipse(*geo1)) && !(isEllipse(*geo2) || isArcOfEllipse(*geo2)))) { Gui::TranslatedUserWarning( Obj, QObject::tr("Wrong selection"), QObject::tr("Select two or more edges of similar type.")); - return; } @@ -9570,7 +9425,6 @@ void CmdSketcherConstrainSymmetric::activated(int iMsg) QObject::tr("Select two points and a symmetry line, " "two points and a symmetry point " "or a line and a symmetry point from the sketch.")); - return; } @@ -9590,13 +9444,13 @@ void CmdSketcherConstrainSymmetric::activated(int iMsg) } if (isEdge(GeoId1, PosId1) && isVertex(GeoId2, PosId2)) { const Part::Geometry* geom = Obj->getGeometry(GeoId1); - if (geom->getTypeId() == Part::GeomLineSegment::getClassTypeId()) { + + if (isLineSegment(*geom)) { if (GeoId1 == GeoId2) { Gui::TranslatedUserWarning(Obj, QObject::tr("Wrong selection"), QObject::tr("Cannot add a symmetry constraint " "between a line and its end points.")); - return; } @@ -9627,7 +9481,6 @@ void CmdSketcherConstrainSymmetric::activated(int iMsg) QObject::tr("Select two points and a symmetry line, " "two points and a symmetry point " "or a line and a symmetry point from the sketch.")); - return; } @@ -9648,16 +9501,15 @@ void CmdSketcherConstrainSymmetric::activated(int iMsg) } if (isVertex(GeoId1, PosId1) && isVertex(GeoId2, PosId2)) { - if (isEdge(GeoId3, PosId3)) { const Part::Geometry* geom = Obj->getGeometry(GeoId3); - if (geom->getTypeId() == Part::GeomLineSegment::getClassTypeId()) { + + if (isLineSegment(*geom)) { if (GeoId1 == GeoId2 && GeoId2 == GeoId3) { Gui::TranslatedUserWarning(Obj, QObject::tr("Wrong selection"), QObject::tr("Cannot add a symmetry constraint " "between a line and its end points!")); - return; } @@ -9737,7 +9589,6 @@ void CmdSketcherConstrainSymmetric::applyConstraint(std::vector& selS QObject::tr("Wrong selection"), QObject::tr( "Cannot add a symmetry constraint between a line and its end points!")); - return; } @@ -9780,13 +9631,13 @@ void CmdSketcherConstrainSymmetric::applyConstraint(std::vector& selS } const Part::Geometry* geom = Obj->getGeometry(GeoId3); - if (geom->getTypeId() == Part::GeomLineSegment::getClassTypeId()) { + + if (isLineSegment(*geom)) { if (GeoId1 == GeoId2 && GeoId2 == GeoId3) { Gui::TranslatedUserWarning(Obj, QObject::tr("Wrong selection"), QObject::tr("Cannot add a symmetry constraint " "between a line and its end points.")); - return; } @@ -9813,7 +9664,6 @@ void CmdSketcherConstrainSymmetric::applyConstraint(std::vector& selS "two points and a symmetry point " "or a line and a symmetry point from the sketch.")); } - return; } case 12:// {SelVertex, SelVertexOrRoot, SelVertex} @@ -9882,7 +9732,6 @@ void CmdSketcherConstrainSnellsLaw::activated(int iMsg) { Q_UNUSED(iMsg); - // get the selection std::vector selection = getSelection().getSelectionEx(); @@ -9916,7 +9765,6 @@ void CmdSketcherConstrainSnellsLaw::activated(int iMsg) Gui::TranslatedUserWarning(Obj, QObject::tr("Wrong selection"), QObject::tr("Number of selected objects is not 3")); - return; } @@ -9942,7 +9790,6 @@ void CmdSketcherConstrainSnellsLaw::activated(int iMsg) Obj, QObject::tr("Wrong selection"), QObject::tr("Cannot create constraint with external geometry only.")); - return; } @@ -9953,19 +9800,17 @@ void CmdSketcherConstrainSnellsLaw::activated(int iMsg) Gui::TranslatedUserWarning(Obj, QObject::tr("Wrong selection"), QObject::tr("Incompatible geometry is selected.")); - return; }; const Part::Geometry* geo = Obj->getGeometry(GeoId3); - if (geo && geo->getTypeId() == Part::GeomBSplineCurve::getClassTypeId()) { + if (geo && isBSplineCurve(*geo)) { // unsupported until normal to B-spline at any point implemented. Gui::TranslatedUserWarning( Obj, QObject::tr("Wrong selection"), QObject::tr("SnellsLaw on B-spline edge is currently unsupported.")); - return; } @@ -9973,7 +9818,6 @@ void CmdSketcherConstrainSnellsLaw::activated(int iMsg) Gui::TranslatedUserWarning(Obj, QObject::tr("Wrong selection"), QObject::tr("Select an edge that is not a B-spline weight.")); - return; } @@ -10130,7 +9974,6 @@ void CmdSketcherToggleDrivingConstraint::activated(int iMsg) Gui::TranslatedUserWarning(Obj, QObject::tr("Wrong selection"), QObject::tr("Select constraints from the sketch.")); - return; } @@ -10168,7 +10011,6 @@ void CmdSketcherToggleDrivingConstraint::activated(int iMsg) Gui::TranslatedUserWarning(Obj, QObject::tr("Wrong selection"), QObject::tr("Select constraints from the sketch.")); - return; } @@ -10258,7 +10100,6 @@ void CmdSketcherToggleActiveConstraint::activated(int iMsg) Gui::TranslatedUserWarning(Obj, QObject::tr("Wrong selection"), QObject::tr("Select constraints from the sketch.")); - return; } @@ -10301,7 +10142,6 @@ bool CmdSketcherToggleActiveConstraint::isActive() return isCreateConstraintActive(getActiveGuiDocument()); } - void CreateSketcherCommandsConstraints() { Gui::CommandManager& rcCmdMgr = Gui::Application::Instance->commandManager(); diff --git a/src/Mod/Test/BaseTests.py b/src/Mod/Test/BaseTests.py index 32e2728e11..30ec380436 100644 --- a/src/Mod/Test/BaseTests.py +++ b/src/Mod/Test/BaseTests.py @@ -638,9 +638,9 @@ class MatrixTestCase(unittest.TestCase): self.mat.setCol(0, FreeCAD.Vector(1, 0, 0)) self.mat.setRow(0, FreeCAD.Vector(1, 0, 0)) - def testTrace(self): + def testDiagonal(self): self.mat.scale(2.0, 2.0, 2.0) - self.assertEqual(self.mat.trace(), FreeCAD.Vector(2.0, 2.0, 2.0)) + self.assertEqual(self.mat.diagonal(), FreeCAD.Vector(2.0, 2.0, 2.0)) def testNumberProtocol(self): with self.assertRaises(NotImplementedError): diff --git a/tests/src/App/StringHasher.cpp b/tests/src/App/StringHasher.cpp index a8edf85116..298f8c42c3 100644 --- a/tests/src/App/StringHasher.cpp +++ b/tests/src/App/StringHasher.cpp @@ -1002,8 +1002,8 @@ TEST_F(StringIDRefTest, getPyObject) // NOLINT auto empty = App::StringIDRef(); // Act - Py::Object pyObject(ref.getPyObject()); - Py::Object none(empty.getPyObject()); + Py::Object pyObject(ref.getPyObject(), true); + Py::Object none(empty.getPyObject(), true); // Assert EXPECT_TRUE(PyObject_TypeCheck(pyObject.ptr(), &App::StringIDPy::Type)); diff --git a/tests/src/Base/Matrix.cpp b/tests/src/Base/Matrix.cpp index 96474dfd76..962267c359 100644 --- a/tests/src/Base/Matrix.cpp +++ b/tests/src/Base/Matrix.cpp @@ -1,7 +1,8 @@ #include "gtest/gtest.h" #include +#include -// NOLINTBEGIN(cppcoreguidelines-avoid-magic-numbers,readability-magic-numbers) +// NOLINTBEGIN(cppcoreguidelines-*,readability-magic-numbers) // clang-format off TEST(Matrix, TestShearing) { @@ -87,12 +88,12 @@ TEST(Matrix, TestNonUniformScaleLeftTwo) EXPECT_EQ(mat.hasScale(), Base::ScaleType::Uniform); } -TEST(Matrix, TestTrace) +TEST(Matrix, TestDiagonal) { Base::Matrix4D mat; mat.scale(2.0, 2.0, 2.0); - Base::Vector3d trace = mat.trace(); - EXPECT_EQ(trace.x + trace.y + trace.z, 6.0); + Base::Vector3d diag = mat.diagonal(); + EXPECT_EQ(diag.x + diag.y + diag.z, 6.0); } TEST(Matrix, TestColRow) @@ -263,5 +264,84 @@ TEST(Matrix, TestSubAssign) 0.0, 0.0, 0.0, 0.0}; EXPECT_EQ(mat1, mat4); } + +TEST(Matrix, TestHatOperator) +{ + Base::Vector3d vec{1.0, 2.0, 3.0}; + + Base::Matrix4D mat1; + mat1.Hat(vec); + + Base::Matrix4D mat2{0.0, -vec.z, vec.y, 0.0, + vec.z, 0.0, -vec.x, 0.0, + -vec.y, vec.x, 0.0, 0.0, + 0.0, 0.0, 0.0, 1.0}; + + EXPECT_EQ(mat1, mat2); +} + +TEST(Matrix, TestDyadic) +{ + Base::Vector3d vec{1.0, 2.0, 3.0}; + + Base::Matrix4D mat1; + mat1.Outer(vec, vec); + + Base::Matrix4D mat2{1.0, 2.0, 3.0, 0.0, + 2.0, 4.0, 6.0, 0.0, + 3.0, 6.0, 9.0, 0.0, + 0.0, 0.0, 0.0, 1.0}; + + EXPECT_EQ(mat1, mat2); +} + +TEST(Matrix, TestRotLine) +{ + Base::Vector3d axis{1.0, 2.0, 3.0}; + double angle = 1.2345; + + Base::Matrix4D mat1; + Base::Matrix4D mat2; + mat1.rotLine(axis, angle); + + Base::Rotation rot(axis, angle); + rot.getValue(mat2); + + EXPECT_EQ(mat1, mat2); +} + +TEST(Matrix, TestRotAxisFormula) //NOLINT +{ + // R = I + sin(alpha)*P + (1-cos(alpha))*P^2 + // with P = hat operator of a vector + Base::Vector3d axis{1.0, 2.0, 3.0}; + double angle = 1.2345; + + Base::Matrix4D mat1; + Base::Matrix4D mat2; + mat1.rotLine(axis, angle); + + double fsin = std::sin(angle); + double fcos = std::cos(angle); + Base::Matrix4D unit; + Base::Matrix4D hat; + Base::Matrix4D hat2; + + axis.Normalize(); + hat.Hat(axis); + + hat2 = hat * hat; + mat2 = unit + hat * fsin + hat2 * (1 - fcos); + + EXPECT_DOUBLE_EQ(mat1[0][0], mat2[0][0]); + EXPECT_DOUBLE_EQ(mat1[0][1], mat2[0][1]); + EXPECT_DOUBLE_EQ(mat1[0][2], mat2[0][2]); + EXPECT_DOUBLE_EQ(mat1[1][0], mat2[1][0]); + EXPECT_DOUBLE_EQ(mat1[1][1], mat2[1][1]); + EXPECT_DOUBLE_EQ(mat1[1][2], mat2[1][2]); + EXPECT_DOUBLE_EQ(mat1[2][0], mat2[2][0]); + EXPECT_DOUBLE_EQ(mat1[2][1], mat2[2][1]); + EXPECT_DOUBLE_EQ(mat1[2][2], mat2[2][2]); +} // clang-format on -// NOLINTEND(cppcoreguidelines-avoid-magic-numbers,readability-magic-numbers) +// NOLINTEND(cppcoreguidelines-*,readability-magic-numbers)