Use Face or 3D direction for View and ProjGroup

- use current 3D window direction as starting
  direction for DrawViewPart and ProjectionGroup
- if a Face is selected, use Face normal as
  starting direction.
This commit is contained in:
wandererfan
2018-08-20 20:01:48 -04:00
committed by wmayer
parent 233ed49b23
commit aa8feb79d0
16 changed files with 544 additions and 893 deletions

View File

@@ -67,6 +67,7 @@
#include <Mod/TechDraw/App/DrawViewDraft.h>
#include <Mod/TechDraw/App/DrawViewMulti.h>
#include <Mod/TechDraw/App/DrawViewDetail.h>
#include <Mod/TechDraw/App/DrawUtil.h>
#include <Mod/TechDraw/Gui/QGVPage.h>
#include "DrawGuiUtil.h"
@@ -264,6 +265,7 @@ void CmdTechDrawNewView::activated(int iMsg)
if (!page) {
return;
}
std::string PageName = page->getNameInDocument();
std::vector<App::DocumentObject*> shapes = getSelection().getObjectsOfType(App::GeoFeature::getClassTypeId());
std::vector<App::DocumentObject*> groups = getSelection().getObjectsOfType(App::DocumentObjectGroup::getClassTypeId());
@@ -276,8 +278,29 @@ void CmdTechDrawNewView::activated(int iMsg)
if (!groups.empty()) {
shapes.insert(shapes.end(),groups.begin(),groups.end());
}
std::string PageName = page->getNameInDocument();
//set projection direction from selected Face
//use first object with a face selected
std::vector<Gui::SelectionObject> selection = getSelection().getSelectionEx();
Part::Feature* partFeat = 0;
std::vector<std::string> SubNames;
std::string faceName;
bool subFound = false;
std::vector<Gui::SelectionObject>::iterator itSel = selection.begin();
for (; itSel != selection.end(); itSel++) {
if ((*itSel).getObject()->isDerivedFrom(Part::Feature::getClassTypeId())) {
partFeat = static_cast<Part::Feature*> ((*itSel).getObject());
SubNames = (*itSel).getSubNames();
if (!SubNames.empty()) {
faceName = SubNames.front();
if (TechDraw::DrawUtil::getGeomTypeFromName(faceName) == "Face") {
subFound = true;
break;
}
}
}
}
Base::Vector3d projDir;
Gui::WaitCursor wc;
openCommand("Create view");
@@ -290,6 +313,19 @@ void CmdTechDrawNewView::activated(int iMsg)
}
dvp->Source.setValues(shapes);
doCommand(Doc,"App.activeDocument().%s.addView(App.activeDocument().%s)",PageName.c_str(),FeatName.c_str());
if (subFound) {
std::pair<Base::Vector3d,Base::Vector3d> dirs = DrawGuiUtil::getProjDirFromFace(partFeat,faceName);
projDir = dirs.first;
doCommand(Doc,"App.activeDocument().%s.Direction = FreeCAD.Vector(%.3f,%.3f,%.3f)",
FeatName.c_str(), projDir.x,projDir.y,projDir.z);
doCommand(Doc,"App.activeDocument().%s.recompute()", FeatName.c_str());
} else {
std::pair<Base::Vector3d,Base::Vector3d> dirs = DrawGuiUtil::get3DDirAndRot();
projDir = dirs.first;
doCommand(Doc,"App.activeDocument().%s.Direction = FreeCAD.Vector(%.3f,%.3f,%.3f)",
FeatName.c_str(), projDir.x,projDir.y,projDir.z);
doCommand(Doc,"App.activeDocument().%s.recompute()", FeatName.c_str());
}
updateActive();
commitCommand();
}
@@ -463,6 +499,7 @@ void CmdTechDrawProjGroup::activated(int iMsg)
if (!page) {
return;
}
std::string PageName = page->getNameInDocument();
std::vector<App::DocumentObject*> shapes = getSelection().getObjectsOfType(App::GeoFeature::getClassTypeId());
std::vector<App::DocumentObject*> groups = getSelection().getObjectsOfType(App::DocumentObjectGroup::getClassTypeId());
@@ -476,8 +513,29 @@ void CmdTechDrawProjGroup::activated(int iMsg)
shapes.insert(shapes.end(),groups.begin(),groups.end());
}
std::string PageName = page->getNameInDocument();
//set projection direction from selected Face
//use first object with a face selected
std::vector<Gui::SelectionObject> selection = getSelection().getSelectionEx();
Part::Feature* partFeat = 0;
std::vector<std::string> SubNames;
std::string faceName;
bool subFound = false;
std::vector<Gui::SelectionObject>::iterator itSel = selection.begin();
for (; itSel != selection.end(); itSel++) {
if ((*itSel).getObject()->isDerivedFrom(Part::Feature::getClassTypeId())) {
partFeat = static_cast<Part::Feature*> ((*itSel).getObject());
SubNames = (*itSel).getSubNames();
if (!SubNames.empty()) {
faceName = SubNames.front();
if (TechDraw::DrawUtil::getGeomTypeFromName(faceName) == "Face") {
subFound = true;
break;
}
}
}
}
Base::Vector3d projDir;
Gui::WaitCursor wc;
openCommand("Create Projection Group");
@@ -489,6 +547,24 @@ void CmdTechDrawProjGroup::activated(int iMsg)
auto multiView( static_cast<TechDraw::DrawProjGroup *>(docObj) );
multiView->Source.setValues(shapes);
if (subFound) {
std::pair<Base::Vector3d,Base::Vector3d> dirs = DrawGuiUtil::getProjDirFromFace(partFeat,faceName);
doCommand(Doc,"App.activeDocument().%s.Anchor.Direction = FreeCAD.Vector(%.3f,%.3f,%.3f)",
multiViewName.c_str(), dirs.first.x,dirs.first.y,dirs.first.z);
doCommand(Doc,"App.activeDocument().%s.Anchor.RotationVector = FreeCAD.Vector(%.3f,%.3f,%.3f)",
multiViewName.c_str(), dirs.second.x,dirs.second.y,dirs.second.z);
getDocument()->setStatus(App::Document::Status::SkipRecompute, false);
doCommand(Doc,"App.activeDocument().%s.Anchor.recompute()", multiViewName.c_str());
} else {
std::pair<Base::Vector3d,Base::Vector3d> dirs = DrawGuiUtil::get3DDirAndRot();
getDocument()->setStatus(App::Document::Status::SkipRecompute, true);
doCommand(Doc,"App.activeDocument().%s.Anchor.Direction = FreeCAD.Vector(%.3f,%.3f,%.3f)",
multiViewName.c_str(), dirs.first.x,dirs.first.y,dirs.first.z);
doCommand(Doc,"App.activeDocument().%s.Anchor.RotationVector = FreeCAD.Vector(%.3f,%.3f,%.3f)",
multiViewName.c_str(), dirs.second.x,dirs.second.y,dirs.second.z);
getDocument()->setStatus(App::Document::Status::SkipRecompute, false);
doCommand(Doc,"App.activeDocument().%s.Anchor.recompute()", multiViewName.c_str());
}
//updateActive(); //exec all pending actions, but there's nothing to do here.
commitCommand(); //write the undo

View File

@@ -36,6 +36,14 @@
#endif
#include <gp_Vec.hxx>
#include <gp_Pnt.hxx>
#include <gp_Trsf.hxx>
#include <gp_Dir.hxx>
#include <gp_Ax2.hxx>
#include <BRepAdaptor_Surface.hxx>
#include <BRepLProp_SLProps.hxx>
#include <App/Application.h>
#include <App/Document.h>
#include <App/DocumentObject.h>
@@ -51,6 +59,11 @@
#include <Gui/Document.h>
#include <Gui/Selection.h>
#include <Gui/MainWindow.h>
#include <Gui/MDIView.h>
#include <Gui/View3DInventor.h>
#include <Gui/View3DInventorViewer.h>
#include <Inventor/SbVec3f.h>
#include <Mod/Part/App/PartFeature.h>
#include <Mod/Part/App/Part2DObject.h>
@@ -67,6 +80,7 @@
#include "DrawGuiUtil.h"
using namespace TechDrawGui;
using namespace TechDraw;
//===========================================================================
// validate helper routines
@@ -187,3 +201,87 @@ void DrawGuiUtil::dumpPointF(const char* text, const QPointF& p)
Base::Console().Message("DUMP - dumpPointF - %s\n",text);
Base::Console().Message("Point: (%.3f, %.3f)\n",p.x(),p.y());
}
std::pair<Base::Vector3d,Base::Vector3d> DrawGuiUtil::get3DDirAndRot()
{
std::pair<Base::Vector3d,Base::Vector3d> result;
Base::Vector3d viewDir(0.0,-1.0,0.0); //default to front
Base::Vector3d viewUp(0.0,0.0,1.0); //default to top
Base::Vector3d viewRight(1.0,0.0,0.0); //default to right
std::list<Gui::MDIView*> mdis = Gui::Application::Instance->activeDocument()->getMDIViews();
Gui::View3DInventor *view;
Gui::View3DInventorViewer *viewer = nullptr;
for (auto& m: mdis) { //find the 3D viewer
view = dynamic_cast<Gui::View3DInventor*>(m);
if (view) {
viewer = view->getViewer();
break;
}
}
if (!viewer) {
Base::Console().Log("LOG - DrawGuiUtil could not find a 3D viewer\n");
return std::make_pair( viewDir, viewRight);
}
SbVec3f dvec = viewer->getViewDirection();
SbVec3f upvec = viewer->getUpDirection();
viewDir = Base::Vector3d(dvec[0], dvec[1], dvec[2]);
viewUp = Base::Vector3d(upvec[0],upvec[1],upvec[2]);
Base::Vector3d dirXup = viewDir.Cross(viewUp); //dir X up should give local Right
viewDir = viewDir * (-1.0); // Inventor dir is opposite TD projection dir
result = std::make_pair(viewDir,dirXup);
return result;
}
std::pair<Base::Vector3d,Base::Vector3d> DrawGuiUtil::getProjDirFromFace(Part::Feature* obj, std::string faceName)
{
std::pair<Base::Vector3d,Base::Vector3d> d3Dirs = get3DDirAndRot();
Base::Vector3d d3Up = (d3Dirs.first).Cross(d3Dirs.second);
std::pair<Base::Vector3d,Base::Vector3d> dirs;
dirs.first = Base::Vector3d(0.0,0.0,1.0); //set a default
dirs.second = Base::Vector3d(1.0,0.0,0.0);
Base::Vector3d projDir, rotVec;
projDir = d3Dirs.first;
rotVec = d3Dirs.second;
if (DrawUtil::getGeomTypeFromName(faceName) != "Face") {
Base::Console().Warning("getProjDirFromFace(%s) is not a Face\n",faceName.c_str());
return dirs;
}
Part::TopoShape ts = obj->Shape.getShape();
ts.setPlacement(obj->globalPlacement());
TopoDS_Shape subShape = ts.getSubShape(faceName.c_str());
const TopoDS_Face& face = TopoDS::Face(subShape);
TopAbs_Orientation orient = face.Orientation();
BRepAdaptor_Surface adapt(face);
double u1 = adapt.FirstUParameter();
double u2 = adapt.LastUParameter();
double v1 = adapt.FirstVParameter();
double v2 = adapt.LastVParameter();
double uMid = (u1+u2)/2.0;
double vMid = (v1+v2)/2.0;
BRepLProp_SLProps props(adapt,uMid,vMid,2,Precision::Confusion());
if (props.IsNormalDefined()) {
gp_Dir vec = props.Normal();
projDir = Base::Vector3d(vec.X(),vec.Y(),vec.Z());
rotVec = projDir.Cross(d3Up);
if (orient != TopAbs_FORWARD) {
projDir = projDir * (-1.0);
}
}
else {
Base::Console().Log("Selected Face has no normal at midpoint\n");
}
dirs = std::make_pair(projDir,rotVec);
return dirs;
}

View File

@@ -26,6 +26,11 @@
#include <string>
#include <QRectF>
#include <QPointF>
#include <Base/Vector3D.h>
namespace Part {
class Feature;
}
namespace TechDraw {
class DrawPage;
@@ -45,6 +50,9 @@ class TechDrawGuiExport DrawGuiUtil {
static bool needView(Gui::Command* cmd, bool partOnly = true);
static void dumpRectF(const char* text, const QRectF& r);
static void dumpPointF(const char* text, const QPointF& p);
static std::pair<Base::Vector3d,Base::Vector3d> get3DDirAndRot();
static std::pair<Base::Vector3d,Base::Vector3d> getProjDirFromFace(Part::Feature* obj, std::string faceName);
};
} //end namespace TechDrawGui

View File

@@ -36,6 +36,7 @@
#include <Gui/Document.h>
#include <Gui/View3DInventor.h>
#include <Gui/View3DInventorViewer.h>
#include <Gui/WaitCursor.h>
#include <Inventor/SbVec3f.h>
@@ -97,10 +98,8 @@ 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)));
// //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)));
@@ -126,13 +125,17 @@ TaskProjGroup::~TaskProjGroup()
void TaskProjGroup::viewToggled(bool toggle)
{
Gui::WaitCursor wc;
bool changed = false;
// Obtain name of checkbox
QString viewName = sender()->objectName();
int index = viewName.mid(7).toInt();
const char *viewNameCStr = viewChkIndexToCStr(index);
if ( toggle && !multiView->hasProjection( viewNameCStr ) ) {
(void) multiView->addProjection( viewNameCStr );
(void) multiView->addProjection( viewNameCStr ); //maybe this should be send a message instead of blocking?
// Gui::Command::doCommand(Gui::Command::Doc, // Gui response is no faster with this. :(
// "App.activeDocument().%s.addProjection('%s')",
// multiView->getNameInDocument(), viewNameCStr);
changed = true;
} else if ( !toggle && multiView->hasProjection( viewNameCStr ) ) {
multiView->removeProjection( viewNameCStr );
@@ -144,7 +147,7 @@ void TaskProjGroup::viewToggled(bool toggle)
setFractionalScale(scale);
}
}
wc.restoreCursor();
}
void TaskProjGroup::rotateButtonClicked(void)
@@ -171,37 +174,14 @@ void TaskProjGroup::rotateButtonClicked(void)
}
}
void TaskProjGroup::on3DClicked(void)
{
Base::Console().Warning("TaskProjGroup - this function is temporarily unavailable\n");
//TODO: how to set the DPG.Cube (or a brand new replacement Cube) to a specific orientation
// {10x(viewDirection + RotationVector)} given only the
// viewDirection + upDirection(!= RotationVector) of the front view?
// need to find the sequence of rotations Left/Right, Up/Down, CW/CCW
// from current orientation to desired orientation.
// std::pair<Base::Vector3d,Base::Vector3d> dir3D = get3DViewDir();
// Base::Vector3d dir = dir3D.first;
// dir = DrawUtil::closestBasis(dir);
// Base::Vector3d up = dir3D.second;
// up = DrawUtil::closestBasis(up);
//void TaskProjGroup::onResetClicked(void)
//{
// TechDraw::DrawProjGroupItem* front = multiView->getProjItem("Front");
// if (front) { //why "if front"???
// multiView->setTable(dir,up);
// if (front) {
// setUiPrimary();
// Gui::Command::updateActive();
// }
}
void TaskProjGroup::onResetClicked(void)
{
TechDraw::DrawProjGroupItem* front = multiView->getProjItem("Front");
if (front) {
multiView->resetCube();
setUiPrimary();
Gui::Command::updateActive();
}
}
//}
void TaskProjGroup::projectionTypeChanged(int index)
{
@@ -463,41 +443,6 @@ void TaskProjGroup::setUiPrimary()
ui->lePrimary->setText(formatVector(frontDir));
}
//should return a configuration? frontdir,upDir mapped in DPG
std::pair<Base::Vector3d,Base::Vector3d> TaskProjGroup::get3DViewDir()
{
std::pair<Base::Vector3d,Base::Vector3d> result;
Base::Vector3d viewDir(0.0,-1.0,0.0); //default to front
Base::Vector3d viewUp(0.0,0.0,1.0); //default to top
std::list<MDIView*> mdis = Gui::Application::Instance->activeDocument()->getMDIViews();
Gui::View3DInventor *view;
Gui::View3DInventorViewer *viewer = nullptr;
for (auto& m: mdis) { //find the 3D viewer
view = dynamic_cast<Gui::View3DInventor*>(m);
if (view) {
viewer = view->getViewer();
break;
}
}
if (!viewer) {
Base::Console().Log("LOG - TaskProjGroup could not find a 3D viewer\n");
return std::make_pair( viewDir, viewUp);
}
SbVec3f dvec = viewer->getViewDirection();
SbVec3f upvec = viewer->getUpDirection();
viewDir = Base::Vector3d(dvec[0], dvec[1], dvec[2]);
viewUp = Base::Vector3d(upvec[0],upvec[1],upvec[2]);
viewDir *= -1.0; //Inventor dir is opposite TD dir, Inventor up is same as TD up
viewDir = DrawUtil::closestBasis(viewDir);
viewUp = DrawUtil::closestBasis(viewUp);
result = std::make_pair(viewDir,viewUp);
return result;
}
QString TaskProjGroup::formatVector(Base::Vector3d v)
{
QString data = QString::fromLatin1("[%1 %2 %3]")

View File

@@ -75,8 +75,7 @@ protected Q_SLOTS:
/// Requests appropriate rotation of our DrawProjGroup
void rotateButtonClicked(void);
void on3DClicked(void);
void onResetClicked(void);
// void onResetClicked(void);
void projectionTypeChanged(int index);
void scaleTypeChanged(int index);
@@ -91,7 +90,6 @@ protected:
* between checkboxes and viewToggled()
*/
void setupViewCheckboxes(bool addConnections = false);
std::pair<Base::Vector3d,Base::Vector3d> get3DViewDir(void);
void setUiPrimary(void);
QString formatVector(Base::Vector3d v);

View File

@@ -7,7 +7,7 @@
<x>0</x>
<y>0</y>
<width>371</width>
<height>491</height>
<height>506</height>
</rect>
</property>
<property name="sizePolicy">
@@ -306,19 +306,6 @@
</property>
</widget>
</item>
<item row="2" column="2">
<widget class="QPushButton" name="but3D">
<property name="enabled">
<bool>false</bool>
</property>
<property name="toolTip">
<string>This function is temporarily unavailable.</string>
</property>
<property name="text">
<string>Match 3D</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QPushButton" name="butDownRotate">
<property name="toolTip">
@@ -340,15 +327,31 @@
</property>
</widget>
</item>
<item row="2" column="2">
<spacer name="horizontalSpacer_7">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="2" column="0">
<widget class="QPushButton" name="butReset">
<property name="toolTip">
<string>Return Primary Direction to Initial Value</string>
<spacer name="horizontalSpacer_8">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="text">
<string>Reset</string>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</widget>
</spacer>
</item>
</layout>
</item>