From 429eb0f727135fe46602fb5ceceea2b18f245a7a Mon Sep 17 00:00:00 2001 From: WandererFan Date: Mon, 28 Nov 2016 19:16:14 -0500 Subject: [PATCH] DPG improvements eliminate orientation matrix remove appl logic from dialog add 3D/Front buttons --- src/Base/Vector3D.cpp | 54 ++- src/Base/Vector3D.h | 16 +- src/Mod/TechDraw/App/DrawProjGroup.cpp | 486 +++++++++++++++----- src/Mod/TechDraw/App/DrawProjGroup.h | 55 +-- src/Mod/TechDraw/App/DrawProjGroupItem.cpp | 1 + src/Mod/TechDraw/App/DrawProjGroupItem.h | 12 + src/Mod/TechDraw/App/DrawProjGroupPyImp.cpp | 17 +- src/Mod/TechDraw/App/DrawViewPart.cpp | 1 + src/Mod/TechDraw/Gui/Command.cpp | 7 +- src/Mod/TechDraw/Gui/TaskProjGroup.cpp | 104 +++-- src/Mod/TechDraw/Gui/TaskProjGroup.h | 7 +- src/Mod/TechDraw/Gui/TaskProjGroup.ui | 362 +++++++++++---- 12 files changed, 821 insertions(+), 301 deletions(-) diff --git a/src/Base/Vector3D.cpp b/src/Base/Vector3D.cpp index 782ee4a44..e4b712b4d 100644 --- a/src/Base/Vector3D.cpp +++ b/src/Base/Vector3D.cpp @@ -24,7 +24,7 @@ #include "PreCompiled.h" #include "Tools.h" #include "Vector3D.h" - +#include "Matrix.h" using namespace Base; template @@ -96,7 +96,7 @@ Vector3<_Precision> Vector3<_Precision>::operator - (const Vector3<_Precision>& cVctRes.z = z - rcVct.z; return cVctRes; } - + template Vector3<_Precision> Vector3<_Precision>::operator - (void) const { @@ -131,7 +131,7 @@ Vector3<_Precision>& Vector3<_Precision>::operator *= (_Precision fScale) } template -Vector3<_Precision>& Vector3<_Precision>::operator /= (_Precision fDiv) +Vector3<_Precision>& Vector3<_Precision>::operator /= (_Precision fDiv) { x /= fDiv; y /= fDiv; @@ -192,9 +192,47 @@ Vector3<_Precision> Vector3<_Precision>::Cross(const Vector3<_Precision>& rcVct) return cVctRes; } +template +Matrix4D Vector3<_Precision>::Outer(const Vector3<_Precision>& rcVct) const +{ + Matrix4D mat; + mat[0][0] = x * rcVct.x; + mat[0][1] = x * rcVct.y; + mat[0][2] = x * rcVct.z; + + mat[1][0] = y * rcVct.x; + mat[1][1] = y * rcVct.y; + mat[1][2] = y * rcVct.z; + + mat[2][0] = z * rcVct.x; + mat[2][1] = z * rcVct.y; + mat[2][2] = z * rcVct.z; + + return mat; +} + +template +Matrix4D Vector3<_Precision>::Hat(void) const +{ + Matrix4D mat; + mat[0][0] = 0.0; + mat[0][1] = -z; + mat[0][2] = y; + + mat[1][0] = z; + mat[1][1] = 0.0; + mat[1][2] = -x; + + mat[2][0] = -y; + mat[2][1] = x; + mat[2][2] = 0.0; + + return mat; +} + template bool Vector3<_Precision>::operator != (const Vector3<_Precision>& rcVct) const -{ +{ return !((*this) == rcVct); } @@ -213,7 +251,7 @@ bool Vector3<_Precision>::IsEqual(const Vector3<_Precision> &rclPnt, _Precision } template -Vector3<_Precision>& Vector3<_Precision>::ProjectToPlane (const Vector3<_Precision> &rclBase, +Vector3<_Precision>& Vector3<_Precision>::ProjectToPlane (const Vector3<_Precision> &rclBase, const Vector3<_Precision> &rclNorm) { Vector3<_Precision> clTemp(rclNorm); @@ -231,7 +269,7 @@ void Vector3<_Precision>::ProjectToPlane (const Vector3 &rclBase, } template -_Precision Vector3<_Precision>::DistanceToPlane (const Vector3<_Precision> &rclBase, +_Precision Vector3<_Precision>::DistanceToPlane (const Vector3<_Precision> &rclBase, const Vector3<_Precision> &rclNorm) const { return ((*this - rclBase) * rclNorm) / rclNorm.Length(); @@ -244,7 +282,7 @@ _Precision Vector3<_Precision>::Length (void) const } template -_Precision Vector3<_Precision>::DistanceToLine (const Vector3<_Precision> &rclBase, +_Precision Vector3<_Precision>::DistanceToLine (const Vector3<_Precision> &rclBase, const Vector3<_Precision> &rclDirect) const { return (_Precision) fabs((rclDirect % Vector3(*this - rclBase)).Length() / rclDirect.Length()); @@ -401,7 +439,7 @@ _Precision Vector3<_Precision>::GetAngle (const Vector3 &rcVect) const _Precision divid, fNum; divid = Length() * ((Vector3<_Precision>&)rcVect).Length(); - + if ((divid < -1e-10f) || (divid > 1e-10f)) { fNum = (*this * rcVect) / divid; if (fNum < -1) diff --git a/src/Base/Vector3D.h b/src/Base/Vector3D.h index da39a80af..51e213559 100644 --- a/src/Base/Vector3D.h +++ b/src/Base/Vector3D.h @@ -73,6 +73,10 @@ struct float_traits { static inline float_type maximum() { return DBL_MAX; } }; +class Matrix4D; +//#include + + /** The Vector Base class. */ template class Vector3 @@ -126,6 +130,11 @@ public: Vector3 operator % (const Vector3<_Precision>& rcVct) const; /// Cross product Vector3 Cross (const Vector3<_Precision>& rcVct) const; + /// Outer product + Matrix4D Outer(const Vector3<_Precision>& rcVct) const; + /// Hat operator (skew symmetric) + Matrix4D Hat(void) const; + /// Comparing for inequality bool operator != (const Vector3<_Precision>& rcVct) const; /// Comparing for equality @@ -159,8 +168,8 @@ public: Vector3 & Normalize (void); /// Get angle between both vectors. The returned value lies in the interval [0,pi]. _Precision GetAngle (const Vector3 &rcVect) const; - /** Transforms this point to the coordinate system defined by origin \a rclBase, - * vector \a vector rclDirX and vector \a vector rclDirY. + /** Transforms this point to the coordinate system defined by origin \a rclBase, + * vector \a vector rclDirX and vector \a vector rclDirY. * \note \a rclDirX must be perpendicular to \a rclDirY, i.e. \a rclDirX * \a rclDirY = 0.. */ void TransformToCoordinateSystem (const Vector3 &rclBase, const Vector3 &rclDirX, const Vector3 &rclDirY); @@ -183,7 +192,7 @@ public: /// Projects this point onto the line given by the base \a rclPoint and the direction \a rclLine. /** * Projects a point \a rclPoint onto the line defined by the origin and the direction \a rclLine. - * The result is a vector from \a rclPoint to the point on the line. The length of this vector + * The result is a vector from \a rclPoint to the point on the line. The length of this vector * is the distance from \a rclPoint to the line. * Note: The resulting vector does not depend on the current vector. */ @@ -286,4 +295,3 @@ inline _Vec1 convertTo(const _Vec2& v) } // namespace Base #endif // BASE_VECTOR3D_H - diff --git a/src/Mod/TechDraw/App/DrawProjGroup.cpp b/src/Mod/TechDraw/App/DrawProjGroup.cpp index 9c9304b61..ebb729ad2 100644 --- a/src/Mod/TechDraw/App/DrawProjGroup.cpp +++ b/src/Mod/TechDraw/App/DrawProjGroup.cpp @@ -26,6 +26,7 @@ #ifndef _PreComp_ # include #include +#include #endif #include @@ -35,6 +36,7 @@ #include #include + #include "DrawUtil.h" #include "DrawPage.h" #include "DrawProjGroupItem.h" @@ -65,13 +67,91 @@ DrawProjGroup::DrawProjGroup(void) ADD_PROPERTY_TYPE(spacingX, (15), agroup, App::Prop_None, "Horizontal spacing between views"); ADD_PROPERTY_TYPE(spacingY, (15), agroup, App::Prop_None, "Vertical spacing between views"); - ADD_PROPERTY(viewOrientationMatrix, (Base::Matrix4D())); } DrawProjGroup::~DrawProjGroup() { } +void DrawProjGroup::onChanged(const App::Property* prop) +{ + //TODO: For some reason, when the projection type is changed, the isometric views show change appropriately, but the orthographic ones dont... Or vice-versa. why would you change from 1st to 3rd in mid drawing? + //if group hasn't been added to page yet, can't scale or distribute projItems + TechDraw::DrawPage *page = getPage(); + if (!isRestoring() && page) { + if ( prop == &Views ) { + recompute(); + } else if (prop == &Scale) { + updateChildren(Scale.getValue()); + //resetPositions(); + distributeProjections(); + } else if (prop == &Source) { + App::DocumentObject* sourceObj = Source.getValue(); + if (sourceObj != nullptr) { + if (!hasAnchor()) { + addProjection("Front"); + } + } else { + //Source has been changed to null! Why? What to do? + } + } else if (prop == &ScaleType) { + recompute(); + } else if (prop == &AutoDistribute && + AutoDistribute.getValue()) { + resetPositions(); + recompute(); + } + } + TechDraw::DrawViewCollection::onChanged(prop); +} + +App::DocumentObjectExecReturn *DrawProjGroup::execute(void) +{ + //if group hasn't been added to page yet, can't scale or distribute projItems + TechDraw::DrawPage *page = getPage(); + if (!page) { + return DrawViewCollection::execute(); + } + + App::DocumentObject* docObj = Source.getValue(); + if (docObj == nullptr) { + return DrawViewCollection::execute(); + } + + docObj = Anchor.getValue(); //must have an anchor, so create one as soon as we have a Page and Source + if (docObj == nullptr) { + docObj = addProjection("Front"); + } + + double newScale = Scale.getValue(); + if (ScaleType.isValue("Automatic")) { + //Recalculate scale if Group is too big or too small! + if (!checkFit(page)) { + newScale = calculateAutomaticScale(); + if(std::abs(Scale.getValue() - newScale) > FLT_EPSILON) { + resetPositions(); + Scale.setValue(newScale); + } + } + } else if (ScaleType.isValue("Page")) { + newScale = page->Scale.getValue(); + if(std::abs(Scale.getValue() - newScale) > FLT_EPSILON) { + resetPositions(); + Scale.setValue(newScale); + } + } else if (ScaleType.isValue("Custom")) { + //don't have to do anything special + } + + // recalculate positions for children + if (Views.getSize()) { + updateChildren(newScale); + distributeProjections(); + } + + return DrawViewCollection::execute(); +} + short DrawProjGroup::mustExecute() const { short result = 0; @@ -169,7 +249,6 @@ QRectF DrawProjGroup::getRect() const //this is current rect, not potent arrangeViewPointers(viewPtrs); double width, height; minimumBbViews(viewPtrs, width, height); // w,h of just the views at 1:1 scale - //need to add spacingX,spacingY double xSpace = spacingX.getValue() * 3.0 * std::max(1.0,Scale.getValue()); double ySpace = spacingY.getValue() * 2.0 * std::max(1.0,Scale.getValue()); double rectW = Scale.getValue() * width + xSpace; //scale the 1:1 w,h and add whitespace @@ -200,28 +279,6 @@ void DrawProjGroup::minimumBbViews(DrawProjGroupItem *viewPtrs[10], height = row0h + row1h + row2h; } -void DrawProjGroup::onChanged(const App::Property* prop) -{ - //TODO: For some reason, when the projection type is changed, the isometric views show change appropriately, but the orthographic ones dont... Or vice-versa. - //if group hasn't been added to page yet, can't scale or distribute projItems - TechDraw::DrawPage *page = getPage(); - if (!isRestoring() && page) { - if ( prop == &Views ) { - recompute(); - } else if (prop == &Scale) { - updateChildren(Scale.getValue()); - //resetPositions(); - distributeProjections(); - } else if (prop == &ScaleType) { - recompute(); - } else if (prop == &AutoDistribute && - AutoDistribute.getValue()) { - resetPositions(); - recompute(); - } - } - TechDraw::DrawViewCollection::onChanged(prop); -} void DrawProjGroup::moveToCentre(void) { @@ -247,6 +304,14 @@ App::DocumentObject * DrawProjGroup::getProjObj(const char *viewProjType) const return 0; } +DrawProjGroupItem* DrawProjGroup::getProjItem(const char *viewProjType) const +{ + App::DocumentObject* docObj = getProjObj(viewProjType); + DrawProjGroupItem* result = static_cast(docObj); + return result; +} + + bool DrawProjGroup::checkViewProjType(const char *in) { if ( strcmp(in, "Front") == 0 || @@ -288,9 +353,6 @@ App::DocumentObject * DrawProjGroup::addProjection(const char *viewProjType) std::string FeatName = getDocument()->getUniqueObjectName("ProjItem"); auto docObj( getDocument()->addObject( "TechDraw::DrawProjGroupItem", //add to Document FeatName.c_str() ) ); - if( strcmp(viewProjType,"Front") == 0 ) { - Anchor.setValue(docObj); - } view = static_cast( docObj ); view->Source.setValue( Source.getValue() ); if (ScaleType.isValue("Automatic")) { @@ -301,7 +363,17 @@ App::DocumentObject * DrawProjGroup::addProjection(const char *viewProjType) view->Scale.setValue( Scale.getValue() ); view->Type.setValue( viewProjType ); view->Label.setValue( viewProjType ); - setViewOrientation( view, viewProjType ); + if( strcmp(viewProjType,"Front") == 0 ) { + + Anchor.setValue(docObj); + view->Direction.setValue(nameToStdDirection("Front")); //just (Base::Vector3d(0.0,-1.0,0.0)) + view->recomputeFeature(); + makeInitialMap(view); + //dumpMap(); + } else { + //dumpMap(); + view->Direction.setValue(m_viewDir[viewProjType]); + } addView(view); //from DrawViewCollection - add to ProjGroup Views moveToCentre(); @@ -351,44 +423,6 @@ int DrawProjGroup::purgeProjections() return Views.getValues().size(); } -void DrawProjGroup::setViewOrientation(DrawProjGroupItem *v, const char *projType) const -{ - Base::Vector3d dir; - - // Traditional orthographic - if(strcmp(projType, "Front") == 0) { - dir.Set(0, -1, 0); - } else if(strcmp(projType, "Rear") == 0) { - dir.Set(0, 1, 0); - } else if(strcmp(projType, "Right") == 0) { - dir.Set(1, 0, 0); - } else if(strcmp(projType, "Left") == 0) { - dir.Set(-1, 0, 0); - } else if(strcmp(projType, "Top") == 0) { - dir.Set(0, 0, 1); - } else if(strcmp(projType, "Bottom") == 0) { - dir.Set(0, 0, -1); - - // Isometric - } else if(strcmp(projType, "FrontTopLeft") == 0) { - dir.Set(-1,-1,1); - dir.Normalize(); - } else if(strcmp(projType, "FrontTopRight") == 0) { - dir.Set(1, -1, 1); - dir.Normalize(); - } else if(strcmp(projType, "FrontBottomRight") == 0) { - dir.Set(1, -1, -1); - dir.Normalize(); - } else if(strcmp(projType, "FrontBottomLeft") == 0) { - dir.Set(-1, -1, -1); - dir.Normalize(); - } else { - throw Base::Exception("Unknown view type in DrawProjGroup::setViewOrientation()"); - } - dir = viewOrientationMatrix.getValue() * dir; //multiply std dir by transform matrix - v->Direction.setValue(dir); -} - void DrawProjGroup::arrangeViewPointers(DrawProjGroupItem *viewPtrs[10]) const { for (int i=0; i<10; ++i) { @@ -570,58 +604,7 @@ void DrawProjGroup::resetPositions(void) } } -//TODO: Turn this into a command so it can be issued from python -//????: this sets the orientation for all views, not just Front??? -void DrawProjGroup::setFrontViewOrientation(const Base::Matrix4D &newMat) -{ - viewOrientationMatrix.setValue(newMat); - for( auto it : Views.getValues() ) { - auto view( dynamic_cast(it) ); - if( view ) { - setViewOrientation(view, view->Type.getValueAsString()); - // TODO: Seems we should ensure that modifying the view triggers this automatically? IR - view->touch(); - } - } -} - -App::DocumentObjectExecReturn *DrawProjGroup::execute(void) -{ - //if group hasn't been added to page yet, can't scale or distribute projItems - TechDraw::DrawPage *page = getPage(); - if (!page) { - return DrawViewCollection::execute(); - } - - double newScale = Scale.getValue(); - if (ScaleType.isValue("Automatic")) { - //Recalculate scale if Group is too big or too small! - if (!checkFit(page)) { - newScale = calculateAutomaticScale(); - if(std::abs(Scale.getValue() - newScale) > FLT_EPSILON) { - resetPositions(); - Scale.setValue(newScale); - } - } - } else if (ScaleType.isValue("Page")) { - newScale = page->Scale.getValue(); - if(std::abs(Scale.getValue() - newScale) > FLT_EPSILON) { - resetPositions(); - Scale.setValue(newScale); - } - } else if (ScaleType.isValue("Custom")) { - //don't have to do anything special - } - - // recalculate positions for children - if (Views.getSize()) { - updateChildren(newScale); - //resetPositions(); - distributeProjections(); - } - return DrawViewCollection::execute(); -} void DrawProjGroup::updateChildren(double scale) { @@ -686,8 +669,277 @@ App::Enumeration DrawProjGroup::usedProjectionType(void) return ret; } +bool DrawProjGroup::hasAnchor(void) +{ + bool result = false; + App::DocumentObject* docObj = Anchor.getValue(); + if (docObj != nullptr) { + result = true; + } + return result; +} + + + +void DrawProjGroup::setAnchorDirection(const Base::Vector3d dir) +{ + App::DocumentObject* docObj = Anchor.getValue(); + DrawProjGroupItem* item = static_cast(docObj); + item->Direction.setValue(dir); +} + +Base::Vector3d DrawProjGroup::getAnchorDirection(void) +{ + Base::Vector3d result; + App::DocumentObject* docObj = Anchor.getValue(); + if (docObj != nullptr) { + DrawProjGroupItem* item = static_cast(docObj); + result = item->Direction.getValue(); + } else { + Base::Console().Log("ERROR - DPG::getAnchorDir - no Anchor!!\n"); + } + return result; +} + +//static +Base::Vector3d DrawProjGroup::nameToStdDirection(std::string name) +{ + Base::Vector3d result; + //name to standard view direction + std::map stdViews = { + { "Front", Base::Vector3d(0, -1, 0) }, + { "Rear", Base::Vector3d(0, 1, 0) }, + { "Right", Base::Vector3d(1, 0, 0) }, + { "Left", Base::Vector3d(-1, 0, 0) }, + { "Top", Base::Vector3d(0, 0, 1) }, + { "Bottom", Base::Vector3d(0, 0, -1) }, + { "FrontTopLeft", Base::Vector3d(-1,-1,1) }, + { "FrontTopRight", Base::Vector3d(1, -1, 1) }, + { "FrontBottomRight", Base::Vector3d(1, -1, -1) }, + { "FrontBottomLeft", Base::Vector3d(-1, -1, -1) } }; + auto it = stdViews.find(name); + if (it != stdViews.end()) { + result = (*it).second; + } + return result; +} + + +//************************************* +//* view direction manipulation routines +//************************************* + +//make map from anchor u,v,w +//std::map DrawProjGroup::makeInitialMap(TechDraw::DrawProjGroupItem* anchor) +void DrawProjGroup::makeInitialMap(TechDraw::DrawProjGroupItem* anchor) +{ + m_viewDir = makeUnspunMap(anchor->Direction.getValue(), + anchor->getUDir(), + anchor->getVDir() * -1); //the infamous flipped Y +} + +//! remake map from FRT +std::map DrawProjGroup::makeUnspunMap() +{ + return makeUnspunMap(m_viewDir["Front"], + m_viewDir["Right"], + m_viewDir["Top"]); +} + +//remake this everytime Anchor.Direction changes +std::map DrawProjGroup::makeUnspunMap(Base::Vector3d f, Base::Vector3d r, Base::Vector3d t) +{ + std::map viewDir; + viewDir["Front"] = f; + viewDir["Right"] = r; + viewDir["Top"] = t; + viewDir["Rear"] = viewDir["Front"] * -1.0; + viewDir["Left"] = viewDir["Right"] * -1.0; + viewDir["Bottom"] = viewDir["Top"] * -1.0; + viewDir["FrontTopRight"] = viewDir["Right"] + viewDir["Front"] + viewDir["Top"]; + viewDir["FrontTopLeft"] = viewDir["Left"] + viewDir["Front"] + viewDir["Top"]; + viewDir["FrontBottomRight"] = viewDir["Right"] + viewDir["Front"] + viewDir["Bottom"]; + viewDir["FrontBottomLeft"] = viewDir["Left"] + viewDir["Front"] + viewDir["Bottom"]; + return viewDir; +} + +void DrawProjGroup::dumpMap() +{ + Base::Console().Message("TRACE - DPG::dumpMap - entries: %d\n",m_viewDir.size()); + std::map::const_iterator it; + for (it = m_viewDir.begin(); it != m_viewDir.end(); it++) + { + Base::Console().Message("%s - %s\n",(it->first).c_str(), DrawUtil::formatVector(it->second).c_str()); + } +} + +void DrawProjGroup::updateSecondaryDirs() +{ + for (auto& docObj: Views.getValues()) { + Base::Vector3d newDir; + DrawProjGroupItem* v = static_cast(docObj); + ProjItemType t = static_cast(v->Type.getValue()); + switch (t) { + case Front : { + newDir = m_viewDir["Front"]; + break; + } + case Rear : { + newDir = m_viewDir["Rear"]; + break; + } + case Left : { + newDir = m_viewDir["Left"]; + break; + } + case Right : { + newDir = m_viewDir["Right"]; + break; + } + case Top : { + newDir = m_viewDir["Top"]; + break; + } + case Bottom : { + newDir = m_viewDir["Bottom"]; + break; + } + case FrontTopLeft : { + newDir = m_viewDir["FrontTopLeft"]; + break; + } + case FrontTopRight : { + newDir = m_viewDir["FrontTopRight"]; + break; + } + case FrontBottomLeft : { + newDir = m_viewDir["FrontBottomLeft"]; + break; + } + case FrontBottomRight : { + newDir = m_viewDir["FrontBottomRight"]; + break; + } + default: { + //TARFU invalid secondary type + Base::Console().Message("ERROR - DPG::updateSecondaryDirs - invalid projection type\n"); + newDir = v->Direction.getValue(); + } + } + v->Direction.setValue(newDir); + } +} + + +void DrawProjGroup::rotateRight() +{ +//Front -> Right -> Rear -> Left -> Front + Base::Vector3d f,r,t; + f = m_viewDir["Left"]; + r = m_viewDir["Front"]; + t = m_viewDir["Top"]; + m_viewDir = makeUnspunMap(f,r,t); + updateSecondaryDirs(); +} + +void DrawProjGroup::rotateLeft() +{ +//Front -> Left -> Rear -> Right -> Front + Base::Vector3d f,r,t; + f = m_viewDir["Right"]; + r = m_viewDir["Rear"]; + t = m_viewDir["Top"]; + m_viewDir = makeUnspunMap(f,r,t); + updateSecondaryDirs(); +} + +void DrawProjGroup::rotateUp() +{ +//Front -> Top -> Rear -> Bottom -> Front + Base::Vector3d f,r,t; + f = m_viewDir["Bottom"]; + r = m_viewDir["Right"]; + t = m_viewDir["Front"]; + m_viewDir = makeUnspunMap(f,r,t); + updateSecondaryDirs(); +} + +void DrawProjGroup::rotateDown() +{ +//Front -> Bottom -> Rear -> Top -> Front + Base::Vector3d f,r,t; + f = m_viewDir["Top"]; + r = m_viewDir["Right"]; + t = m_viewDir["Rear"]; + m_viewDir = makeUnspunMap(f,r,t); + updateSecondaryDirs(); +} + +void DrawProjGroup::spinCW() +{ +//Top -> Right -> Bottom -> Left -> Top + Base::Vector3d f,r,t; + f = m_viewDir["Front"]; + t = m_viewDir["Left"]; + r = m_viewDir["Top"]; + m_viewDir = makeUnspunMap(f,r,t); + updateSecondaryDirs(); +} + +void DrawProjGroup::spinCCW() +{ +//Top -> Left -> Bottom -> Right -> Top + Base::Vector3d f,r,t; + f = m_viewDir["Front"]; + t = m_viewDir["Right"]; + r = m_viewDir["Bottom"]; + m_viewDir = makeUnspunMap(f,r,t); + updateSecondaryDirs(); +} + +//************************************* + +//! rebuild view direction map from existing DPGI's if possible or from Anchor void DrawProjGroup::onDocumentRestored() { + Base::Vector3d f,r,t; + bool ffound = false; + bool rfound = false; + bool tfound = false; + + for (auto& docObj: Views.getValues()) { + DrawProjGroupItem* v = static_cast(docObj); + ProjItemType type = static_cast(v->Type.getValue()); + switch (type) { + case Front : { + f = v->Direction.getValue(); + ffound = true; + break; + } + case Right : { + r = v->Direction.getValue(); + rfound = true; + break; + } + case Top : { + t = v->Direction.getValue(); + tfound = true; + break; + } + default: { + break; + } + } + } + if (ffound && rfound && tfound) { + m_viewDir = makeUnspunMap(f,r,t); + } else { + App::DocumentObject* docObj = Anchor.getValue(); + TechDraw::DrawProjGroupItem* view = static_cast( docObj ); + makeInitialMap(view); + Base::Console().Log("LOG: - DPG::restore - making map from Anchor\n"); + } + //dumpMap(); DrawViewCollection::onDocumentRestored(); } diff --git a/src/Mod/TechDraw/App/DrawProjGroup.h b/src/Mod/TechDraw/App/DrawProjGroup.h index b84164fa2..2cd2b7299 100644 --- a/src/Mod/TechDraw/App/DrawProjGroup.h +++ b/src/Mod/TechDraw/App/DrawProjGroup.h @@ -23,12 +23,14 @@ #ifndef _TECHDRAW_FEATUREVIEWGROUP_H_ #define _TECHDRAW_FEATUREVIEWGROUP_H_ +#include # include #include #include #include #include +#include #include "DrawViewCollection.h" @@ -58,9 +60,6 @@ public: /// Default vertical spacing between adjacent views on Drawing, in mm App::PropertyFloat spacingY; - /// Transforms Direction and XAxisDirection vectors in child views - App::PropertyMatrix viewOrientationMatrix; - App::PropertyLink Anchor; /// Anchor Element to align views to Base::BoundBox3d getBoundingBox() const; @@ -71,6 +70,7 @@ public: bool hasProjection(const char *viewProjType) const; App::DocumentObject * getProjObj(const char *viewProjType) const; + DrawProjGroupItem* getProjItem(const char *viewProjType) const; //! Adds a projection to the group /*! @@ -88,11 +88,6 @@ public: /// Automatically position child views bool distributeProjections(void); void resetPositions(void); - /// Changes child views' coordinate space - /*! - * Used to set the Direction and XAxisDirection in child views - */ - void setFrontViewOrientation(const Base::Matrix4D &newMat); short mustExecute() const; /** @name methods overide Feature */ @@ -115,29 +110,25 @@ public: /// Allowed projection types - either Document, First Angle or Third Angle static const char* ProjectionTypeEnums[]; - /// Sets Direction in v - /*! - * Applies viewOrientationMatrix to appropriate unit vectors depending on projType - */ - void setViewOrientation(DrawProjGroupItem *v, const char *projType) const; - /// Populates an array of DrawProjGroupItem*s arranged for drawing - /*! - * Setup array of pointers to the views that we're displaying, - * assuming front is in centre (index 4): - *
-     * [0]  [1]  [2]
-     * [3]  [4]  [5]  [6]
-     * [7]  [8]  [9]
-     *
-     * Third Angle:  FTL  T  FTRight
-     *                L   F   Right   Rear
-     *               FBL  B  FBRight
-     *
-     * First Angle:  FBRight  B  FBL
-     *                Right   F   L  Rear
-     *               FTRight  T  FTL
-     * 
- */ + bool hasAnchor(void); + void setAnchorDirection(Base::Vector3d dir); + Base::Vector3d getAnchorDirection(void); + + void makeInitialMap(TechDraw::DrawProjGroupItem* anchor); + std::map makeUnspunMap(Base::Vector3d f, Base::Vector3d r, Base::Vector3d t); + std::map makeUnspunMap(void); + void dumpMap(); + void updateSecondaryDirs(); + + void rotateRight(void); + void rotateLeft(void); + void rotateUp(void); + void rotateDown(void); + void spinCW(void); + void spinCCW(void); + + static Base::Vector3d nameToStdDirection(std::string name); + protected: void onChanged(const App::Property* prop); @@ -174,6 +165,8 @@ protected: /// Returns pointer to our page, or NULL if it couldn't be located TechDraw::DrawPage * getPage(void) const; void updateChildren(double scale); + + std::map m_viewDir; }; diff --git a/src/Mod/TechDraw/App/DrawProjGroupItem.cpp b/src/Mod/TechDraw/App/DrawProjGroupItem.cpp index b03cb97aa..0d24934dc 100644 --- a/src/Mod/TechDraw/App/DrawProjGroupItem.cpp +++ b/src/Mod/TechDraw/App/DrawProjGroupItem.cpp @@ -34,6 +34,7 @@ #include // generated from DrawProjGroupItemPy.xml + using namespace TechDraw; const char* DrawProjGroupItem::TypeEnums[] = {"Front", diff --git a/src/Mod/TechDraw/App/DrawProjGroupItem.h b/src/Mod/TechDraw/App/DrawProjGroupItem.h index c6f6885bd..79be59c05 100644 --- a/src/Mod/TechDraw/App/DrawProjGroupItem.h +++ b/src/Mod/TechDraw/App/DrawProjGroupItem.h @@ -30,6 +30,18 @@ namespace TechDraw { + +enum ProjItemType{ Front, + Left, + Right, + Rear, + Top, + Bottom, + FrontTopLeft, + FrontTopRight, + FrontBottomLeft, + FrontBottomRight }; + class DrawProjGroup; class TechDrawExport DrawProjGroupItem : public TechDraw::DrawViewPart diff --git a/src/Mod/TechDraw/App/DrawProjGroupPyImp.cpp b/src/Mod/TechDraw/App/DrawProjGroupPyImp.cpp index cb016fdde..0100bf27c 100644 --- a/src/Mod/TechDraw/App/DrawProjGroupPyImp.cpp +++ b/src/Mod/TechDraw/App/DrawProjGroupPyImp.cpp @@ -71,6 +71,7 @@ PyObject* DrawProjGroupPy::getItemByLabel(PyObject* args) return new DrawProjGroupItemPy(newProj); } +//TODO: this is no longer required? PyObject* DrawProjGroupPy::setViewOrientation(PyObject* args) { const char* projType; @@ -78,15 +79,15 @@ PyObject* DrawProjGroupPy::setViewOrientation(PyObject* args) if (!PyArg_ParseTuple(args, "Os", &pcObj,&projType)) throw Py::Exception(); - App::DocumentObject* obj = static_cast(pcObj)->getDocumentObjectPtr(); - if (obj->getTypeId().isDerivedFrom(TechDraw::DrawProjGroupItem::getClassTypeId())) { - TechDraw::DrawProjGroupItem* view = static_cast(obj); - TechDraw::DrawProjGroup* projGroup = getDrawProjGroupPtr(); - projGroup->setViewOrientation( view, projType ); +// App::DocumentObject* obj = static_cast(pcObj)->getDocumentObjectPtr(); +// if (obj->getTypeId().isDerivedFrom(TechDraw::DrawProjGroupItem::getClassTypeId())) { +// TechDraw::DrawProjGroupItem* view = static_cast(obj); +// TechDraw::DrawProjGroup* projGroup = getDrawProjGroupPtr(); +// projGroup->setViewOrientation( view, projType ); - } else { - Base::Console().Message("'%s' is not a DrawProjGroup Item, it will be ignored.\n", obj->Label.getValue()); - } +// } else { +// Base::Console().Message("'%s' is not a DrawProjGroup Item, it will be ignored.\n", obj->Label.getValue()); +// } return Py_None; } diff --git a/src/Mod/TechDraw/App/DrawViewPart.cpp b/src/Mod/TechDraw/App/DrawViewPart.cpp index 60a2b1060..557e590db 100644 --- a/src/Mod/TechDraw/App/DrawViewPart.cpp +++ b/src/Mod/TechDraw/App/DrawViewPart.cpp @@ -143,6 +143,7 @@ DrawViewPart::~DrawViewPart() App::DocumentObjectExecReturn *DrawViewPart::execute(void) { + //Base::Console().Message("TRACE - DVP::execute() - %s\n",getNameInDocument()); App::DocumentObject *link = Source.getValue(); if (!link) { return new App::DocumentObjectExecReturn("FVP - No Source object linked"); diff --git a/src/Mod/TechDraw/Gui/Command.cpp b/src/Mod/TechDraw/Gui/Command.cpp index d7c03ffe3..e970bcd9d 100644 --- a/src/Mod/TechDraw/Gui/Command.cpp +++ b/src/Mod/TechDraw/Gui/Command.cpp @@ -481,16 +481,17 @@ void CmdTechDrawProjGroup::activated(int iMsg) std::string multiViewName = getUniqueObjectName("cView"); std::string SourceName = (*shapes.begin())->getNameInDocument(); doCommand(Doc,"App.activeDocument().addObject('TechDraw::DrawProjGroup','%s')",multiViewName.c_str()); + doCommand(Doc,"App.activeDocument().%s.addView(App.activeDocument().%s)",PageName.c_str(),multiViewName.c_str()); doCommand(Doc,"App.activeDocument().%s.Source = App.activeDocument().%s",multiViewName.c_str(),SourceName.c_str()); App::DocumentObject *docObj = getDocument()->getObject(multiViewName.c_str()); auto multiView( static_cast(docObj) ); // set the anchor - std::string anchor = "Front"; - doCommand(Doc,"App.activeDocument().%s.addProjection('%s')",multiViewName.c_str(),anchor.c_str()); +// std::string anchor = "Front"; +// doCommand(Doc,"App.activeDocument().%s.addProjection('%s')",multiViewName.c_str(),anchor.c_str()); // add the multiView to the page - doCommand(Doc,"App.activeDocument().%s.addView(App.activeDocument().%s)",PageName.c_str(),multiViewName.c_str()); +// doCommand(Doc,"App.activeDocument().%s.addView(App.activeDocument().%s)",PageName.c_str(),multiViewName.c_str()); // create the rest of the desired views Gui::Control().showDialog(new TaskDlgProjGroup(multiView,true)); diff --git a/src/Mod/TechDraw/Gui/TaskProjGroup.cpp b/src/Mod/TechDraw/Gui/TaskProjGroup.cpp index 4854aba82..df9e00296 100644 --- a/src/Mod/TechDraw/Gui/TaskProjGroup.cpp +++ b/src/Mod/TechDraw/Gui/TaskProjGroup.cpp @@ -34,10 +34,15 @@ #include #include #include +#include +#include + +#include #include #include +#include #include #include @@ -51,6 +56,7 @@ #include using namespace Gui; +using namespace TechDraw; using namespace TechDrawGui; //TODO: Look into this, seems we might be able to delete it now? IR @@ -89,6 +95,11 @@ TaskProjGroup::TaskProjGroup(TechDraw::DrawProjGroup* featView, bool mode) : connect(ui->butLeftRotate, SIGNAL(clicked()), this, SLOT(rotateButtonClicked(void))); connect(ui->butCCWRotate, SIGNAL(clicked()), this, SLOT(rotateButtonClicked(void))); + //3D button + connect(ui->but3D, SIGNAL(clicked()), this, SLOT(on3DClicked(void))); + //Reset button + connect(ui->butReset, SIGNAL(clicked()), this, SLOT(onResetClicked(void))); + // Slot for Scale Type connect(ui->cmbScaleType, SIGNAL(currentIndexChanged(int)), this, SLOT(scaleTypeChanged(int))); connect(ui->sbScaleNum, SIGNAL(valueChanged(int)), this, SLOT(scaleManuallyChanged(int))); @@ -103,7 +114,7 @@ TaskProjGroup::TaskProjGroup(TechDraw::DrawProjGroup* featView, bool mode) : ViewProviderPage* dvp = dynamic_cast(vp); m_mdi = dvp->getMDIViewPage(); - setPrimaryDirection(); + setUiPrimary(); } TaskProjGroup::~TaskProjGroup() @@ -144,32 +155,50 @@ void TaskProjGroup::rotateButtonClicked(void) if ( multiView && ui ) { const QObject *clicked = sender(); - // Any translation/scale/etc applied here will be ignored, as - // DrawProjGroup::setFrontViewOrientation() only - // uses it to set Direction and XAxisDirection. - Base::Matrix4D m = multiView->viewOrientationMatrix.getValue(); - // TODO: Construct these directly - Base::Matrix4D t; - - //TODO: Consider changing the vectors around depending on whether we're in First or Third angle mode - might be more intuitive? IR - if ( clicked == ui->butTopRotate ) { - t.rotX(M_PI / 2); + if ( clicked == ui->butTopRotate ) { //change Front View Dir by 90 + multiView->rotateUp(); } else if ( clicked == ui->butDownRotate) { - t.rotX(M_PI / -2); + multiView->rotateDown(); } else if ( clicked == ui->butRightRotate) { - t.rotZ(M_PI / -2); + multiView->rotateRight(); } else if ( clicked == ui->butLeftRotate) { - t.rotZ(M_PI / 2); - } else if ( clicked == ui->butCWRotate ) { - t.rotY(M_PI / -2); + multiView->rotateLeft(); + } else if ( clicked == ui->butCWRotate ) { //doesn't change Anchor view dir. changes projType of secondaries, not dir + multiView->spinCW(); } else if ( clicked == ui->butCCWRotate) { - t.rotY(M_PI / 2); + multiView->spinCCW(); } - m *= t; + setUiPrimary(); + Gui::Command::updateActive(); + } +} - multiView->setFrontViewOrientation(m); - setPrimaryDirection(); +void TaskProjGroup::on3DClicked(void) +{ + Base::Vector3d dir3D = get3DViewDir(); + TechDraw::DrawProjGroupItem* front = multiView->getProjItem("Front"); + if (front) { + front->Direction.setValue(dir3D); + front->recomputeFeature(); + setUiPrimary(); + multiView->makeInitialMap(front); + multiView->updateSecondaryDirs(); + Gui::Command::updateActive(); + } +} + +void TaskProjGroup::onResetClicked(void) +{ + Base::Vector3d dir = multiView->nameToStdDirection("Front"); + TechDraw::DrawProjGroupItem* front = multiView->getProjItem("Front"); + if (front) { + front->Direction.setValue(dir); + front->recomputeFeature(); + setUiPrimary(); + multiView->makeInitialMap(front); + multiView->updateSecondaryDirs(); + multiView->dumpMap(); Gui::Command::updateActive(); } } @@ -378,16 +407,37 @@ void TaskProjGroup::setupViewCheckboxes(bool addConnections) } } -void TaskProjGroup::setPrimaryDirection() +void TaskProjGroup::setUiPrimary() { - App::DocumentObject* docObj = multiView->getProjObj("Front"); - TechDraw::DrawViewPart* dvp = dynamic_cast(docObj); - if (dvp != nullptr) { - Base::Vector3d frontDir = dvp->Direction.getValue(); - ui->lePrimary->setText(formatVector(frontDir)); - } + Base::Vector3d frontDir = multiView->getAnchorDirection(); + ui->lePrimary->setText(formatVector(frontDir)); } +Base::Vector3d TaskProjGroup::get3DViewDir() +{ + Base::Vector3d viewDir(0.0,-1.0,0.0); //default to front + std::list mdis = Gui::Application::Instance->activeDocument()->getMDIViews(); + Gui::View3DInventor *view; + Gui::View3DInventorViewer *viewer; + for (auto& m: mdis) { //find the 3D viewer + view = dynamic_cast(m); + if (view) { + viewer = view->getViewer(); + break; + } + } + if (!viewer) { + Base::Console().Log("LOG - TaskProjGroup could not find a 3D viewer\n"); + return viewDir; + } + + SbVec3f dvec = viewer->getViewDirection(); + viewDir = Base::Vector3d(dvec[0], dvec[1], dvec[2]); + viewDir = viewDir * -1; //Inventor coords are opposite projection direction coords + return viewDir; +} + + QString TaskProjGroup::formatVector(Base::Vector3d v) { QString data = QString::fromLatin1("[%1 %2 %3]") diff --git a/src/Mod/TechDraw/Gui/TaskProjGroup.h b/src/Mod/TechDraw/Gui/TaskProjGroup.h index ff07ea086..1ea902590 100644 --- a/src/Mod/TechDraw/Gui/TaskProjGroup.h +++ b/src/Mod/TechDraw/Gui/TaskProjGroup.h @@ -75,6 +75,9 @@ protected Q_SLOTS: /// Requests appropriate rotation of our DrawProjGroup void rotateButtonClicked(void); + void on3DClicked(void); + void onResetClicked(void); + void projectionTypeChanged(int index); void scaleTypeChanged(int index); void scaleManuallyChanged(int i); @@ -88,8 +91,8 @@ protected: * between checkboxes and viewToggled() */ void setupViewCheckboxes(bool addConnections = false); - - void setPrimaryDirection(void); + Base::Vector3d get3DViewDir(void); + void setUiPrimary(void); QString formatVector(Base::Vector3d v); private: diff --git a/src/Mod/TechDraw/Gui/TaskProjGroup.ui b/src/Mod/TechDraw/Gui/TaskProjGroup.ui index ab54d9046..beebff70e 100644 --- a/src/Mod/TechDraw/Gui/TaskProjGroup.ui +++ b/src/Mod/TechDraw/Gui/TaskProjGroup.ui @@ -57,6 +57,9 @@ + + First or Third Angle + false @@ -90,6 +93,9 @@ + + Scale Page/Auto/Custom + Page @@ -133,6 +139,9 @@ + + Scale Numerator + 1 @@ -150,6 +159,9 @@ + + Scale Denominator + 1 @@ -205,7 +217,7 @@ - 12 + 11 50 false false @@ -214,6 +226,9 @@ Qt::NoFocus + + Primary View Direction + Qt::AlignCenter @@ -292,9 +307,12 @@ - + - false + true + + + Set Primary Direction to match 3D Match 3D @@ -322,6 +340,16 @@ + + + + Set Primary Direction to 3D Front + + + 3D Front + + + @@ -345,8 +373,236 @@ + + + + + + true + + + Bottom + + + QCheckBox::indicator { +width: 24px; +height: 24px; +} + + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + false + + + Primary + + + QCheckBox::indicator { +width: 24px; +height: 24px; +} + + + + + + + true + + + + + + + Right + + + QCheckBox::indicator { +width: 24px; +height: 24px; +} + + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Left + + + QCheckBox::indicator { +width: 24px; +height: 24px; +} + + + + + + + + + + + LeftFrontBottom + + + QCheckBox::indicator { +width: 24px; +height: 24px; +} + + + + + + + + + + + Top + + + QCheckBox::indicator { +width: 24px; +height: 24px; +} + + + + + + + + + + + RightFrontBottom + + + QCheckBox::indicator { +width: 24px; +height: 24px; +} + + + + + + + + + + + RightFrontTop + + + QCheckBox::indicator { +width: 24px; +height: 24px; +} + + + + + + + + + + + Rear + + + QCheckBox::indicator { +width: 24px; +height: 24px; +} + + + + + + + + + + + LeftFrontTop + + + QCheckBox::indicator { +width: 24px; +height: 24px; +} + + + + + + + + 24 + 24 + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + @@ -377,22 +633,8 @@ - - - - - - - - true - - - - - - - - + + Qt::Horizontal @@ -404,88 +646,6 @@ - - - - false - - - - - - true - - - - - - - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -