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

@@ -96,8 +96,6 @@ SET(TechDraw_SRCS
AppTechDrawPy.cpp
DrawUtil.cpp
DrawUtil.h
Cube.cpp
Cube.h
HatchLine.cpp
HatchLine.h
PreCompiled.cpp

View File

@@ -1,565 +0,0 @@
/***************************************************************************
* Copyright (c) 2016 WandererFan <wandererfan@gmail.com> *
* *
* This file is part of the FreeCAD CAx development system. *
* *
* This library is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Library General Public *
* License as published by the Free Software Foundation; either *
* version 2 of the License, or (at your option) any later version. *
* *
* This library 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 Library General Public License for more details. *
* *
* You should have received a copy of the GNU Library General Public *
* License along with this library; see the file COPYING.LIB. If not, *
* write to the Free Software Foundation, Inc., 59 Temple Place, *
* Suite 330, Boston, MA 02111-1307, USA *
* *
***************************************************************************/
#include "PreCompiled.h"
#ifndef _PreComp_
# include <sstream>
#endif
#include <Base/Console.h>
#include "DrawUtil.h"
#include "Cube.h"
using namespace TechDraw;
//default starting dirs & rots
const std::map<std::string,Base::Vector3d> Cube::m_viewDefault = {
{ "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
};
const std::map<std::string,Base::Vector3d> Cube::m_rotDefault = {
{ "Front", Base::Vector3d(1, 0, 0) }, //front RightDir
{ "Rear", Base::Vector3d(-1, 0, 0) }, //rear LeftDir
{ "Right", Base::Vector3d(0, -1, 0) }, //right FrontDir
{ "Left", Base::Vector3d(0, 1, 0) }, //left RearDir
{ "Top", Base::Vector3d(1, 0, 0) }, //top RightDir
{ "Bottom", Base::Vector3d(1, 0, 0) }, //bottom RightDir
};
const Base::Vector3d _Y(0,1,0);
Cube::Cube(void)
{
}
Cube::~Cube(void)
{
}
void Cube::initialize()
{
m_mapCubeDir = m_viewDefault;
m_mapCubeRot = m_rotDefault;
}
// left,right,front,back,top,bottom
void Cube::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)
{
m_mapCubeDir.clear();
m_mapCubeDir.insert(std::map<std::string, Base::Vector3d>::value_type("Bottom", b));
m_mapCubeDir.insert(std::map<std::string, Base::Vector3d>::value_type("Front" , f));
m_mapCubeDir.insert(std::map<std::string, Base::Vector3d>::value_type("Left" , l));
m_mapCubeDir.insert(std::map<std::string, Base::Vector3d>::value_type("Rear" , k));
m_mapCubeDir.insert(std::map<std::string, Base::Vector3d>::value_type("Right" , r));
m_mapCubeDir.insert(std::map<std::string, Base::Vector3d>::value_type("Top" , t));
m_mapCubeRot.clear();
m_mapCubeRot.insert(std::map<std::string, Base::Vector3d>::value_type("Bottom", br));
m_mapCubeRot.insert(std::map<std::string, Base::Vector3d>::value_type("Front" , fr));
m_mapCubeRot.insert(std::map<std::string, Base::Vector3d>::value_type("Left" , lr));
m_mapCubeRot.insert(std::map<std::string, Base::Vector3d>::value_type("Rear" , kr));
m_mapCubeRot.insert(std::map<std::string, Base::Vector3d>::value_type("Right" , rr));
m_mapCubeRot.insert(std::map<std::string, Base::Vector3d>::value_type("Top" , tr));
}
// rotate/spin the subject inside the glass cube
// effectively, rotate/spin the cube in reverse of the apparent subject movement
//TODO: there is a problem with calculation of view rotation vector when the axis of rotation is
// +/-Y. There is hack code here to handle it, but there should be a more elegant solution
// subject CW about Right
void Cube::rotateUp(double angle)
{
//Front -> Top -> Rear -> Bottom -> Front
Base::Vector3d axis = getRight();
std::map<std::string, Base::Vector3d> newDirs;
for (auto& d: m_mapCubeDir) {
Base::Vector3d v = rodrigues(d.second,angle,axis);
newDirs.insert(std::map<std::string, Base::Vector3d>::value_type(d.first, v));
}
std::map<std::string, Base::Vector3d> newRots;
for (auto& r: m_mapCubeRot) {
Base::Vector3d v = rodrigues(r.second,-angle,axis);
newRots.insert(std::map<std::string, Base::Vector3d>::value_type(r.first, v));
}
double flipper = 1.0;
if (DrawUtil::checkParallel(axis,_Y)) {
flipper = -flipper;
newRots["Right"] = newRots["Right"] * flipper;
newRots["Left"] = newRots["Left"] * flipper;
}
m_mapCubeDir = newDirs;
m_mapCubeRot = newRots;
}
// CCW about Right
void Cube::rotateDown(double angle)
{
//Front -> Bottom -> Rear -> Top -> Front
Base::Vector3d axis = getRight();
std::map<std::string, Base::Vector3d> newDirs;
for (auto& d: m_mapCubeDir) {
Base::Vector3d v = rodrigues(d.second,-angle,axis);
newDirs.insert(std::map<std::string, Base::Vector3d>::value_type(d.first, v));
}
std::map<std::string, Base::Vector3d> newRots;
for (auto& r: m_mapCubeRot) {
Base::Vector3d v = rodrigues(r.second,angle,axis);
newRots.insert(std::map<std::string, Base::Vector3d>::value_type(r.first, v));
}
double flipper = 1.0;
if (DrawUtil::checkParallel(axis,_Y)) {
flipper = -flipper;
newRots["Right"] = newRots["Right"] * flipper;
newRots["Left"] = newRots["Left"] * flipper;
}
m_mapCubeDir = newDirs;
m_mapCubeRot = newRots;
}
// CCW about Top
void Cube::rotateRight(double angle)
{
//Front -> Right -> Rear -> Left -> Front
Base::Vector3d axis = getTop();
std::map<std::string, Base::Vector3d> newDirs;
for (auto& d: m_mapCubeDir) {
Base::Vector3d v = rodrigues(d.second,-angle,axis);
newDirs.insert(std::map<std::string, Base::Vector3d>::value_type(d.first, v));
}
std::map<std::string, Base::Vector3d> newRots;
for (auto& r: m_mapCubeRot) {
Base::Vector3d v = rodrigues(r.second,angle,axis);
newRots.insert(std::map<std::string, Base::Vector3d>::value_type(r.first, v));
}
double flipper = 1.0;
if (DrawUtil::checkParallel(axis,_Y)) {
flipper = -flipper;
newRots["Top"] = newRots["Top"] * flipper;
newRots["Bottom"] = newRots["Bottom"] * flipper;
newRots["Left"] = newDirs["Front"];
newRots["Right"] = newRots["Left"] * -1.0;
}
newRots["Front"] = newRots["Top"];
newRots["Rear"] = newRots["Front"] * -1.0;
m_mapCubeDir = newDirs;
m_mapCubeRot = newRots;
}
// CW about Top
void Cube::rotateLeft(double angle)
{
//Front -> Left -> Rear -> Right -> Front
Base::Vector3d axis = getTop();
std::map<std::string, Base::Vector3d> newDirs;
for (auto& d: m_mapCubeDir) {
Base::Vector3d v = rodrigues(d.second,angle,axis);
newDirs.insert(std::map<std::string, Base::Vector3d>::value_type(d.first, v));
}
std::map<std::string, Base::Vector3d> newRots;
for (auto& r: m_mapCubeRot) {
Base::Vector3d v = rodrigues(r.second,-angle,axis);
newRots.insert(std::map<std::string, Base::Vector3d>::value_type(r.first, v));
}
double flipper = 1.0;
if (DrawUtil::checkParallel(axis,_Y)) {
flipper = -flipper;
newRots["Top"] = newRots["Top"] * flipper;
newRots["Bottom"] = newRots["Bottom"] * flipper;
newRots["Left"] = newDirs["Front"];
newRots["Right"] = newRots["Left"] * -1.0;
}
newRots["Front"] = newRots["Top"];
newRots["Rear"] = newRots["Front"] * -1.0;
m_mapCubeDir = newDirs;
m_mapCubeRot = newRots;
}
// CCW about Front
void Cube::spinCCW(double angle)
{
Base::Vector3d axis = getFront();
std::map<std::string, Base::Vector3d> newDirs;
for (auto& d: m_mapCubeDir) {
Base::Vector3d v = rodrigues(d.second,-angle,axis);
newDirs.insert(std::map<std::string, Base::Vector3d>::value_type(d.first, v));
}
std::map<std::string, Base::Vector3d> newRots;
for (auto& r: m_mapCubeRot) {
Base::Vector3d v = rodrigues(r.second,angle,axis);
newRots.insert(std::map<std::string, Base::Vector3d>::value_type(r.first, v));
}
double flipper = 1.0;
if (DrawUtil::checkParallel(axis,_Y)) {
flipper = -flipper;
}
newRots["Front"] = newRots["Front"] * flipper;
newRots["Rear"] = newRots["Rear"] * flipper;
newRots["Top"] = newRots["Front"];
newRots["Bottom"] = newRots["Front"];
m_mapCubeDir = newDirs;
m_mapCubeRot = newRots;
}
// CW about Front
void Cube::spinCW(double angle)
{
//Right -> Bottom -> Left -> Top -> Right
Base::Vector3d axis = getFront();
std::map<std::string, Base::Vector3d> newDirs;
for (auto& d: m_mapCubeDir) {
Base::Vector3d v = rodrigues(d.second,angle,axis);
newDirs.insert(std::map<std::string, Base::Vector3d>::value_type(d.first, v));
}
std::map<std::string, Base::Vector3d> newRots;
for (auto& r: m_mapCubeRot) {
Base::Vector3d v = rodrigues(r.second,-angle,axis);
newRots.insert(std::map<std::string, Base::Vector3d>::value_type(r.first, v));
}
double flipper = 1.0;
if (DrawUtil::checkParallel(axis,_Y)) {
flipper = -flipper;
newRots["Front"] = newRots["Front"] * flipper;
newRots["Rear"] = newRots["Rear"] * flipper;
}
newRots["Top"] = newRots["Front"];
newRots["Bottom"] = newRots["Front"];
m_mapCubeDir = newDirs;
m_mapCubeRot = newRots;
}
//dumps the current ortho state of cube
void Cube::dump(char * title)
{
//Bottom/Front/Left/Rear/Right/Top
Base::Console().Message("Cube: %s\n", title);
Base::Console().Message("B: %s/%s \nF: %s/%s \nL: %s/%s\n",
DrawUtil::formatVector(getBottom()).c_str(),DrawUtil::formatVector(getBottomRot()).c_str(),
DrawUtil::formatVector(getFront()).c_str(),DrawUtil::formatVector(getFrontRot()).c_str(),
DrawUtil::formatVector(getLeft()).c_str(),DrawUtil::formatVector(getLeftRot()).c_str());
Base::Console().Message("K: %s/%s \nR: %s/%s \nT: %s/%s\n",
DrawUtil::formatVector(getRear()).c_str(),DrawUtil::formatVector(getRearRot()).c_str(),
DrawUtil::formatVector(getRight()).c_str(),DrawUtil::formatVector(getRightRot()).c_str(),
DrawUtil::formatVector(getTop()).c_str(),DrawUtil::formatVector(getTopRot()).c_str());
}
//dumps the current "board" -ISO's
void Cube::dumpISO(char * title)
{
//FBL/FBR/FTL/FTR
Base::Console().Message("Cube ISO: %s\n", title);
Base::Console().Message("FBL: %s/%s \nFBR: %s/%s \nFTL: %s/%s\nFTR: %s/%s\n",
DrawUtil::formatVector(getFBL()).c_str(),DrawUtil::formatVector(getFBLRot()).c_str(),
DrawUtil::formatVector(getFBR()).c_str(),DrawUtil::formatVector(getFBRRot()).c_str(),
DrawUtil::formatVector(getFTL()).c_str(),DrawUtil::formatVector(getFTLRot()).c_str(),
DrawUtil::formatVector(getFTR()).c_str(),DrawUtil::formatVector(getFTRRot()).c_str());
}
Base::Vector3d Cube::getViewDir(std::string name)
{
Base::Vector3d result;
auto x = m_mapCubeDir.find(name);
if (x != m_mapCubeDir.end()) {
result = m_mapCubeDir.at(name);
} else {
if (name == "FrontTopRight") {
result = getFTR();
} else if (name == "FrontBottomRight") {
result = getFBR();
} else if (name == "FrontTopLeft") {
result = getFTL();
} else if (name == "FrontBottomLeft") {
result = getFBL();
} else {
result = Base::Vector3d(0,-1,0);
Base::Console().Log("Cube: invalid direction name - %s\n",name.c_str());
}
}
return result;
}
Base::Vector3d Cube::getRight()
{
Base::Vector3d result;
result = m_mapCubeDir.at("Right");
return result;
}
Base::Vector3d Cube::getFront()
{
Base::Vector3d result;
result = m_mapCubeDir.at("Front");
return result;
}
Base::Vector3d Cube::getTop()
{
Base::Vector3d result;
result = m_mapCubeDir.at("Top");
return result;
}
Base::Vector3d Cube::getLeft()
{
Base::Vector3d result;
result = m_mapCubeDir.at("Left");
return result;
}
Base::Vector3d Cube::getRear()
{
Base::Vector3d result;
result = m_mapCubeDir.at("Rear");
return result;
}
Base::Vector3d Cube::getBottom()
{
Base::Vector3d result;
result = m_mapCubeDir.at("Bottom");
return result;
}
Base::Vector3d Cube::getFBL()
{
Base::Vector3d result;
result = getFront() + getBottom() + getLeft();
return result;
}
Base::Vector3d Cube::getFBR()
{
Base::Vector3d result;
result = getFront() + getBottom() + getRight();
return result;
}
Base::Vector3d Cube::getFTL()
{
Base::Vector3d result;
result = getFront() + getTop() + getLeft();
return result;
}
Base::Vector3d Cube::getFTR()
{
Base::Vector3d result;
result = getFront() + getTop() + getRight();
return result;
}
Base::Vector3d Cube::getRotationDir(std::string name)
{
Base::Vector3d result;
auto x = m_mapCubeRot.find(name);
if (x != m_mapCubeRot.end()) {
result = m_mapCubeRot.at(name);
} else {
if (name == "FrontTopRight") {
result = getFTRRot();
} else if (name == "FrontBottomRight") {
result = getFBRRot();
} else if (name == "FrontTopLeft") {
result = getFTLRot();
} else if (name == "FrontBottomLeft") {
result = getFBLRot();
} else {
result = Base::Vector3d(1,0,0);
Base::Console().Log("Cube: invalid rotation name - %s\n",name.c_str());
}
}
return result;
}
Base::Vector3d Cube::getRightRot()
{
Base::Vector3d result;
result = m_mapCubeRot.at("Right");
return result;
}
Base::Vector3d Cube::getFrontRot()
{
Base::Vector3d result;
result = m_mapCubeRot.at("Front");
return result;
}
Base::Vector3d Cube::getTopRot()
{
Base::Vector3d result;
result = m_mapCubeRot.at("Top");
return result;
}
Base::Vector3d Cube::getLeftRot()
{
Base::Vector3d result;
result = m_mapCubeRot.at("Left");
return result;
}
Base::Vector3d Cube::getRearRot()
{
Base::Vector3d result;
result = m_mapCubeRot.at("Rear");
return result;
}
Base::Vector3d Cube::getBottomRot()
{
Base::Vector3d result;
result = m_mapCubeRot.at("Bottom");
return result;
}
Base::Vector3d Cube::getFBLRot()
{
Base::Vector3d result;
result = getFrontRot() + getLeftRot();
return result;
}
Base::Vector3d Cube::getFBRRot()
{
Base::Vector3d result;
result = getFrontRot() + getRightRot();
return result;
}
Base::Vector3d Cube::getFTLRot()
{
Base::Vector3d result;
result = getFrontRot() + getLeftRot();
return result;
}
Base::Vector3d Cube::getFTRRot()
{
Base::Vector3d result;
result = getFrontRot() + getRightRot();
return result;
}
Base::Vector3d Cube::rodrigues(Base::Vector3d v,
double angle,
Base::Vector3d axis)
{
Base::Vector3d result;
if (DrawUtil::checkParallel(v,axis)) {
result = v;
} else {
Base::Vector3d around = axis;
around.Normalize();
double theta = angle * (M_PI / 180.0);
Base::Vector3d t1 = cos(theta) * v;
Base::Vector3d t2 = sin(theta) * around.Cross(v);
Base::Vector3d t3 = around.Dot(v) * (1 - cos(theta)) * around;
result = t1 + t2 + t3;
}
return result;
}
std::vector<Base::Vector3d> Cube::getAllDirs(void)
{
std::vector<Base::Vector3d> result;
for (auto& d: m_mapCubeDir) {
Base::Vector3d v = d.second;
result.push_back(v);
}
return result;
}
std::vector<Base::Vector3d> Cube::getAllRots(void)
{
std::vector<Base::Vector3d> result;
for (auto& r: m_mapCubeRot) {
Base::Vector3d v = r.second;
result.push_back(v);
}
return result;
}
void Cube::setAllDirs(std::vector<Base::Vector3d> dirs)
{
if (dirs.size() != 6) {
Base::Console().Error("Cube:setAllDirs - missing dirs: %d\n",dirs.size());
return; //throw something?
}
auto i = dirs.begin();
std::map<std::string, Base::Vector3d> newDirs;
for (auto& d: m_mapCubeDir) {
Base::Vector3d v = (*i);
newDirs.insert(std::map<std::string, Base::Vector3d>::value_type(d.first, v));
i++;
}
m_mapCubeDir = newDirs;
}
void Cube::setAllRots(std::vector<Base::Vector3d> rots)
{
if (rots.size() != 6) {
Base::Console().Error("Cube:setAllRots - missing rots: %d\n",rots.size());
return; //throw something?
}
auto i = rots.begin();
std::map<std::string, Base::Vector3d> newRots;
for (auto& r: m_mapCubeRot) {
Base::Vector3d v = (*i);
newRots.insert(std::map<std::string, Base::Vector3d>::value_type(r.first, v));
i++;
}
m_mapCubeRot = newRots;
}

View File

@@ -1,107 +0,0 @@
/***************************************************************************
* Copyright (c) 2016 WandererFan <wandererfan@gmail.com> *
* *
* This file is part of the FreeCAD CAx development system. *
* *
* This library is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Library General Public *
* License as published by the Free Software Foundation; either *
* version 2 of the License, or (at your option) any later version. *
* *
* This library 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 Library General Public License for more details. *
* *
* You should have received a copy of the GNU Library General Public *
* License along with this library; see the file COPYING.LIB. If not, *
* write to the Free Software Foundation, Inc., 59 Temple Place, *
* Suite 330, Boston, MA 02111-1307, USA *
* *
***************************************************************************/
#ifndef _CUBE_H_
#define _CUBE_H_
#include <map>
#include <Base/Vector3D.h>
namespace TechDraw
{
class Cube
{
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);
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();
Base::Vector3d getLeft();
Base::Vector3d getRear();
Base::Vector3d getBottom();
Base::Vector3d getFBL();
Base::Vector3d getFBR();
Base::Vector3d getFTL();
Base::Vector3d getFTR();
//rotation getters
Base::Vector3d getRotationDir(std::string name);
Base::Vector3d getRightRot();
Base::Vector3d getFrontRot();
Base::Vector3d getTopRot();
Base::Vector3d getLeftRot();
Base::Vector3d getRearRot();
Base::Vector3d getBottomRot();
Base::Vector3d getFBLRot();
Base::Vector3d getFBRRot();
Base::Vector3d getFTLRot();
Base::Vector3d getFTRRot();
void dump(char * title);
void dumpISO(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:
//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_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);
};
}
#endif

View File

@@ -39,7 +39,6 @@
#include <Base/Matrix.h>
#include <Base/Parameter.h>
#include "Cube.h"
#include "DrawUtil.h"
#include "DrawPage.h"
#include "DrawProjGroupItem.h"
@@ -77,23 +76,12 @@ DrawProjGroup::DrawProjGroup(void)
ADD_PROPERTY_TYPE(AutoDistribute ,(autoDist),agroup,App::Prop_None,"Distribute Views Automatically or Manually");
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();
m_cube->initialize(); //set default dirs & rots
}
DrawProjGroup::~DrawProjGroup()
{
delete m_cube;
}
void DrawProjGroup::resetCube(void)
{
m_cube->initialize();
updateSecondaryDirs();
}
void DrawProjGroup::onChanged(const App::Property* prop)
{
@@ -106,6 +94,7 @@ void DrawProjGroup::onChanged(const App::Property* prop)
if (!sourceObjs.empty()) {
if (!hasAnchor()) {
// if we have a Source, but no Anchor, make an anchor
// Base::Console().Message("TRACE - DPG::onChanged - adding Front\n");
Anchor.setValue(addProjection("Front"));
Anchor.purgeTouched(); //don't need to mark this
}
@@ -137,28 +126,10 @@ void DrawProjGroup::onChanged(const App::Property* prop)
}
}
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 (!keepUpdated()) {
@@ -392,6 +363,8 @@ bool DrawProjGroup::hasProjection(const char *viewProjType) const
App::DocumentObject * DrawProjGroup::addProjection(const char *viewProjType)
{
DrawProjGroupItem *view( nullptr );
std::pair<Base::Vector3d,Base::Vector3d> vecs;
if ( checkViewProjType(viewProjType) && !hasProjection(viewProjType) ) {
std::string FeatName = getDocument()->getUniqueObjectName("ProjItem");
@@ -403,8 +376,12 @@ App::DocumentObject * DrawProjGroup::addProjection(const char *viewProjType)
view->Type.setValue( viewProjType );
view->Label.setValue( viewProjType );
view->Source.setValues( Source.getValues() );
view->Direction.setValue(m_cube->getViewDir(viewProjType));
view->RotationVector.setValue(m_cube->getRotationDir(viewProjType));
if (strcmp(viewProjType, "Front") != 0 ) {
vecs = getDirsFromFront(view);
view->Direction.setValue(vecs.first);
view->RotationVector.setValue(vecs.second);
}
addView(view); //from DrawViewCollection
moveToCentre();
if (view != getAnchor()) { //anchor is done elsewhere
@@ -462,6 +439,76 @@ int DrawProjGroup::purgeProjections()
return Views.getValues().size();
}
std::pair<Base::Vector3d,Base::Vector3d> DrawProjGroup::getDirsFromFront(DrawProjGroupItem* view)
{
std::pair<Base::Vector3d,Base::Vector3d> result;
std::string viewType = view->Type.getValueAsString();
result = getDirsFromFront(viewType);
return result;
}
std::pair<Base::Vector3d,Base::Vector3d> DrawProjGroup::getDirsFromFront(std::string viewType)
{
std::pair<Base::Vector3d,Base::Vector3d> result;
Base::Vector3d projDir, rotVec;
DrawProjGroupItem* anch = getAnchor();
Base::Vector3d dirAnch = anch->Direction.getValue();
Base::Vector3d rotAnch = anch->RotationVector.getValue();
Base::Vector3d upAnch = dirAnch.Cross(rotAnch); //this can get weird after rotations
projDir = dirAnch; //need default
rotVec = rotAnch;
Base::Vector3d realUp = DrawUtil::closestBasis(upAnch);
Base::Vector3d org(0.0,0.0,0.0);
result = std::make_pair(dirAnch,rotAnch);
double angle = M_PI / 2.0; //90*
if (viewType == "Right") {
projDir = DrawUtil::vecRotate(dirAnch,angle,realUp,org);
rotVec = DrawUtil::vecRotate(rotAnch,angle,upAnch,org);
} else if (viewType == "Left") {
projDir = DrawUtil::vecRotate(dirAnch,-angle,realUp,org);
rotVec = DrawUtil::vecRotate(rotAnch,-angle,upAnch,org);
} else if (viewType == "Top") {
projDir = upAnch;
rotVec = rotAnch;
} else if (viewType == "Bottom") {
projDir = upAnch * (-1.0);
rotVec = rotAnch;
} else if (viewType == "Rear") {
projDir = DrawUtil::vecRotate(dirAnch,2.0 * angle,realUp,org);
rotVec = -rotAnch;
} else if (viewType == "FrontTopLeft") {
projDir = dirAnch + //front
DrawUtil::vecRotate(dirAnch,-angle,realUp,org) + //left
upAnch; //top
rotVec = rotAnch + dirAnch; //sb current front rot + curr right rot
} else if (viewType == "FrontTopRight") {
projDir = dirAnch + //front
DrawUtil::vecRotate(dirAnch,angle,realUp,org) + //right
upAnch; //top
rotVec = rotAnch - dirAnch;
} else if (viewType == "FrontBottomLeft") {
projDir = dirAnch + //front
DrawUtil::vecRotate(dirAnch,-angle,realUp,org) + //left
upAnch * (-1.0); //bottom
rotVec = rotAnch + dirAnch;
} else if (viewType == "FrontBottomRight") {
projDir = dirAnch + //front
DrawUtil::vecRotate(dirAnch,angle,realUp,org) + //right
upAnch * (-1.0); //bottom
rotVec = rotAnch - dirAnch;
} else {
Base::Console().Error("DrawProjGroup - %s unknown projection: %s\n",getNameInDocument(),viewType.c_str());
return result;
}
result = std::make_pair(projDir,rotVec);
return result;
}
Base::Vector3d DrawProjGroup::getXYPosition(const char *viewTypeCStr)
{
Base::Vector3d result;
@@ -833,74 +880,109 @@ Base::Vector3d DrawProjGroup::getAnchorDirection(void)
void DrawProjGroup::updateSecondaryDirs()
{
DrawProjGroupItem* anchor = getAnchor();
Base::Vector3d anchDir = anchor->Direction.getValue();
Base::Vector3d anchRot = anchor->RotationVector.getValue();
std::map<std::string, std::pair<Base::Vector3d,Base::Vector3d> > saveVals;
std::string key;
std::pair<Base::Vector3d, Base::Vector3d> data;
for (auto& docObj: Views.getValues()) {
Base::Vector3d newDir;
Base::Vector3d newAxis;
Base::Vector3d newRot;
std::pair<Base::Vector3d,Base::Vector3d> newDirs;
std::string pic;
DrawProjGroupItem* v = static_cast<DrawProjGroupItem*>(docObj);
ProjItemType t = static_cast<ProjItemType>(v->Type.getValue());
switch (t) {
case Front : {
newDir = m_cube->getFront();
newAxis = m_cube->getFrontRot();
case Front :
data.first = anchDir;
data.second = anchRot;
key = "Front";
saveVals[key] = data;
break;
}
case Rear : {
newDir = m_cube->getRear();
newAxis = m_cube->getRearRot();
case Rear :
key = "Rear";
newDirs = getDirsFromFront(key);
saveVals[key] = newDirs;
// newDir = newDirs.first;
// newRot = newDirs.second;
break;
}
case Left : {
newDir = m_cube->getLeft();
newAxis = m_cube->getLeftRot();
case Left :
key = "Left";
newDirs = getDirsFromFront(key);
saveVals[key] = newDirs;
// newDir = newDirs.first;
// newRot = newDirs.second;
break;
}
case Right : {
newDir = m_cube->getRight();
newAxis = m_cube->getRightRot();
case Right :
key = "Right";
newDirs = getDirsFromFront(key);
saveVals[key] = newDirs;
// newDir = newDirs.first;
// newRot = newDirs.second;
break;
}
case Top : {
newDir = m_cube->getTop();
newAxis = m_cube->getTopRot();
case Top :
key = "Top";
newDirs = getDirsFromFront(key);
saveVals[key] = newDirs;
// newDir = newDirs.first;
// newRot = newDirs.second;
break;
}
case Bottom : {
newDir = m_cube->getBottom();
newAxis = m_cube->getBottomRot();
case Bottom :
key = "Bottom";
newDirs = getDirsFromFront(key);
saveVals[key] = newDirs;
// newDir = newDirs.first;
// newRot = newDirs.second;
break;
}
case FrontTopLeft : {
newDir = m_cube->getFTL();
newAxis = m_cube->getFTLRot();
case FrontTopLeft :
key = "FrontTopLeft";
newDirs = getDirsFromFront(key);
saveVals[key] = newDirs;
// newDir = newDirs.first;
// newRot = newDirs.second;
break;
}
case FrontTopRight : {
newDir = m_cube->getFTR();
newAxis = m_cube->getFTRRot();
case FrontTopRight :
key = "FrontTopRight";
newDirs = getDirsFromFront(key);
saveVals[key] = newDirs;
// newDir = newDirs.first;
// newRot = newDirs.second;
break;
}
case FrontBottomLeft : {
newDir = m_cube->getFBL();
newAxis = m_cube->getFBLRot();
case FrontBottomLeft :
key = "FrontBottomLeft";
newDirs = getDirsFromFront(key);
saveVals[key] = newDirs;
// newDir = newDirs.first;
// newRot = newDirs.second;
break;
}
case FrontBottomRight : {
newDir = m_cube->getFBR();
newAxis = m_cube->getFBRRot();
case FrontBottomRight :
key = "FrontBottomRight";
newDirs = getDirsFromFront(key);
saveVals[key] = newDirs;
newDir = newDirs.first;
newRot = newDirs.second;
break;
}
default: {
//TARFU invalid secondary type
Base::Console().Message("ERROR - DPG::updateSecondaryDirs - invalid projection type\n");
newDir = v->Direction.getValue();
newAxis = v->RotationVector.getValue();
newRot = v->RotationVector.getValue();
}
}
v->Direction.setValue(newDir);
v->RotationVector.setValue(newAxis);
// v->Direction.setValue(newDir);
// v->RotationVector.setValue(newRot);
}
//not sure if this is required.
for (auto& docObj: Views.getValues()) {
DrawProjGroupItem* v = static_cast<DrawProjGroupItem*>(docObj);
std::string type = v->Type.getValueAsString();
data = saveVals[type];
v->Direction.setValue(data.first);
v->RotationVector.setValue(data.second);
}
setPropsFromCube();
auto page = findParentPage();
if (page != nullptr) {
@@ -908,46 +990,74 @@ void DrawProjGroup::updateSecondaryDirs()
}
}
void DrawProjGroup::rotateRight()
{
//Front -> Right -> Rear -> Left -> Front
m_cube->rotateRight();
std::pair<Base::Vector3d,Base::Vector3d> newDirs;
newDirs = getDirsFromFront("Left");
DrawProjGroupItem* anchor = getAnchor();
anchor->Direction.setValue(newDirs.first);
anchor->RotationVector.setValue(newDirs.second);
updateSecondaryDirs();
}
void DrawProjGroup::rotateLeft()
{
//Front -> Left -> Rear -> Right -> Front
m_cube->rotateLeft();
std::pair<Base::Vector3d,Base::Vector3d> newDirs;
newDirs = getDirsFromFront("Right");
DrawProjGroupItem* anchor = getAnchor();
anchor->Direction.setValue(newDirs.first);
anchor->RotationVector.setValue(newDirs.second);
updateSecondaryDirs();
}
void DrawProjGroup::rotateUp()
{
//Front -> Top -> Rear -> Bottom -> Front
m_cube->rotateUp();
std::pair<Base::Vector3d,Base::Vector3d> newDirs;
newDirs = getDirsFromFront("Bottom");
DrawProjGroupItem* anchor = getAnchor();
anchor->Direction.setValue(newDirs.first);
anchor->RotationVector.setValue(newDirs.second);
updateSecondaryDirs();
}
void DrawProjGroup::rotateDown()
{
//Front -> Bottom -> Rear -> Top -> Front
m_cube->rotateDown();
std::pair<Base::Vector3d,Base::Vector3d> newDirs;
newDirs = getDirsFromFront("Top");
DrawProjGroupItem* anchor = getAnchor();
anchor->Direction.setValue(newDirs.first);
anchor->RotationVector.setValue(newDirs.second);
updateSecondaryDirs();
}
void DrawProjGroup::spinCW()
{
//Top -> Right -> Bottom -> Left -> Top
m_cube->spinCW();
DrawProjGroupItem* anchor = getAnchor();
double angle = M_PI / 2.0;
Base::Vector3d org(0.0,0.0,0.0);
Base::Vector3d curRot = anchor->RotationVector.getValue();
Base::Vector3d curDir = anchor->Direction.getValue();
Base::Vector3d newRot = DrawUtil::vecRotate(curRot,-angle,curDir,org);
anchor->RotationVector.setValue(newRot);
updateSecondaryDirs();
}
void DrawProjGroup::spinCCW()
{
//Top -> Left -> Bottom -> Right -> Top
m_cube->spinCCW();
DrawProjGroupItem* anchor = getAnchor();
double angle = M_PI / 2.0;
Base::Vector3d org(0.0,0.0,0.0);
Base::Vector3d curRot = anchor->RotationVector.getValue();
Base::Vector3d curDir = anchor->Direction.getValue();
Base::Vector3d newRot = DrawUtil::vecRotate(curRot,angle,curDir,org);
anchor->RotationVector.setValue(newRot);
updateSecondaryDirs();
}

View File

@@ -32,14 +32,12 @@
#include <Base/Matrix.h>
#include <Base/Vector3D.h>
//#include "Cube.h"
#include "DrawViewCollection.h"
namespace TechDraw
{
class DrawProjGroupItem;
class Cube;
/**
* Class super-container for managing a collection of DrawProjGroupItem
@@ -64,8 +62,6 @@ 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;
@@ -116,9 +112,10 @@ public:
void setAnchorDirection(Base::Vector3d dir);
Base::Vector3d getAnchorDirection(void);
TechDraw::DrawProjGroupItem* getAnchor(void);
std::pair<Base::Vector3d,Base::Vector3d> getDirsFromFront(DrawProjGroupItem* view);
std::pair<Base::Vector3d,Base::Vector3d> getDirsFromFront(std::string viewType);
void updateSecondaryDirs();
void resetCube(void);
void rotateRight(void);
void rotateLeft(void);
@@ -166,11 +163,8 @@ protected:
TechDraw::DrawPage * getPage(void) const;
void updateChildren(void);
void updateChildrenSource(void);
void setPropsFromCube(void);
void setCubeFromProps(void);
int getViewIndex(const char *viewTypeCStr) const;
TechDraw::Cube* m_cube;
};
} //namespace TechDraw

View File

@@ -27,6 +27,8 @@
#endif
#include <gp_Ax2.hxx>
#include <gp_Ax3.hxx>
#include <gp_Trsf.hxx>
#include <Base/Console.h>
#include <Base/Writer.h>
@@ -63,8 +65,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.setValue("Custom");
ScaleType.setStatus(App::Property::ReadOnly,true);
@@ -98,6 +100,15 @@ DrawProjGroupItem::~DrawProjGroupItem()
App::DocumentObjectExecReturn *DrawProjGroupItem::execute(void)
{
if (DrawUtil::checkParallel(Direction.getValue(),
RotationVector.getValue())) {
Base::Console().Message("TRACE - DPGI::execute - Projdir: %s X: %s\n",
TechDraw::DrawUtil::formatVector(Direction.getValue()).c_str(),
TechDraw::DrawUtil::formatVector(RotationVector.getValue()).c_str());
return new App::DocumentObjectExecReturn("DPGI: Direction and RotationVector are parallel");
}
App::DocumentObjectExecReturn * ret = DrawViewPart::execute();
delete ret;
@@ -160,21 +171,43 @@ bool DrawProjGroupItem::isAnchor(void)
return result;
}
/// get a coord system aligned with Direction and Rotation Vector
gp_Ax2 DrawProjGroupItem::getViewAxis(const Base::Vector3d& pt,
const Base::Vector3d& axis,
const bool flip) const
{
(void) flip;
gp_Ax2 viewAxis;
Base::Vector3d x = RotationVector.getValue();
Base::Vector3d nx = x;
x.Normalize();
Base::Vector3d na = axis;
na.Normalize();
viewAxis = TechDrawGeometry::getViewAxis(pt,axis,flip); //default orientation
if (!DrawUtil::checkParallel(nx,na)) { //!parallel/antiparallel
viewAxis = TechDrawGeometry::getViewAxis(pt,axis,x,flip);
if (DrawUtil::checkParallel(nx,na)) {
Base::Console().Warning("DPGI::getVA - axis and X parallel. using defaults\n");
viewAxis = TechDrawGeometry::getViewAxis(pt,axis,false);
} else {
viewAxis = TechDrawGeometry::getViewAxis(pt,na,nx,false);
}
// gp_Dir va_Main = viewAxis.Direction();
// gp_Dir va_X = viewAxis.XDirection();
// gp_Ax3 R3;
// gp_Ax3 viewCS(viewAxis);
// gp_Trsf txTo, txFrom;
// txTo.SetTransformation(R3,viewCS);
// txFrom = txTo.Inverted();
// gp_Dir dirFrom = va_Main.Transformed(txFrom);
// gp_Dir dirTo = va_Main.Transformed(txTo);
// Base::Console().Message("TRACE - DPGI::getVA - dirFrom: %s dirTo: %s\n",
// DrawUtil::formatVector(dirFrom).c_str(),
// DrawUtil::formatVector(dirTo).c_str());
// gp_Dir xFrom = va_X.Transformed(txFrom);
// gp_Dir xTo = va_X.Transformed(txTo);
// Base::Console().Message("TRACE - DPGI::getVA - xFrom: %s xTo: %s\n",
// DrawUtil::formatVector(xFrom).c_str(),
// DrawUtil::formatVector(xTo).c_str());
return viewAxis;
}

View File

@@ -1,4 +1,3 @@
/***************************************************************************
* Copyright (c) 2015 WandererFan <wandererfan@gmail.com> *
* *
@@ -38,7 +37,9 @@
#include <BRep_Tool.hxx>
#include <gp_Ax3.hxx>
#include <gp_Dir.hxx>
#include <gp_Pnt.hxx>
#include <gp_Vec.hxx>
#include <Precision.hxx>
#include <BRepAdaptor_Curve.hxx>
#include <BRepExtrema_DistShapeShape.hxx>
@@ -50,6 +51,10 @@
#include <TopExp.hxx>
#include <TopExp_Explorer.hxx>
#include <GProp_GProps.hxx>
#include <GeomLProp_SLProps.hxx>
#include <BRepAdaptor_Surface.hxx>
#include <BRepLProp_SLProps.hxx>
#include <BRepGProp_Face.hxx>
#endif
@@ -59,6 +64,10 @@
#include <Base/Parameter.h>
#include <Base/Vector3D.h>
#include <Mod/Part/App/PartFeature.h>
#include <Mod/Part/App/TopoShape.h>
#include "GeometryObject.h"
#include "DrawUtil.h"
using namespace TechDraw;
@@ -288,6 +297,27 @@ std::string DrawUtil::formatVector(const Base::Vector2d& v)
return result;
}
std::string DrawUtil::formatVector(const gp_Dir& v)
{
std::string result;
std::stringstream builder;
builder << std::fixed << std::setprecision(3) ;
builder << " (" << v.X() << "," << v.Y() << "," << v.Z() << ") ";
result = builder.str();
return result;
}
std::string DrawUtil::formatVector(const gp_Vec& v)
{
std::string result;
std::stringstream builder;
builder << std::fixed << std::setprecision(3) ;
builder << " (" << v.X() << "," << v.Y() << "," << v.Z() << ") ";
result = builder.str();
return result;
}
//! compare 2 vectors for sorting - true if v1 < v2
bool DrawUtil::vectorLess(const Base::Vector3d& v1, const Base::Vector3d& v2)
{

View File

@@ -29,6 +29,8 @@
#include <QByteArray>
#include <gp_Ax2.hxx>
#include <gp_Dir.hxx>
#include <gp_Vec.hxx>
#include <TopoDS.hxx>
#include <TopoDS_Vertex.hxx>
#include <TopoDS_Edge.hxx>
@@ -36,10 +38,13 @@
#include <TopoDS_Face.hxx>
#include <TopoDS_Shape.hxx>
#include <App/DocumentObject.h>
#include <Base/Tools2D.h>
#include <Base/Vector3D.h>
#include <Base/Matrix.h>
#include <Mod/Part/App/PartFeature.h>
#include "LineGroup.h"
#define VERTEXTOLERANCE (2.0 * Precision::Confusion())
@@ -65,6 +70,8 @@ class TechDrawExport DrawUtil {
static Base::Vector3d vertex2Vector(const TopoDS_Vertex& v);
static std::string formatVector(const Base::Vector3d& v);
static std::string formatVector(const Base::Vector2d& v);
static std::string formatVector(const gp_Dir& v);
static std::string formatVector(const gp_Vec& v);
static bool vectorLess(const Base::Vector3d& v1, const Base::Vector3d& v2);
static Base::Vector3d toR3(const gp_Ax2 fromSystem, const Base::Vector3d fromPoint);
static bool checkParallel(const Base::Vector3d v1, const Base::Vector3d v2, double tolerance = FLT_EPSILON);
@@ -83,7 +90,6 @@ class TechDrawExport DrawUtil {
static Base::Vector3d Intersect2d(Base::Vector3d p1, Base::Vector3d d1,
Base::Vector3d p2, Base::Vector3d d2);
//debugging routines
static void dumpVertexes(const char* text, const TopoDS_Shape& s);
static void dumpEdge(char* label, int i, TopoDS_Edge e);

View File

@@ -129,7 +129,8 @@ DrawViewPart::DrawViewPart(void) : geometryObject(0)
//properties that affect Geometry
ADD_PROPERTY_TYPE(Source ,(0),group,App::Prop_None,"3D Shape to view");
Source.setScope(App::LinkScope::Global);
ADD_PROPERTY_TYPE(Direction ,(0,0,1.0) ,group,App::Prop_None,"Projection direction. The direction you are looking from.");
ADD_PROPERTY_TYPE(Direction ,(0.0,-1.0,0.0),
group,App::Prop_None,"Projection direction. The direction you are looking from.");
ADD_PROPERTY_TYPE(Perspective ,(false),group,App::Prop_None,"Perspective(true) or Orthographic(false) projection");
ADD_PROPERTY_TYPE(Focus,(defDist),group,App::Prop_None,"Perspective view focus distance");
@@ -248,19 +249,18 @@ App::DocumentObjectExecReturn *DrawViewPart::execute(void)
inputCenter = TechDrawGeometry::findCentroid(shape,
Direction.getValue());
shapeCentroid = Base::Vector3d(inputCenter.X(),inputCenter.Y(),inputCenter.Z());
TopoDS_Shape mirroredShape;
mirroredShape = TechDrawGeometry::mirrorShape(shape,
inputCenter,
getScale());
gp_Ax2 viewAxis = getViewAxis(shapeCentroid,Direction.getValue());
if (!DrawUtil::fpCompare(Rotation.getValue(),0.0)) {
gp_Ax2 viewAxis = getViewAxis(shapeCentroid,Direction.getValue());
if (!DrawUtil::fpCompare(Rotation.getValue(),0.0)) {
mirroredShape = TechDrawGeometry::rotateShape(mirroredShape,
viewAxis,
Rotation.getValue());
}
geometryObject = buildGeometryObject(mirroredShape,viewAxis);
geometryObject = buildGeometryObject(mirroredShape,viewAxis);
#if MOD_TECHDRAW_HANDLE_FACES
if (handleFaces() && !geometryObject->usePolygonHLR()) {
@@ -690,7 +690,14 @@ gp_Ax2 DrawViewPart::getViewAxis(const Base::Vector3d& pt,
const Base::Vector3d& axis,
const bool flip) const
{
gp_Ax2 viewAxis = TechDrawGeometry::getViewAxis(pt,axis,flip);
gp_Ax2 viewAxis = TechDrawGeometry::getViewAxis(pt,axis,flip);
//put X dir of viewAxis on other side to get view right side up
gp_Ax1 rotAxis(viewAxis.Location(),viewAxis.Direction());
gp_Dir xDir = viewAxis.XDirection();
gp_Dir newX = xDir.Rotated(rotAxis, M_PI);
viewAxis.SetXDirection(newX);
return viewAxis;
}

View File

@@ -161,6 +161,18 @@ void GeometryObject::clear()
void GeometryObject::projectShape(const TopoDS_Shape& input,
const gp_Ax2 viewAxis)
{
gp_Pnt org(0.0,0.0,0.0);
gp_Dir stdY(0.0,1.0,0.0);
gp_Dir stdX(1.0,0.0,0.0);
gp_Ax2 yPlane(org,stdY,stdX); //XZ plane
gp_Dir va_Main = viewAxis.Direction();
gp_Dir dirRev = va_Main.Mirrored(yPlane);
gp_Dir va_X = viewAxis.XDirection();
gp_Dir xRev = va_X.Mirrored(yPlane);
gp_Ax2 projAxis(org,dirRev,xRev);
// Clear previous Geometry
clear();
@@ -172,10 +184,10 @@ void GeometryObject::projectShape(const TopoDS_Shape& input,
brep_hlr->Add(input, m_isoCount);
if (m_isPersp) {
double fLength = std::max(Precision::Confusion(),m_focus);
HLRAlgo_Projector projector( viewAxis, fLength );
HLRAlgo_Projector projector( projAxis, fLength );
brep_hlr->Projector(projector);
} else {
HLRAlgo_Projector projector( viewAxis );
HLRAlgo_Projector projector( projAxis );
brep_hlr->Projector(projector);
}
brep_hlr->Update();
@@ -543,21 +555,20 @@ bool GeometryObject::findVertex(Base::Vector2d v)
/// utility non-class member functions
//! gets a coordinate system that matches view system used in 3D with +Z up (or +Y up if necessary)
//! used for individual views, but not secondary views in projection groups
//! flip determines Y mirror or not.
// getViewAxis 1
gp_Ax2 TechDrawGeometry::getViewAxis(const Base::Vector3d origin,
const Base::Vector3d& direction,
const bool flip)
{
(void) flip;
gp_Pnt inputCenter(origin.x,origin.y,origin.z);
Base::Vector3d stdZ(0.0,0.0,1.0);
Base::Vector3d flipDirection(direction.x,-direction.y,direction.z);
if (!flip) {
flipDirection = Base::Vector3d(direction.x,direction.y,direction.z);
}
flipDirection = Base::Vector3d(direction.x,direction.y,direction.z);
Base::Vector3d cross = flipDirection;
//special cases
if ((flipDirection - stdZ).Length() < Precision::Confusion()) {
cross = Base::Vector3d(1.0,0.0,0.0);
} else if ((flipDirection - (stdZ * -1.0)).Length() < Precision::Confusion()) {
//special case
if (TechDraw::DrawUtil::checkParallel(flipDirection, stdZ)) {
cross = Base::Vector3d(1.0,0.0,0.0);
} else {
cross.Normalize();
@@ -566,30 +577,36 @@ gp_Ax2 TechDrawGeometry::getViewAxis(const Base::Vector3d origin,
gp_Ax2 viewAxis;
viewAxis = gp_Ax2(inputCenter,
gp_Dir(flipDirection.x, flipDirection.y, flipDirection.z),
// gp_Dir(1.0, 1.0, 0.0));
gp_Dir(cross.x, cross.y, cross.z));
return viewAxis;
}
//! gets a coordinate system specified by Z and X directions
//getViewAxis 2
gp_Ax2 TechDrawGeometry::getViewAxis(const Base::Vector3d origin,
const Base::Vector3d& direction,
const Base::Vector3d& xAxis,
const bool flip)
{
(void) flip;
gp_Pnt inputCenter(origin.x,origin.y,origin.z);
Base::Vector3d flipDirection(direction.x,-direction.y,direction.z);
if (!flip) {
flipDirection = Base::Vector3d(direction.x,direction.y,direction.z);
}
Base::Vector3d projDir(direction.x,direction.y,direction.z);
gp_Ax2 viewAxis;
viewAxis = gp_Ax2(inputCenter,
gp_Dir(flipDirection.x, flipDirection.y, flipDirection.z),
gp_Dir(xAxis.x, xAxis.y, xAxis.z));
if (TechDraw::DrawUtil::checkParallel(projDir, xAxis)) {
Base::Console().Warning("GO::getViewAxis2 - direction and axis parallel - using default VA\n");
viewAxis = gp_Ax2(inputCenter,
gp_Dir(projDir.x, projDir.y, projDir.z));
} else {
viewAxis = gp_Ax2(inputCenter,
gp_Dir(projDir.x, projDir.y, projDir.z),
gp_Dir(xAxis.x, xAxis.y, xAxis.z));
}
return viewAxis;
}
//TODO: cardinal directions don't seem to affect result. is this right?
//! Returns the centroid of shape, as viewed according to direction
gp_Pnt TechDrawGeometry::findCentroid(const TopoDS_Shape &shape,
const Base::Vector3d &direction)

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>