committed by
WandererFan
parent
516595fbce
commit
4d9e4efc87
@@ -101,6 +101,16 @@ using namespace TechDraw;
|
||||
}
|
||||
}
|
||||
|
||||
/*static*/ std::vector<int> DrawUtil::getIndexFromName(const std::vector<std::string>& geomNames)
|
||||
{
|
||||
std::vector<int> result;
|
||||
result.reserve(200);
|
||||
for (const std::string& geomName : geomNames) {
|
||||
result.push_back(getIndexFromName(geomName));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
std::string DrawUtil::getGeomTypeFromName(const std::string& geomName)
|
||||
{
|
||||
if (geomName.empty()) {
|
||||
@@ -126,6 +136,20 @@ std::string DrawUtil::getGeomTypeFromName(const std::string& geomName)
|
||||
}
|
||||
}
|
||||
|
||||
//! Check if all geomNames are of same geomType
|
||||
//! Edge1, Edge2, Edge3 -> true
|
||||
//! Edge1, Edge2, Vertex7 -> false
|
||||
bool DrawUtil::isGeomTypeConsistent(const std::vector<std::string>& geomNames)
|
||||
{
|
||||
std::string reference = getGeomTypeFromName(geomNames.at(0));
|
||||
for (std::string geomName : geomNames) {
|
||||
if (reference != getGeomTypeFromName(geomName)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string DrawUtil::makeGeomName(const std::string& geomType, int index)
|
||||
{
|
||||
std::stringstream newName;
|
||||
|
||||
@@ -91,7 +91,9 @@ class TechDrawExport DrawUtil
|
||||
{
|
||||
public:
|
||||
static int getIndexFromName(const std::string& geomName);
|
||||
static std::vector<int> getIndexFromName(const std::vector<std::string>& geomNames);
|
||||
static std::string getGeomTypeFromName(const std::string& geomName);
|
||||
static bool isGeomTypeConsistent(const std::vector<std::string>& geomNames);
|
||||
static std::string makeGeomName(const std::string& geomType, int index);
|
||||
static bool isSamePoint(TopoDS_Vertex v1, TopoDS_Vertex v2, double tolerance = VERTEXTOLERANCE);
|
||||
static bool isZeroEdge(TopoDS_Edge e, double tolerance = VERTEXTOLERANCE);
|
||||
|
||||
@@ -74,6 +74,7 @@ void CreateTechDrawCommandsAnnotate();
|
||||
void CreateTechDrawCommandsExtensionDims();
|
||||
void CreateTechDrawCommandsExtensions();
|
||||
void CreateTechDrawCommandsStack();
|
||||
void CreateTechDrawCommandsAlign();
|
||||
|
||||
void loadTechDrawResource()
|
||||
{
|
||||
@@ -130,6 +131,7 @@ PyMOD_INIT_FUNC(TechDrawGui)
|
||||
CreateTechDrawCommandsExtensions();
|
||||
CreateTechDrawCommandsDims();
|
||||
CreateTechDrawCommandsStack();
|
||||
CreateTechDrawCommandsAlign();
|
||||
|
||||
TechDrawGui::Workbench::init();
|
||||
TechDrawGui::MDIViewPage::init();
|
||||
|
||||
@@ -101,6 +101,7 @@ SET(TechDrawGui_SRCS
|
||||
CommandCreateDims.cpp
|
||||
CommandDecorate.cpp
|
||||
CommandAnnotate.cpp
|
||||
CommandAlign.cpp
|
||||
CommandExtensionDims.cpp
|
||||
CommandExtensionDims.h
|
||||
CommandExtensionPack.cpp
|
||||
|
||||
183
src/Mod/TechDraw/Gui/CommandAlign.cpp
Normal file
183
src/Mod/TechDraw/Gui/CommandAlign.cpp
Normal file
@@ -0,0 +1,183 @@
|
||||
/***************************************************************************
|
||||
* Copyright (c) 2024 Benjamin Bræstrup Sayoc <benj5378@outlook.com> *
|
||||
* *
|
||||
* 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 <QMessageBox>
|
||||
|
||||
#include <App/DocumentObject.h>
|
||||
#include <Base/Console.h>
|
||||
#include <Gui/Action.h>
|
||||
#include <Gui/Command.h>
|
||||
#include <Gui/Document.h>
|
||||
#include <Gui/MainWindow.h>
|
||||
#include <Gui/Selection/Selection.h>
|
||||
|
||||
#include <Mod/TechDraw/App/DrawViewPart.h>
|
||||
#include <Mod/TechDraw/App/DrawUtil.h>
|
||||
|
||||
#include "QGIView.h"
|
||||
#include "DrawGuiUtil.h"
|
||||
#include "ViewProviderViewPart.h"
|
||||
|
||||
|
||||
const auto& getSelection = Gui::Command::getSelection; // alias
|
||||
using namespace TechDrawGui;
|
||||
using namespace TechDraw;
|
||||
|
||||
namespace TechDrawGui {
|
||||
class QGIEdge;
|
||||
class QGIVertex;
|
||||
}
|
||||
|
||||
namespace {
|
||||
void incorrectSelection()
|
||||
{
|
||||
QMessageBox::warning(
|
||||
Gui::getMainWindow(),
|
||||
QObject::tr("Incorrect Selection"),
|
||||
QObject::tr("You must select 2 vertexes or 1 edge\n")
|
||||
);
|
||||
}
|
||||
|
||||
void CmdTechDrawAlignByRotation(const Base::Vector2d& direction)
|
||||
{
|
||||
std::vector<TechDraw::DrawViewPart*> dvps = getSelection().getObjectsOfType<TechDraw::DrawViewPart>();
|
||||
if (dvps.size() != 1) {
|
||||
incorrectSelection();
|
||||
return;
|
||||
}
|
||||
TechDraw::DrawViewPart* dvp = dvps[0];
|
||||
|
||||
Gui::Document* guiDoc = Gui::Application::Instance->getDocument(dvp->getDocument());
|
||||
if (!guiDoc) {
|
||||
return;
|
||||
}
|
||||
|
||||
Gui::ViewProvider* gvp = guiDoc->getViewProvider(dvp);
|
||||
auto vpdvp = static_cast<TechDrawGui::ViewProviderViewPart*>(gvp);
|
||||
if (!vpdvp) {
|
||||
return;
|
||||
}
|
||||
QGIView* view = vpdvp->getQView();
|
||||
|
||||
std::vector<std::string> subNames = getSelection().getSelectionEx()[0].getSubNames();
|
||||
if(!DrawUtil::isGeomTypeConsistent(subNames)) {
|
||||
incorrectSelection();
|
||||
return;
|
||||
}
|
||||
|
||||
std::vector<int> subIndexes = DrawUtil::getIndexFromName(subNames);
|
||||
std::string subType = DrawUtil::getGeomTypeFromName(subNames.at(0));
|
||||
if (subType == "Vertex") {
|
||||
std::vector<QGIVertex*> vertexes = view->getObjects<QGIVertex*>(subIndexes);
|
||||
if (vertexes.size() == 2) {
|
||||
QGIVertex* v1 = vertexes.front();
|
||||
QGIVertex* v2 = vertexes.back();
|
||||
DrawGuiUtil::rotateToAlign(v1, v2, direction);
|
||||
dvp->recomputeFeature();
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (subType == "Edge") {
|
||||
std::vector<QGIEdge*> edges = view->getObjects<QGIEdge*>(subIndexes);
|
||||
if (edges.size() == 1) {
|
||||
DrawGuiUtil::rotateToAlign(edges.at(0), direction);
|
||||
dvp->recomputeFeature();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
incorrectSelection();
|
||||
}
|
||||
} // anonymous namespace
|
||||
|
||||
|
||||
//===========================================================================
|
||||
// TechDraw_AlignVertexesVertically
|
||||
//===========================================================================
|
||||
|
||||
DEF_STD_CMD_A(CmdTechDrawAlignVertexesVertically)
|
||||
|
||||
CmdTechDrawAlignVertexesVertically::CmdTechDrawAlignVertexesVertically()
|
||||
: Command("TechDraw_AlignVertexesVertically")
|
||||
{
|
||||
sAppModule = "TechDraw";
|
||||
sGroup = QT_TR_NOOP("TechDraw");
|
||||
sMenuText = QT_TR_NOOP("Align vertexes/edge vertically by view rotation");
|
||||
sToolTipText = sMenuText;
|
||||
sWhatsThis = "TechDraw_AlignGroup";
|
||||
sStatusTip = sToolTipText;
|
||||
}
|
||||
|
||||
void CmdTechDrawAlignVertexesVertically::activated(int iMsg)
|
||||
{
|
||||
Q_UNUSED(iMsg)
|
||||
|
||||
Base::Vector2d Vertical(0.0, 1.0);
|
||||
CmdTechDrawAlignByRotation(Vertical);
|
||||
}
|
||||
|
||||
bool CmdTechDrawAlignVertexesVertically::isActive(void)
|
||||
{
|
||||
bool havePage = DrawGuiUtil::needPage(this);
|
||||
bool haveView = DrawGuiUtil::needView(this, false);
|
||||
return (havePage && haveView);
|
||||
}
|
||||
|
||||
|
||||
//===========================================================================
|
||||
// TechDraw_AlignVertexesHorizontally
|
||||
//===========================================================================
|
||||
|
||||
DEF_STD_CMD_A(CmdTechDrawAlignVertexesHorizontally)
|
||||
|
||||
CmdTechDrawAlignVertexesHorizontally::CmdTechDrawAlignVertexesHorizontally()
|
||||
: Command("TechDraw_AlignVertexesHorizontally")
|
||||
{
|
||||
sAppModule = "TechDraw";
|
||||
sGroup = QT_TR_NOOP("TechDraw");
|
||||
sMenuText = QT_TR_NOOP("Align vertexes/edge horizontally by view rotation");
|
||||
sToolTipText = sMenuText;
|
||||
sWhatsThis = "TechDraw_AlignGroup";
|
||||
sStatusTip = sToolTipText;
|
||||
}
|
||||
|
||||
void CmdTechDrawAlignVertexesHorizontally::activated(int iMsg)
|
||||
{
|
||||
Q_UNUSED(iMsg)
|
||||
|
||||
Base::Vector2d Horizontal(1.0, 0.0);
|
||||
CmdTechDrawAlignByRotation(Horizontal);
|
||||
}
|
||||
|
||||
bool CmdTechDrawAlignVertexesHorizontally::isActive(void)
|
||||
{
|
||||
bool havePage = DrawGuiUtil::needPage(this);
|
||||
bool haveView = DrawGuiUtil::needView(this, false);
|
||||
return (havePage && haveView);
|
||||
}
|
||||
|
||||
|
||||
void CreateTechDrawCommandsAlign(void)
|
||||
{
|
||||
Gui::CommandManager& rcCmdMgr = Gui::Application::Instance->commandManager();
|
||||
|
||||
rcCmdMgr.addCommand(new CmdTechDrawAlignVertexesVertically());
|
||||
rcCmdMgr.addCommand(new CmdTechDrawAlignVertexesHorizontally());
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
/***************************************************************************
|
||||
* Copyright (c) 2016 WandererFan <wandererfan@gmail.com> *
|
||||
* Copyright (c) 2024 Benjamin Bræstrup Sayoc <benj5378@outlook.com> *
|
||||
* *
|
||||
* This file is part of the FreeCAD CAx development system. *
|
||||
* *
|
||||
@@ -48,6 +49,7 @@
|
||||
#include <Base/Exception.h>
|
||||
#include <Base/Parameter.h>
|
||||
#include <Base/Tools.h>
|
||||
#include <Base/Tools2D.h>
|
||||
#include <Base/Type.h>
|
||||
#include <Gui/Application.h>
|
||||
#include <Gui/Command.h>
|
||||
@@ -74,6 +76,9 @@
|
||||
#include "DlgPageChooser.h"
|
||||
#include "DrawGuiUtil.h"
|
||||
#include "MDIViewPage.h"
|
||||
#include "QGIEdge.h"
|
||||
#include "QGIVertex.h"
|
||||
#include "QGIViewPart.h"
|
||||
#include "QGSPage.h"
|
||||
#include "ViewProviderPage.h"
|
||||
#include "Rez.h"
|
||||
@@ -776,3 +781,53 @@ QIcon DrawGuiUtil::maskBlackPixels(QIcon itemIcon, QSize iconSize, QColor textCo
|
||||
return filler;
|
||||
}
|
||||
|
||||
void DrawGuiUtil::rotateToAlign(const QGIEdge* edge, const Base::Vector2d& direction)
|
||||
{
|
||||
QGIViewPart* view = static_cast<QGIViewPart*>(edge->parentItem());
|
||||
DrawViewPart* dvp = static_cast<DrawViewPart*>(view->getViewObject());
|
||||
BaseGeomPtr bg = dvp->getEdgeGeometry().at(edge->getProjIndex());
|
||||
std::vector<Base::Vector3d> endPoints = bg->findEndPoints();
|
||||
Base::Vector3d oldDirection3d = endPoints.at(0) - endPoints.at(1);
|
||||
Base::Vector2d oldDirection2d(oldDirection3d.x, oldDirection3d.y);
|
||||
rotateToAlign(dvp, oldDirection2d, direction);
|
||||
}
|
||||
|
||||
//! The view of p1 and p2 will be rotated to make p1 and p2 aligned with direction (for instance horizontalle aligned)
|
||||
void DrawGuiUtil::rotateToAlign(const QGIVertex* p1, const QGIVertex* p2, const Base::Vector2d& direction)
|
||||
{
|
||||
QGIViewPart* view = static_cast<QGIViewPart*>(p1->parentItem());
|
||||
if(view != static_cast<QGIViewPart*>(p2->parentItem())) {
|
||||
Base::Console().Error("Vertexes have to be from the same view!");
|
||||
}
|
||||
|
||||
Base::Vector2d oldDirection = p2->vector2dBetweenPoints(p1);
|
||||
DrawViewPart* dvp = static_cast<DrawViewPart*>(view->getViewObject());
|
||||
rotateToAlign(dvp, oldDirection, direction);
|
||||
}
|
||||
|
||||
void DrawGuiUtil::rotateToAlign(DrawViewPart* view, const Base::Vector2d& oldDirection, const Base::Vector2d& newDirection)
|
||||
{
|
||||
// If pointing counterclockwise, we need to rotate clockwise
|
||||
// If pointing clockwise, we need to rotate counter clockwise
|
||||
int cw = 1;
|
||||
if(newDirection.Angle() > oldDirection.Angle()) {
|
||||
cw = -1;
|
||||
}
|
||||
|
||||
double toRotate = newDirection.GetAngle(oldDirection);
|
||||
// Radians to degrees
|
||||
toRotate = toRotate * 180 / M_PI;
|
||||
|
||||
// Rotate least amount possible
|
||||
if(toRotate > 90) {
|
||||
// Instead of rotating 145 degrees to match direction
|
||||
// we only rotate -35 degrees
|
||||
toRotate = toRotate - 180;
|
||||
}
|
||||
else if(toRotate < -90) {
|
||||
toRotate = toRotate + 180;
|
||||
}
|
||||
|
||||
double oldRotation = view->Rotation.getValue();
|
||||
view->Rotation.setValue(oldRotation + toRotate * cw);
|
||||
}
|
||||
|
||||
@@ -44,14 +44,21 @@ class Feature;
|
||||
namespace TechDraw {
|
||||
class DrawPage;
|
||||
class DrawView;
|
||||
class DrawViewPart;
|
||||
class LineGenerator;
|
||||
}
|
||||
namespace Gui {
|
||||
class Command;
|
||||
}
|
||||
|
||||
namespace Base {
|
||||
class Vector2d;
|
||||
}
|
||||
|
||||
namespace TechDrawGui
|
||||
{
|
||||
class QGIEdge;
|
||||
class QGIVertex;
|
||||
|
||||
/// Convenient utility functions for TechDraw Gui Module
|
||||
class TechDrawGuiExport DrawGuiUtil {
|
||||
@@ -94,6 +101,10 @@ class TechDrawGuiExport DrawGuiUtil {
|
||||
const App::DocumentObject& targetObject);
|
||||
static std::vector<std::string> getSubsForSelectedObject(const std::vector<Gui::SelectionObject>& selection,
|
||||
App::DocumentObject* selectedObj);
|
||||
|
||||
static void rotateToAlign(const QGIEdge* edge, const Base::Vector2d& direction);
|
||||
static void rotateToAlign(const QGIVertex* p1, const QGIVertex* p2, const Base::Vector2d& direction);
|
||||
static void rotateToAlign(TechDraw::DrawViewPart* view, const Base::Vector2d& oldDirection, const Base::Vector2d& newDirection);
|
||||
};
|
||||
|
||||
} //end namespace TechDrawGui
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
/***************************************************************************
|
||||
* Copyright (c) 2013 Luke Parry <l.parry@warwick.ac.uk> *
|
||||
* Copyright (c) 2024 Benjamin Bræstrup Sayoc <benj5378@outlook.com> *
|
||||
* *
|
||||
* This file is part of the FreeCAD CAx development system. *
|
||||
* *
|
||||
@@ -29,6 +30,8 @@
|
||||
# include <QStyleOptionGraphicsItem>
|
||||
#endif
|
||||
|
||||
#include <Base/Tools2D.h>
|
||||
|
||||
#include "QGIVertex.h"
|
||||
#include "PreferencesGui.h"
|
||||
#include "QGIPrimPath.h"
|
||||
@@ -67,3 +70,16 @@ void QGIVertex::paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
|
||||
// setBrush(m_brush);
|
||||
QGIPrimPath::paint (painter, &myOption, widget);
|
||||
}
|
||||
|
||||
Base::Vector2d QGIVertex::toVector2d() const
|
||||
{
|
||||
QPointF center = boundingRect().center();
|
||||
center = mapToScene(center);
|
||||
return Base::Vector2d(center.x(), center.y());
|
||||
}
|
||||
|
||||
//! Returns a vector drawn from own position to p2
|
||||
Base::Vector2d QGIVertex::vector2dBetweenPoints(const QGIVertex* p2) const
|
||||
{
|
||||
return p2->toVector2d() - toVector2d();
|
||||
}
|
||||
|
||||
@@ -27,6 +27,10 @@
|
||||
|
||||
# include "QGIPrimPath.h"
|
||||
|
||||
namespace Base {
|
||||
class Vector2d;
|
||||
}
|
||||
|
||||
namespace TechDrawGui
|
||||
{
|
||||
|
||||
@@ -45,6 +49,9 @@ public:
|
||||
float getRadius() { return m_radius; }
|
||||
virtual void setRadius(float r);
|
||||
|
||||
Base::Vector2d toVector2d() const;
|
||||
Base::Vector2d vector2dBetweenPoints(const QGIVertex* p2) const;
|
||||
|
||||
protected:
|
||||
bool multiselectEligible() override { return true; }
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
/***************************************************************************
|
||||
* Copyright (c) 2012-2013 Luke Parry <l.parry@warwick.ac.uk> *
|
||||
* Copyright (c) 2024 Benjamin Bræstrup Sayoc <benj5378@outlook.com> *
|
||||
* *
|
||||
* This file is part of the FreeCAD CAx development system. *
|
||||
* *
|
||||
@@ -56,6 +57,7 @@
|
||||
#include "QGCustomImage.h"
|
||||
#include "QGCustomLabel.h"
|
||||
#include "QGICaption.h"
|
||||
#include "QGIEdge.h"
|
||||
#include "QGIVertex.h"
|
||||
#include "QGIViewClip.h"
|
||||
#include "QGSPage.h"
|
||||
@@ -972,4 +974,31 @@ void QGIView::makeMark(QPointF pos, QColor color)
|
||||
makeMark(pos.x(), pos.y(), color);
|
||||
}
|
||||
|
||||
//! Retrieves objects of type T with given indexes
|
||||
template <typename T>
|
||||
std::vector<T> QGIView::getObjects(std::vector<int> indexes)
|
||||
{
|
||||
QList<QGraphicsItem*> children = childItems();
|
||||
std::vector<T> result;
|
||||
for (QGraphicsItem*& child : children) {
|
||||
// Convert QGIVertex* (as T) to QGIVertex
|
||||
if (child->type() != std::remove_pointer<T>::type::Type) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Get index of child item
|
||||
T object = static_cast<T>(child);
|
||||
int target = object->getProjIndex();
|
||||
// If child item's index in indexes, then add to results
|
||||
if (std::find(indexes.begin(), indexes.end(), target) != indexes.end()) {
|
||||
result.push_back(object);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
template std::vector<QGIVertex*> QGIView::getObjects<QGIVertex*>(std::vector<int>);
|
||||
template std::vector<QGIEdge*> QGIView::getObjects<QGIEdge*>(std::vector<int>);
|
||||
|
||||
|
||||
#include <Mod/TechDraw/Gui/moc_QGIView.cpp>
|
||||
|
||||
@@ -168,6 +168,9 @@ public:
|
||||
void mouseMoveEvent(QGraphicsSceneMouseEvent *event) override;
|
||||
void mouseReleaseEvent(QGraphicsSceneMouseEvent *event) override;
|
||||
|
||||
template <typename T>
|
||||
std::vector<T> getObjects(std::vector<int> indexes);
|
||||
|
||||
protected:
|
||||
QGIView* getQGIVByName(std::string name);
|
||||
|
||||
|
||||
@@ -252,6 +252,12 @@ Gui::MenuItem* Workbench::setupMenuBar() const
|
||||
*symbols << "TechDraw_SurfaceFinishSymbols";
|
||||
*symbols << "TechDraw_HoleShaftFit";
|
||||
|
||||
|
||||
Gui::MenuItem* aligning = new Gui::MenuItem;
|
||||
aligning->setCommand("Aligning");
|
||||
*aligning << "TechDraw_AlignVertexesVertically";
|
||||
*aligning << "TechDraw_AlignVertexesHorizontally";
|
||||
|
||||
// main menu
|
||||
draw->setCommand("TechDraw");
|
||||
*draw << pages;
|
||||
@@ -267,6 +273,7 @@ Gui::MenuItem* Workbench::setupMenuBar() const
|
||||
*draw << symbols;
|
||||
*draw << "Separator";
|
||||
*draw << stacking;
|
||||
*draw << aligning;
|
||||
*draw << "Separator";
|
||||
*draw << toolattrib;
|
||||
*draw << toolcenter;
|
||||
|
||||
Reference in New Issue
Block a user