Files
create/src/Mod/TechDraw/Gui/CommandExtensionPack.cpp
2021-09-06 18:32:45 +02:00

460 lines
19 KiB
C++

/***************************************************************************
* Copyright (c) 2021 edi *
* *
* 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 <QMessageBox>
# include <iostream>
# include <string>
# include <sstream>
# include <cstdlib>
# include <exception>
#endif //#ifndef _PreComp_
#include <QGraphicsView>
# include <App/DocumentObject.h>
# include <Base/Exception.h>
#include <Base/Console.h>
#include <Base/Type.h>
# include <Gui/Action.h>
# include <Gui/Application.h>
# include <Gui/BitmapFactory.h>
# include <Gui/Command.h>
# include <Gui/Control.h>
# include <Gui/Document.h>
# include <Gui/Selection.h>
# include <Gui/MainWindow.h>
# include <Gui/FileDialog.h>
# include <Gui/ViewProvider.h>
# include <Mod/Part/App/PartFeature.h>
# include <Mod/TechDraw/App/DrawViewPart.h>
# include <Mod/TechDraw/App/DrawProjGroupItem.h>
# include <Mod/TechDraw/App/DrawProjGroup.h>
# include <Mod/TechDraw/App/DrawViewDimension.h>
# include <Mod/TechDraw/App/DrawDimHelper.h>
# include <Mod/TechDraw/App/LandmarkDimension.h>
# include <Mod/TechDraw/App/DrawPage.h>
# include <Mod/TechDraw/App/DrawUtil.h>
# include <Mod/TechDraw/App/Geometry.h>
#include <Mod/TechDraw/Gui/QGVPage.h>
#include "DrawGuiUtil.h"
#include "MDIViewPage.h"
#include "ViewProviderPage.h"
#include "TaskLinkDim.h"
using namespace TechDrawGui;
using namespace TechDraw;
using namespace std;
//internal helper functions
bool _circulation(Base::Vector3d A, Base::Vector3d B, Base::Vector3d C);
void _createThreadCircle(std::string Name, TechDraw::DrawViewPart* objFeat, float factor);
void _createThreadLines(std::vector<std::string> SubNames, TechDraw::DrawViewPart* objFeat, float factor);
void _setStyleAndWeight(TechDraw::CosmeticEdge* cosEdge, int style, float weight);
//===========================================================================
// TechDraw_ExtensionCircleCenterLines
//===========================================================================
DEF_STD_CMD_A(CmdTechDrawExtensionCircleCenterLines)
CmdTechDrawExtensionCircleCenterLines::CmdTechDrawExtensionCircleCenterLines()
: Command("TechDraw_ExtensionCircleCenterLines")
{
sAppModule = "TechDraw";
sGroup = QT_TR_NOOP("TechDraw");
sMenuText = QT_TR_NOOP("Draw circle center lines");
sToolTipText = QT_TR_NOOP("Draw circle center line cross at circles\n\
- select many circles or arcs\n\
- click this button");
sWhatsThis = "TechDraw_ExtensionCircleCenterLines";
sStatusTip = sToolTipText;
sPixmap = "TechDraw_ExtensionCircleCenterLines";
}
void CmdTechDrawExtensionCircleCenterLines::activated(int iMsg)
{
Q_UNUSED(iMsg);
auto selection = getSelection().getSelectionEx();
if( selection.empty() ) {
QMessageBox::warning(Gui::getMainWindow(),
QObject::tr("TechDraw Circle Centerlines"),
QObject::tr("Selection is empty"));
return;
}
auto objFeat = dynamic_cast<TechDraw::DrawViewPart *>(selection[0].getObject());
if( objFeat == nullptr ) {
QMessageBox::warning(Gui::getMainWindow(),
QObject::tr("TechDraw Circle Centerlines"),
QObject::tr("No object selected"));
return;
}
double scale = objFeat->getScale();
const std::vector<std::string> SubNames = selection[0].getSubNames();
for (std::string Name : SubNames) {
int GeoId = TechDraw::DrawUtil::getIndexFromName(Name);
TechDraw::BaseGeom* geom = objFeat->getGeomByIndex(GeoId);
std::string GeoType = TechDraw::DrawUtil::getGeomTypeFromName(Name);
if (GeoType == "Edge"){
if (geom->geomType == TechDraw::CIRCLE ||
geom->geomType == TechDraw::ARCOFCIRCLE){
TechDraw::Circle* cgen = static_cast<TechDraw::Circle *>(geom);
Base::Vector3d center = cgen->center;
center.y = -center.y;
float radius = cgen->radius;
Base::Vector3d right(center.x+radius+2.0,center.y,0.0);
Base::Vector3d top(center.x,center.y+radius+2.0,0.0);
Base::Vector3d left(center.x-radius-2.0,center.y,0.0);
Base::Vector3d bottom(center.x,center.y-radius-2.0,0.0);
std::string line1tag = objFeat->addCosmeticEdge(right/scale, left/scale);
std::string line2tag = objFeat->addCosmeticEdge(top/scale, bottom/scale);
TechDraw::CosmeticEdge* horiz = objFeat->getCosmeticEdge(line1tag);
_setStyleAndWeight(horiz,4,0.35);
TechDraw::CosmeticEdge* vert = objFeat->getCosmeticEdge(line2tag);
_setStyleAndWeight(vert,4,0.35);
}
}
}
getSelection().clearSelection();
objFeat->refreshCEGeoms();
objFeat->requestPaint();
}
bool CmdTechDrawExtensionCircleCenterLines::isActive(void)
{
bool havePage = DrawGuiUtil::needPage(this);
bool haveView = DrawGuiUtil::needView(this);
return (havePage && haveView);
}
//===========================================================================
// TechDraw_ExtensionThreadHoleSide
//===========================================================================
DEF_STD_CMD_A(CmdTechDrawExtensionThreadHoleSide)
CmdTechDrawExtensionThreadHoleSide::CmdTechDrawExtensionThreadHoleSide()
: Command("TechDraw_ExtensionThreadHoleSide")
{
sAppModule = "TechDraw";
sGroup = QT_TR_NOOP("TechDraw");
sMenuText = QT_TR_NOOP("Cosmetic thread hole side view");
sToolTipText = QT_TR_NOOP("Draw cosmetic thread hole side view\n\
- select two parallel lines\n\
- click this button");
sWhatsThis = "TechDraw_ExtensionThreadHoleSide";
sStatusTip = sToolTipText;
sPixmap = "TechDraw_ExtensionThreadHoleSide";
}
void CmdTechDrawExtensionThreadHoleSide::activated(int iMsg)
{
Q_UNUSED(iMsg);
auto selection = getSelection().getSelectionEx();
if( selection.empty() ) {
QMessageBox::warning(Gui::getMainWindow(),
QObject::tr("TechDraw Thread Hole Side"),
QObject::tr("Selection is empty"));
return;
}
TechDraw::DrawViewPart* objFeat = dynamic_cast<TechDraw::DrawViewPart *>(selection[0].getObject());
if( objFeat == nullptr ) {
QMessageBox::warning(Gui::getMainWindow(),
QObject::tr("TechDraw Thread Hole Side"),
QObject::tr("No object selected"));
return;
}
const std::vector<std::string> SubNames = selection[0].getSubNames();
if (SubNames.size() >= 2) {
_createThreadLines(SubNames, objFeat, 1.176);
}
getSelection().clearSelection();
objFeat->refreshCEGeoms();
objFeat->requestPaint();
}
bool CmdTechDrawExtensionThreadHoleSide::isActive(void)
{
bool havePage = DrawGuiUtil::needPage(this);
bool haveView = DrawGuiUtil::needView(this);
return (havePage && haveView);
}
//===========================================================================
// TechDraw_ExtensionThreadBoltSide
//===========================================================================
DEF_STD_CMD_A(CmdTechDrawExtensionThreadBoltSide)
CmdTechDrawExtensionThreadBoltSide::CmdTechDrawExtensionThreadBoltSide()
: Command("TechDraw_ExtensionThreadBoltSide")
{
sAppModule = "TechDraw";
sGroup = QT_TR_NOOP("TechDraw");
sMenuText = QT_TR_NOOP("Cosmetic thread bolt side view");
sToolTipText = QT_TR_NOOP("Draw cosmetic screw thread side view\n\
- select two parallel lines\n\
- click this button");
sWhatsThis = "TechDraw_ExtensionThreadBoltSide";
sStatusTip = sToolTipText;
sPixmap = "TechDraw_ExtensionThreadBoltSide";
}
void CmdTechDrawExtensionThreadBoltSide::activated(int iMsg)
{
Q_UNUSED(iMsg);
auto selection = getSelection().getSelectionEx();
if( selection.empty() ) {
QMessageBox::warning(Gui::getMainWindow(),
QObject::tr("TechDraw Thread Bolt Side"),
QObject::tr("Selection is empty"));
return;
}
TechDraw::DrawViewPart* objFeat = dynamic_cast<TechDraw::DrawViewPart *>(selection[0].getObject());
if( objFeat == nullptr ) {
QMessageBox::warning(Gui::getMainWindow(),
QObject::tr("TechDraw Thread Bolt Side"),
QObject::tr("No object selected"));
return;
}
const std::vector<std::string> SubNames = selection[0].getSubNames();
if (SubNames.size() >= 2) {
_createThreadLines(SubNames, objFeat, 0.85);
}
getSelection().clearSelection();
objFeat->refreshCEGeoms();
objFeat->requestPaint();
}
bool CmdTechDrawExtensionThreadBoltSide::isActive(void)
{
bool havePage = DrawGuiUtil::needPage(this);
bool haveView = DrawGuiUtil::needView(this);
return (havePage && haveView);
}
//===========================================================================
// TechDraw_ExtensionThreadHoleBottom
//===========================================================================
DEF_STD_CMD_A(CmdTechDrawExtensionThreadHoleBottom)
CmdTechDrawExtensionThreadHoleBottom::CmdTechDrawExtensionThreadHoleBottom()
: Command("TechDraw_ExtensionThreadHoleBottom")
{
sAppModule = "TechDraw";
sGroup = QT_TR_NOOP("TechDraw");
sMenuText = QT_TR_NOOP("Cosmetic thread hole bottom view");
sToolTipText = QT_TR_NOOP("Draw cosmetic hole thread ground view\n\
- select many circles\n\
- click this button");
sWhatsThis = "TechDraw_ExtensionThreadHoleBottom";
sStatusTip = sToolTipText;
sPixmap = "TechDraw_ExtensionThreadHoleBottom";
}
void CmdTechDrawExtensionThreadHoleBottom::activated(int iMsg)
{
Q_UNUSED(iMsg);
auto selection = getSelection().getSelectionEx();
if( selection.empty() ) {
QMessageBox::warning(Gui::getMainWindow(),
QObject::tr("TechDraw Thread Hole Bottom"),
QObject::tr("Selection is empty"));
return;
}
auto objFeat = dynamic_cast<TechDraw::DrawViewPart *>(selection[0].getObject());
if( objFeat == nullptr ) {
QMessageBox::warning(Gui::getMainWindow(),
QObject::tr("TechDraw Thread Hole Bottom"),
QObject::tr("No object selected"));
return;
}
const std::vector<std::string> SubNames = selection[0].getSubNames();
for (std::string Name : SubNames) {
_createThreadCircle(Name, objFeat, 1.177);
}
getSelection().clearSelection();
objFeat->refreshCEGeoms();
objFeat->requestPaint();
}
bool CmdTechDrawExtensionThreadHoleBottom::isActive(void)
{
bool havePage = DrawGuiUtil::needPage(this);
bool haveView = DrawGuiUtil::needView(this);
return (havePage && haveView);
}
//===========================================================================
// TechDraw_ExtensionThreadBoltBottom
//===========================================================================
DEF_STD_CMD_A(CmdTechDrawExtensionThreadBoltBottom)
CmdTechDrawExtensionThreadBoltBottom::CmdTechDrawExtensionThreadBoltBottom()
: Command("TechDraw_ExtensionThreadBoltBottom")
{
sAppModule = "TechDraw";
sGroup = QT_TR_NOOP("TechDraw");
sMenuText = QT_TR_NOOP("Cosmetic thread bolt bottom view");
sToolTipText = QT_TR_NOOP("Draw cosmetic screw thread ground view\n\
- select many circles\n\
- click this button");
sWhatsThis = "TechDraw_ExtensionThreadBoltBottom";
sStatusTip = sToolTipText;
sPixmap = "TechDraw_ExtensionThreadBoltBottom";
}
void CmdTechDrawExtensionThreadBoltBottom::activated(int iMsg)
{
Q_UNUSED(iMsg);
auto selection = getSelection().getSelectionEx();
if( selection.empty() ) {
QMessageBox::warning(Gui::getMainWindow(),
QObject::tr("TechDraw Tread Bolt Bottom"),
QObject::tr("Selection is empty"));
return;
}
auto objFeat = dynamic_cast<TechDraw::DrawViewPart *>(selection[0].getObject());
if( objFeat == nullptr ) {
QMessageBox::warning(Gui::getMainWindow(),
QObject::tr("TechDraw Tread Bolt Bottom"),
QObject::tr("No object selected"));
return;
}
const std::vector<std::string> SubNames = selection[0].getSubNames();
for (std::string Name : SubNames) {
_createThreadCircle(Name, objFeat, 0.85);
}
getSelection().clearSelection();
objFeat->refreshCEGeoms();
objFeat->requestPaint();
}
bool CmdTechDrawExtensionThreadBoltBottom::isActive(void)
{
bool havePage = DrawGuiUtil::needPage(this);
bool haveView = DrawGuiUtil::needView(this);
return (havePage && haveView);
}
//===========================================================================
// internal helper routines
//===========================================================================
bool _circulation(Base::Vector3d A, Base::Vector3d B, Base::Vector3d C){
// test the circulation of the triangle A-B-C
if (A.x*B.y+A.y*C.x+B.x*C.y-C.x*B.y-C.y*A.x-B.x*A.y > 0.0)
return true;
else
return false;
}
void _createThreadCircle(std::string Name, TechDraw::DrawViewPart* objFeat, float factor){
// create the 3/4 arc symbolizing a thread from top seen
double scale = objFeat->getScale();
int GeoId = TechDraw::DrawUtil::getIndexFromName(Name);
TechDraw::BaseGeom* geom = objFeat->getGeomByIndex(GeoId);
std::string GeoType = TechDraw::DrawUtil::getGeomTypeFromName(Name);
if (GeoType == "Edge"){
if (geom->geomType == TechDraw::CIRCLE){
TechDraw::Circle* cgen = static_cast<TechDraw::Circle *>(geom);
Base::Vector3d center = cgen->center;
float radius = cgen->radius;
TechDraw::BaseGeom* threadArc = new TechDraw::AOC(center/scale, radius*factor/scale, 255.0, 165.0);
std::string arcTag = objFeat->addCosmeticEdge(threadArc);
TechDraw::CosmeticEdge* arc = objFeat->getCosmeticEdge(arcTag);
_setStyleAndWeight(arc,1,0.35);
}
}
}
void _createThreadLines(std::vector<std::string> SubNames, TechDraw::DrawViewPart* objFeat, float factor){
// create symbolizing lines of a thread from the side seen
double scale = objFeat->getScale();
std::string GeoType0 = TechDraw::DrawUtil::getGeomTypeFromName(SubNames[0]);
std::string GeoType1 = TechDraw::DrawUtil::getGeomTypeFromName(SubNames[1]);
if ((GeoType0 == "Edge") && (GeoType1 == "Edge")) {
int GeoId0 = TechDraw::DrawUtil::getIndexFromName(SubNames[0]);
int GeoId1 = TechDraw::DrawUtil::getIndexFromName(SubNames[1]);
TechDraw::BaseGeom* geom0 = objFeat->getGeomByIndex(GeoId0);
TechDraw::BaseGeom* geom1 = objFeat->getGeomByIndex(GeoId1);
if ((geom0->geomType == TechDraw::GENERIC) && (geom1->geomType == TechDraw::GENERIC)) {
TechDraw::Generic* line0 = static_cast<TechDraw::Generic *>(geom0);
TechDraw::Generic* line1 = static_cast<TechDraw::Generic *>(geom1);
Base::Vector3d start0 = line0->points.at(0);
Base::Vector3d end0 = line0->points.at(1);
Base::Vector3d start1 = line1->points.at(0);
Base::Vector3d end1 = line1->points.at(1);
if (_circulation(start0,end0,start1) != _circulation(end0,end1,start1)) {
Base::Vector3d help1 = start1;
Base::Vector3d help2 = end1;
start1 = help2;
end1 = help1;
}
start0.y = -start0.y;
end0.y = -end0.y;
start1.y = -start1.y;
end1.y = -end1.y;
float kernelDiam = (start1-start0).Length();
float kernelFactor = (kernelDiam*factor-kernelDiam)/2;
Base::Vector3d delta = (start1-start0).Normalize()*kernelFactor;
std::string line0Tag = objFeat->addCosmeticEdge((start0-delta)/scale, (end0-delta)/scale);
std::string line1Tag = objFeat->addCosmeticEdge((start1+delta)/scale, (end1+delta)/scale);
TechDraw::CosmeticEdge* cosTag0 = objFeat->getCosmeticEdge(line0Tag);
TechDraw::CosmeticEdge* cosTag1 = objFeat->getCosmeticEdge(line1Tag);
_setStyleAndWeight(cosTag0,1,0.35);
_setStyleAndWeight(cosTag1,1,0.35);
} else {
QMessageBox::warning(Gui::getMainWindow(),
QObject::tr("TechDraw Thread Hole Side"),
QObject::tr("Please select two straight lines"));
return;
}
}
}
void _setStyleAndWeight(TechDraw::CosmeticEdge* cosEdge, int style, float weight) {
// set style and weight of a cosmetic edge
cosEdge->m_format.m_style = style;
cosEdge->m_format.m_weight = weight;
}
//------------------------------------------------------------------------------
void CreateTechDrawCommandsExtensions(void)
{
Gui::CommandManager &rcCmdMgr = Gui::Application::Instance->commandManager();
rcCmdMgr.addCommand(new CmdTechDrawExtensionCircleCenterLines());
rcCmdMgr.addCommand(new CmdTechDrawExtensionThreadHoleSide());
rcCmdMgr.addCommand(new CmdTechDrawExtensionThreadBoltSide());
rcCmdMgr.addCommand(new CmdTechDrawExtensionThreadHoleBottom());
rcCmdMgr.addCommand(new CmdTechDrawExtensionThreadBoltBottom());
}