Replace DPG table lookup logic with calculations

DPG used a pair of large tables to determine view
direction and rotation vector when subject was rotated
and spun.  There were many errors in the tables that
needed manual checking to correct.  The new version
uses calculations on a virtual glass cube to find view
direction and rotation vector.
This commit is contained in:
WandererFan
2017-06-13 10:34:57 -04:00
committed by wmayer
parent 75900944c9
commit 4c4e1e3210
7 changed files with 423 additions and 866 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -26,54 +26,8 @@
#include <Base/Vector3D.h>
namespace TechDraw {
class configLine
namespace TechDraw
{
public:
configLine() {}
~configLine() {}
configLine(int ln, std::string ky, Base::Vector3d b, Base::Vector3d f,
Base::Vector3d l, Base::Vector3d k,
Base::Vector3d r, Base::Vector3d t);
Base::Vector3d getItem(std::string s);
std::string getKey(void) { return key; }
std::string getString();
void dump(char* title);
std::map<std::string, Base::Vector3d> itemMap;
// Base::Vector3d getItem(std::string s);
private:
int lineNumber;
std::string key;
// std::map<std::string, Base::Vector3d> itemMap;
};
class configTable
{
public:
configTable(void) {}
~configTable(void) {}
void initialize();
std::string getCfgDirStr(std::string cfg);
std::string getCfgRotStr(std::string cfg);
configLine getDirLine(std::string k);
configLine getRotLine(std::string k);
Base::Vector3d getDirItem(std::string k, std::string v);
Base::Vector3d getRotItem(std::string k, std::string v);
void addDirItem(configLine);
void addRotItem(configLine);
//bool checkConfig(std::vector<std::string> c);
void dump(char* title);
private:
configLine getLine(std::string k, std::vector<configLine> list);
Base::Vector3d getItem(std::string k, std::string v, std::vector<configLine> list);
std::vector<configLine> dirs;
std::vector<configLine> rots;
};
class Cube
@@ -82,23 +36,23 @@ public:
Cube();
~Cube();
void initialize();
void initialize(Base::Vector3d r, Base::Vector3d rr, Base::Vector3d l, Base::Vector3d lr,
Base::Vector3d f, Base::Vector3d fr, Base::Vector3d k, Base::Vector3d kr, //k for bacK (rear)
Base::Vector3d t, Base::Vector3d tr, Base::Vector3d b, Base::Vector3d br,
Base::Vector3d fbl, Base::Vector3d fblr, Base::Vector3d fbr, Base::Vector3d fbrr,
Base::Vector3d ftl, Base::Vector3d ftlr, Base::Vector3d ftr, Base::Vector3d ftrr);
Base::Vector3d t, Base::Vector3d tr, Base::Vector3d b, Base::Vector3d br);
void rotateUp();
void rotateDown();
void rotateRight();
void rotateLeft ();
void spinCCW();
void spinCW();
void rotateUp(double angle = 90.0);
void rotateDown(double angle = 90.0);
void rotateRight(double angle = 90.0);
void rotateLeft (double angle = 90.0);
void spinCCW(double angle = 90.0);
void spinCW(double angle = 90.0);
void updateIsoDirs();
//viewDirection getters
Base::Vector3d getViewDir(std::string name);
Base::Vector3d getRight();
Base::Vector3d getFront();
Base::Vector3d getTop();
@@ -110,6 +64,8 @@ void initialize(Base::Vector3d r, Base::Vector3d rr, Base::Vector3d l, Base::Vec
Base::Vector3d getFTL();
Base::Vector3d getFTR();
//rotation getters
Base::Vector3d getRotationDir(std::string name);
Base::Vector3d getRightRot();
Base::Vector3d getFrontRot();
Base::Vector3d getTopRot();
@@ -121,48 +77,30 @@ void initialize(Base::Vector3d r, Base::Vector3d rr, Base::Vector3d l, Base::Vec
Base::Vector3d getFTLRot();
Base::Vector3d getFTRRot();
static std::string dirToView(Base::Vector3d v);
void updateDirsToConfig(std::string cfg);
void updateRotsToConfig(std::string cfg);
bool validateBoard(std::string cfg);
std::string getCurrConfig(void);
void dump(char * title);
void dumpISO(char * title);
void dumpState(char * title);
std::vector<Base::Vector3d> getAllDirs(void);
std::vector<Base::Vector3d> getAllRots(void);
void setAllDirs(std::vector<Base::Vector3d> dirs);
void setAllRots(std::vector<Base::Vector3d> rots);
private:
// Base::Vector3d currRight;
// Base::Vector3d currRightRot;
// Base::Vector3d currFront;
// Base::Vector3d currFrontRot;
// Base::Vector3d currTop;
// Base::Vector3d currTopRot;
// Base::Vector3d currLeft;
// Base::Vector3d currLeftRot;
// Base::Vector3d currRear;
// Base::Vector3d currRearRot;
// Base::Vector3d currBottom;
// Base::Vector3d currBottomRot;
//the current state of the "board"
//the "board" is always full - entries for every position
std::map<std::string, Base::Vector3d> m_mapFrameDir;
std::map<std::string, Base::Vector3d> m_mapFrameRot;
//the current state of the "cube"
//the "cube" is always full - entries for every ortho position (6 total)
std::map<std::string, Base::Vector3d> m_mapCubeDir;
std::map<std::string, Base::Vector3d> m_mapCubeRot;
static const std::map<std::string,Base::Vector3d> m_viewToStdDir; //would really like this map the other way round.
static const std::map<std::string,Base::Vector3d> m_viewDefault;
static const std::map<std::string,Base::Vector3d> m_rotDefault;
//should be in drawutil?
Base::Vector3d rodrigues(Base::Vector3d v,
double angle,
Base::Vector3d axis);
void shiftFrame(std::string from, std::string to);
void saveSwap(std::string frame);
void restoreSwap(std::string frame);
Base::Vector3d m_swapDir;
Base::Vector3d m_swapRot;
configTable m_conTab;
};
}
#endif

View File

@@ -53,87 +53,6 @@ const char* DrawProjGroup::ProjectionTypeEnums[] = {"Default",
"Third Angle",
NULL};
//default starting dirs & rots
const std::map<std::string,Base::Vector3d> DrawProjGroup::m_frameToStdDir = {
{ "Front", Base::Vector3d(0, -1, 0) }, //front
{ "Rear", Base::Vector3d(0, 1, 0) }, //rear
{ "Right", Base::Vector3d(1, 0, 0) }, //right
{ "Left", Base::Vector3d(-1, 0, 0) }, //left
{ "Top", Base::Vector3d(0, 0, 1) }, //top
{ "Bottom", Base::Vector3d(0, 0, -1) }, //bottom
{ "FrontBottomLeft", Base::Vector3d(-1, -1, -1) }, //FBL
{ "FrontBottomRight", Base::Vector3d(1, -1, -1) }, //FBR
{ "FrontTopLeft", Base::Vector3d(-1,-1,1) }, //FTL
{ "FrontTopRight", Base::Vector3d(1, -1, 1) } //FTR
};
const std::map<std::string,Base::Vector3d> DrawProjGroup::m_frameToStdRot = {
{ "Front", Base::Vector3d(1, 0, 0) }, //front
{ "Rear", Base::Vector3d(-1, 0, 0) }, //rear
{ "Right", Base::Vector3d(0, -1, 0) }, //right
{ "Left", Base::Vector3d(0, 1, 0) }, //left
{ "Top", Base::Vector3d(1, 0, 0) }, //top
{ "Bottom", Base::Vector3d(1, 0, 0) }, //bottom
{ "FrontBottomLeft", Base::Vector3d(2, 1, 0.5) },
{ "FrontBottomRight", Base::Vector3d(2, -1, -0.5) },
{ "FrontTopLeft", Base::Vector3d(2, 1, -0.5) },
{ "FrontTopRight", Base::Vector3d(2, -1, 0.5) }
};
//one of these is obs??
// map of front.dir+front.rot onto config
const std::map<std::string,std::string> DrawProjGroup::m_dirRotToConfig = {
{"AB","AB"},
{"AC","AC"},
{"AD","AD"},
{"AE","AE"},
{"BF","BA"},
{"BC","BC"},
{"BD","BD"},
{"BA","BF"},
{"CD","CA"},
{"CB","CB"},
{"CE","CE"},
{"CA","CF"},
{"DF","DA"},
{"DB","DB"},
{"DE","DE"},
{"DC","DF"},
{"EF","EA"},
{"EC","EC"},
{"ED","ED"},
{"EA","EF"},
{"FB","FB"},
{"FF","FC"},
{"FD","FD"},
{"FE","FE"} };
// map frontDir + topDir onto config
const std::map<std::string,std::string> DrawProjGroup::m_frontTopToConfig = {
{ "AC" , "AB" },
{ "AE" , "AC" },
{ "AB" , "AD" },
{ "AD" , "AE" },
{ "BD" , "BA" },
{ "BA" , "BC" },
{ "BF" , "BD" },
{ "BC" , "BF" },
{ "CB" , "CA" },
{ "CF" , "CB" },
{ "CA" , "CE" },
{ "CE" , "CF" },
{ "DE" , "DA" },
{ "DA" , "DB" },
{ "DF" , "DE" },
{ "DB" , "DF" },
{ "EC" , "EA" },
{ "EF" , "EC" },
{ "EA" , "ED" },
{ "ED" , "EF" },
{ "FD" , "FB" },
{ "FB" , "FC" },
{ "FE" , "FD" },
{ "FC" , "FE" } };
PROPERTY_SOURCE(TechDraw::DrawProjGroup, TechDraw::DrawViewCollection)
@@ -152,16 +71,10 @@ 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_TYPE(CubeDirs,(Base::Vector3d()) ,agroup, App::Prop_None, "Current view directions");
ADD_PROPERTY_TYPE(CubeRotations,(Base::Vector3d()),agroup, App::Prop_None, "Current rotations");
m_cube = new Cube();
// D/C/A/F/B/E/FBL/
m_cube->initialize(m_frameToStdDir.at("Right"), m_frameToStdRot.at("Right"),
m_frameToStdDir.at("Left"), m_frameToStdRot.at("Left"),
m_frameToStdDir.at("Front"), m_frameToStdRot.at("Front"), m_frameToStdDir.at("Rear"), m_frameToStdRot.at("Rear"),
m_frameToStdDir.at("Top"), m_frameToStdRot.at("Top"), m_frameToStdDir.at("Bottom"), m_frameToStdRot.at("Bottom"),
m_frameToStdDir.at("FrontBottomLeft"), m_frameToStdRot.at("FrontBottomLeft"),
m_frameToStdDir.at("FrontBottomRight"), m_frameToStdRot.at("FrontBottomRight"),
m_frameToStdDir.at("FrontTopLeft"), m_frameToStdRot.at("FrontTopLeft"),
m_frameToStdDir.at("FrontTopRight"), m_frameToStdRot.at("FrontTopRight") );
m_cube->initialize(); //set default dirs & rots
}
DrawProjGroup::~DrawProjGroup()
@@ -169,6 +82,12 @@ DrawProjGroup::~DrawProjGroup()
delete m_cube;
}
void DrawProjGroup::resetCube(void)
{
m_cube->initialize();
updateSecondaryDirs();
}
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 don't... Or vice-versa. WF: why would you change from 1st to 3rd in mid drawing?
@@ -201,9 +120,28 @@ void DrawProjGroup::onChanged(const App::Property* prop)
recompute();
}
}
if (isRestoring() && (prop == &CubeDirs)) {
m_cube->setAllDirs(CubeDirs.getValues()); //override defaults from saved value if valid
}
if (isRestoring() && (prop == &CubeRotations)) {
m_cube->setAllRots(CubeRotations.getValues()); //override defaults from saved value if valid
}
TechDraw::DrawViewCollection::onChanged(prop);
}
//! call this after changing the Cube
void DrawProjGroup::setPropsFromCube(void)
{
CubeDirs.setValues(m_cube->getAllDirs());
CubeRotations.setValues(m_cube->getAllRots());
}
void DrawProjGroup::setCubeFromProps(void)
{
m_cube->setAllDirs(CubeDirs.getValues());
m_cube->setAllRots(CubeRotations.getValues());
}
App::DocumentObjectExecReturn *DrawProjGroup::execute(void)
{
//if group hasn't been added to page yet, can't scale or distribute projItems
@@ -461,8 +399,8 @@ App::DocumentObject * DrawProjGroup::addProjection(const char *viewProjType)
view->Type.setValue( viewProjType );
view->Label.setValue( viewProjType );
view->Source.setValue( Source.getValue() );
view->Direction.setValue(m_frameToStdDir.at(viewProjType));
view->RotationVector.setValue(m_frameToStdRot.at(viewProjType));
view->Direction.setValue(m_cube->getViewDir(viewProjType));
view->RotationVector.setValue(m_cube->getRotationDir(viewProjType));
addView(view); //from DrawViewCollection - add to ProjGroup Views
moveToCentre();
view->recomputeFeature();
@@ -896,8 +834,9 @@ void DrawProjGroup::updateSecondaryDirs()
}
v->Direction.setValue(newDir);
v->RotationVector.setValue(newAxis);
v->recomputeFeature();
// v->recomputeFeature();
}
setPropsFromCube();
}
@@ -943,50 +882,10 @@ void DrawProjGroup::spinCCW()
updateSecondaryDirs();
}
// find a config with Dir as Front view and Up as Top view
// used in setting view to match OpenInventor
void DrawProjGroup::setTable(Base::Vector3d dir, Base::Vector3d up)
{
std::string viewFront = Cube::dirToView(dir); //convert to closest basis vector?
std::string viewUp = Cube::dirToView(up); //convert to closest basis vector
std::string altKey = viewFront + viewUp;
std::string config;
try {
config = m_frontTopToConfig.at(altKey);
}
catch (const std::out_of_range& oor) {
Base::Console().Error("Error - DPG::setTable - no match for alt config: %s - %s\n",altKey.c_str(),oor.what());
return;
}
setConfig(config);
}
// set config to a specific value
void DrawProjGroup::setConfig(std::string cfg)
{
m_cube->updateDirsToConfig(cfg);
m_cube->updateRotsToConfig(cfg);
updateSecondaryDirs();
}
void DrawProjGroup::resetTable(void)
{
m_cube->initialize(m_frameToStdDir.at("Right"), m_frameToStdRot.at("Right"),
m_frameToStdDir.at("Left"), m_frameToStdRot.at("Left"),
m_frameToStdDir.at("Front"), m_frameToStdRot.at("Front"), m_frameToStdDir.at("Rear"), m_frameToStdRot.at("Rear"),
m_frameToStdDir.at("Top"), m_frameToStdRot.at("Top"), m_frameToStdDir.at("Bottom"), m_frameToStdRot.at("Bottom"),
m_frameToStdDir.at("FrontBottomLeft"), m_frameToStdRot.at("FrontBottomLeft"),
m_frameToStdDir.at("FrontBottomRight"), m_frameToStdRot.at("FrontBottomRight"),
m_frameToStdDir.at("FrontTopLeft"), m_frameToStdRot.at("FrontTopLeft"),
m_frameToStdDir.at("FrontTopRight"), m_frameToStdRot.at("FrontTopRight") );
updateSecondaryDirs();
}
//dumps the current iso DPGI's
void DrawProjGroup::dumpISO(char * title)
{
//FBL/FBR/FTL/FTR
//
Base::Console().Message("DPG ISO: %s\n", title);
for (auto& docObj: Views.getValues()) {
Base::Vector3d dir;
@@ -1001,45 +900,6 @@ void DrawProjGroup::dumpISO(char * title)
}
}
//*************************************
//! rebuild view direction map from existing DPGI's
void DrawProjGroup::onDocumentRestored()
{
if (hasProjection("Front") && hasProjection("Right")) {
Base::Vector3d dirFront = getProjItem("Front")->Direction.getValue();
std::string viewFront = Cube::dirToView(dirFront);
Base::Vector3d dirRight = getProjItem("Right")->Direction.getValue();
std::string viewRight = Cube::dirToView(dirRight);
std::string config = viewFront + viewRight;
setConfig(config);
} else if (hasProjection("Front")) {
Base::Vector3d dirFront = getProjItem("Front")->Direction.getValue();
std::string viewDir = Cube::dirToView(dirFront);
Base::Vector3d rotFront(1.0,0.0,0.0);
App::Property* prop = getPropertyByName("RotationVector");
if (prop) {
Base::Console().Log("INFO - DPG::onRestore - DPG has RotationVector property\n");
rotFront = getProjItem("Front")->RotationVector.getValue();
} else {
Base::Console().Log("INFO - DPG::onRestore - DPG has NO RotationVector property\n");
}
std::string viewRot = Cube::dirToView(rotFront);
std::string config = viewDir + viewRot;
//find(config) or try/catch
try {
config = m_dirRotToConfig.at(config);
setConfig(config);
}
catch (...) {
Base::Console().Message("PROBLEM: DPG cannot set configuration: %s using default instead\n",config.c_str());
setConfig("AD");
}
} else {
Base::Console().Message("PROBLEM: DPG cannot find Front view on restore. Using default instead.\n");
setConfig("AD");
}
}
PyObject *DrawProjGroup::getPyObject(void)
{
if (PythonObject.is(Py::_None())) {

View File

@@ -63,6 +63,8 @@ public:
App::PropertyFloat spacingY;
App::PropertyLink Anchor; /// Anchor Element to align views to
App::PropertyVectorList CubeDirs;
App::PropertyVectorList CubeRotations;
Base::BoundBox3d getBoundingBox() const;
double calculateAutomaticScale() const;
@@ -95,7 +97,6 @@ public:
/** @name methods overide Feature */
//@{
/// recalculate the Feature
virtual void onDocumentRestored() override;
virtual App::DocumentObjectExecReturn *execute(void) override;
//@}
@@ -118,6 +119,7 @@ public:
TechDraw::DrawProjGroupItem* getAnchor(void);
void updateSecondaryDirs();
void resetCube(void);
void rotateRight(void);
void rotateLeft(void);
@@ -126,9 +128,6 @@ public:
void spinCW(void);
void spinCCW(void);
void setTable(Base::Vector3d dir, Base::Vector3d rot);
void setConfig(std::string cfg);
void resetTable(void);
void dumpISO(char * title);
protected:
@@ -166,13 +165,10 @@ protected:
/// Returns pointer to our page, or NULL if it couldn't be located
TechDraw::DrawPage * getPage(void) const;
void updateChildren(double scale);
void setPropsFromCube(void);
void setCubeFromProps(void);
//TechDraw::Cube m_cube;
TechDraw::Cube* m_cube;
static const std::map<std::string,Base::Vector3d> m_frameToStdDir; //for initializing cube and
static const std::map<std::string,Base::Vector3d> m_frameToStdRot; //creating DPGI's
static const std::map<std::string,std::string> m_dirRotToConfig;
static const std::map<std::string,std::string> m_frontTopToConfig;
};
} //namespace TechDraw

View File

@@ -62,8 +62,8 @@ DrawProjGroupItem::DrawProjGroupItem(void)
ADD_PROPERTY_TYPE(RotationVector ,(1.0,0.0,0.0) ,"Base",App::Prop_None,"Controls rotation of item in view. ");
//projection group controls these
Direction.setStatus(App::Property::ReadOnly,true);
RotationVector.setStatus(App::Property::ReadOnly,true);
// Direction.setStatus(App::Property::ReadOnly,true);
// RotationVector.setStatus(App::Property::ReadOnly,true);
Scale.setStatus(App::Property::ReadOnly,true);
ScaleType.setStatus(App::Property::ReadOnly,true);
}

View File

@@ -176,24 +176,31 @@ void TaskProjGroup::rotateButtonClicked(void)
void TaskProjGroup::on3DClicked(void)
{
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);
TechDraw::DrawProjGroupItem* front = multiView->getProjItem("Front");
if (front) { //why "if front"???
multiView->setTable(dir,up);
setUiPrimary();
Gui::Command::updateActive();
}
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);
// TechDraw::DrawProjGroupItem* front = multiView->getProjItem("Front");
// if (front) { //why "if front"???
// multiView->setTable(dir,up);
// setUiPrimary();
// Gui::Command::updateActive();
// }
}
void TaskProjGroup::onResetClicked(void)
{
TechDraw::DrawProjGroupItem* front = multiView->getProjItem("Front");
if (front) {
multiView->resetTable();
multiView->resetCube();
setUiPrimary();
Gui::Command::updateActive();
}

View File

@@ -309,10 +309,10 @@
<item row="2" column="2">
<widget class="QPushButton" name="but3D">
<property name="enabled">
<bool>true</bool>
<bool>false</bool>
</property>
<property name="toolTip">
<string>Try to match Primary Direction to 3D view</string>
<string>This function is temporarily unavailable.</string>
</property>
<property name="text">
<string>Match 3D</string>