FreeCAD

Форк
0
/
CommandExtensionPack.cpp 
2224 строки · 88.8 Кб
1
/***************************************************************************
2
 *   Copyright (c) 2021 edi                                                *
3
 *                                                                         *
4
 *   This file is part of the FreeCAD CAx development system.              *
5
 *                                                                         *
6
 *   This library is free software; you can redistribute it and/or         *
7
 *   modify it under the terms of the GNU Library General Public           *
8
 *   License as published by the Free Software Foundation; either          *
9
 *   version 2 of the License, or (at your option) any later version.      *
10
 *                                                                         *
11
 *   This library  is distributed in the hope that it will be useful,      *
12
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
13
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
14
 *   GNU Library General Public License for more details.                  *
15
 *                                                                         *
16
 *   You should have received a copy of the GNU Library General Public     *
17
 *   License along with this library; see the file COPYING.LIB. If not,    *
18
 *   write to the Free Software Foundation, Inc., 59 Temple Place,         *
19
 *   Suite 330, Boston, MA  02111-1307, USA                                *
20
 *                                                                         *
21
 ***************************************************************************/
22

23
#include "PreCompiled.h"
24
#ifndef _PreComp_
25
#include <QApplication>
26
#include <QMessageBox>
27
#include <sstream>
28
#include <BRepGProp.hxx>
29
#include <GProp_GProps.hxx>
30
#include <BRepAdaptor_Curve.hxx>
31
#include <GCPnts_AbscissaPoint.hxx>
32
#endif
33

34
#include <App/Document.h>
35
#include <App/DocumentObject.h>
36
#include <Base/Console.h>
37
#include <Base/Tools.h>
38
#include <Base/Type.h>
39
#include <Gui/Action.h>
40
#include <Gui/Application.h>
41
#include <Gui/BitmapFactory.h>
42
#include <Gui/Command.h>
43
#include <Gui/Control.h>
44
#include <Gui/Document.h>
45
#include <Gui/MainWindow.h>
46
#include <Gui/Selection.h>
47
#include <Gui/SelectionObject.h>
48
#include <Gui/ViewProvider.h>
49
#include <Mod/Part/App/Geometry2d.h>
50
#include <Mod/TechDraw/App/CenterLine.h>
51
#include <Mod/TechDraw/App/Cosmetic.h>
52
#include <Mod/TechDraw/App/DrawPage.h>
53
#include <Mod/TechDraw/App/DrawProjGroup.h>
54
#include <Mod/TechDraw/App/DrawProjGroupItem.h>
55
#include <Mod/TechDraw/App/DrawUtil.h>
56
#include <Mod/TechDraw/App/DrawViewBalloon.h>
57
#include <Mod/TechDraw/App/DrawViewDimension.h>
58
#include <Mod/TechDraw/App/DrawViewPart.h>
59
#include <Mod/TechDraw/App/DrawViewSection.h>
60
#include <Mod/TechDraw/App/Preferences.h>
61

62
#include "DrawGuiUtil.h"
63
#include "QGSPage.h"
64
#include "TaskSelectLineAttributes.h"
65
#include "ViewProviderBalloon.h"
66
#include "ViewProviderDimension.h"
67
#include "ViewProviderPage.h"
68

69

70
using namespace TechDrawGui;
71
using namespace TechDraw;
72
using DU = DrawUtil;
73

74

75
namespace TechDrawGui
76
{
77
//TechDraw::LineFormat activeAttributes; // container holding global line attributes
78

79
//internal helper functions
80
TechDraw::LineFormat& _getActiveLineAttributes();
81
Base::Vector3d _circleCenter(Base::Vector3d p1, Base::Vector3d p2, Base::Vector3d p3);
82
void _createThreadCircle(std::string Name, TechDraw::DrawViewPart* objFeat, float factor);
83
void _createThreadLines(std::vector<std::string> SubNames, TechDraw::DrawViewPart* objFeat,
84
                        float factor);
85
void _setLineAttributes(TechDraw::CosmeticEdge* cosEdge);
86
void _setLineAttributes(TechDraw::CenterLine* cosEdge);
87
void _setLineAttributes(TechDraw::CosmeticEdge* cosEdge, int style, float weight, App::Color color);
88
void _setLineAttributes(TechDraw::CenterLine* cosEdge, int style, float weight, App::Color color);
89
float _getAngle(Base::Vector3d center, Base::Vector3d point);
90
std::vector<Base::Vector3d> _getVertexPoints(std::vector<std::string> SubNames,
91
                                             TechDraw::DrawViewPart* objFeat);
92
bool _checkSel(Gui::Command* cmd, std::vector<Gui::SelectionObject>& selection,
93
               TechDraw::DrawViewPart*& objFeat, std::string message);
94
std::string _createBalloon(Gui::Command* cmd, TechDraw::DrawViewPart* objFeat);
95

96
//===========================================================================
97
// TechDraw_ExtensionHoleCircle
98
//===========================================================================
99

100
void execHoleCircle(Gui::Command* cmd)
101
{
102
    //create centerlines of a hole/bolt circle
103
    std::vector<Gui::SelectionObject> selection;
104
    TechDraw::DrawViewPart* objFeat;
105
    if (!_checkSel(cmd, selection, objFeat, QT_TRANSLATE_NOOP("Command","TechDraw Hole Circle")))
106
        return;
107
    const std::vector<std::string> SubNames = selection[0].getSubNames();
108
    std::vector<TechDraw::CirclePtr> Circles;
109
    for (const std::string& Name : SubNames) {
110
        int GeoId = TechDraw::DrawUtil::getIndexFromName(Name);
111
        std::string GeoType = TechDraw::DrawUtil::getGeomTypeFromName(Name);
112
        TechDraw::BaseGeomPtr geom = objFeat->getGeomByIndex(GeoId);
113
        if (GeoType == "Edge") {
114
            if (geom->getGeomType() == TechDraw::CIRCLE || geom->getGeomType() == TechDraw::ARCOFCIRCLE) {
115
                TechDraw::CirclePtr cgen = std::static_pointer_cast<TechDraw::Circle>(geom);
116
                Circles.push_back(cgen);
117
            }
118
        }
119
    }
120
    if (Circles.size() <= 2) {
121
        QMessageBox::warning(Gui::getMainWindow(), QObject::tr("TechDraw Hole Circle"),
122
                             QObject::tr("Fewer than three circles selected"));
123
        return;
124
    }
125
    Gui::Command::openCommand(QT_TRANSLATE_NOOP("Command", "Bolt Circle Centerlines"));
126

127
    // make the bolt hole circle from 3 scaled and rotated points
128
    Base::Vector3d bigCenter =
129
        _circleCenter(Circles[0]->center, Circles[1]->center, Circles[2]->center);
130
    double bigRadius = (Circles[0]->center - bigCenter).Length();
131
    // now convert the center & radius to canonical form
132
    bigCenter = DU::invertY(bigCenter);
133
    bigCenter = CosmeticVertex::makeCanonicalPoint(objFeat, bigCenter);
134
    bigCenter = DU::invertY(bigCenter);
135
    bigRadius = bigRadius / objFeat->getScale();
136
    TechDraw::BaseGeomPtr bigCircle =
137
        std::make_shared<TechDraw::Circle>(bigCenter, bigRadius);
138
    std::string bigCircleTag = objFeat->addCosmeticEdge(bigCircle);
139
    TechDraw::CosmeticEdge* ceCircle = objFeat->getCosmeticEdge(bigCircleTag);
140
    _setLineAttributes(ceCircle);
141

142
    // make the center lines for the individual bolt holes
143
    constexpr double ExtendFactor{1.1};
144
    for (const TechDraw::CirclePtr& oneCircle : Circles) {
145
        // convert the center to canonical form
146
        Base::Vector3d oneCircleCenter = DU::invertY(oneCircle->center);
147
        oneCircleCenter = CosmeticVertex::makeCanonicalPoint(objFeat, oneCircleCenter);
148
        oneCircleCenter = DU::invertY(oneCircleCenter);
149
        // oneCircle->radius is scaled.
150
        float oneRadius = oneCircle->radius / objFeat->getScale();
151
        // what is magic number 2 (now ExtendFactor)?  just a fudge factor to extend the line beyond the bolt
152
        // hole circle?  should it be a function of hole diameter? maybe 110% of oneRadius?
153
        Base::Vector3d delta = (oneCircleCenter - bigCenter).Normalize() * (oneRadius * ExtendFactor);
154
        Base::Vector3d startPt = oneCircleCenter + delta;
155
        Base::Vector3d endPt = oneCircleCenter - delta;
156
        startPt = DU::invertY(startPt);
157
        endPt = DU::invertY(endPt);
158
        std::string oneLineTag = objFeat->addCosmeticEdge(startPt, endPt);
159
        TechDraw::CosmeticEdge* ceLine = objFeat->getCosmeticEdge(oneLineTag);
160
        _setLineAttributes(ceLine);
161
    }
162
    cmd->getSelection().clearSelection();
163
    objFeat->refreshCEGeoms();
164
    objFeat->requestPaint();
165
    Gui::Command::commitCommand();
166
}
167
}// namespace TechDrawGui
168

169
DEF_STD_CMD_A(CmdTechDrawExtensionHoleCircle)
170

171
CmdTechDrawExtensionHoleCircle::CmdTechDrawExtensionHoleCircle()
172
    : Command("TechDraw_ExtensionHoleCircle")
173
{
174
    sAppModule = "TechDraw";
175
    sGroup = QT_TR_NOOP("TechDraw");
176
    sMenuText = QT_TR_NOOP("Add Bolt Circle Centerlines");
177
    sToolTipText = QT_TR_NOOP("Add centerlines to a circular pattern of circles:<br>\
178
- Specify the line attributes (optional)<br>\
179
- Select three or more circles forming a circular pattern<br>\
180
- Click this tool");
181
    sWhatsThis = "TechDraw_ExtensionHoleCircle";
182
    sStatusTip = sMenuText;
183
    sPixmap = "TechDraw_ExtensionHoleCircle";
184
}
185

186
void CmdTechDrawExtensionHoleCircle::activated(int iMsg)
187
{
188
    Q_UNUSED(iMsg);
189
    execHoleCircle(this);
190
    //Base::Console().Message("HoleCircle started\n");
191
}
192

193
bool CmdTechDrawExtensionHoleCircle::isActive()
194
{
195
    bool havePage = DrawGuiUtil::needPage(this);
196
    bool haveView = DrawGuiUtil::needView(this);
197
    return (havePage && haveView);
198
}
199

200
//===========================================================================
201
// TechDraw_ExtensionCircleCenterLines
202
//===========================================================================
203

204
void execCircleCenterLines(Gui::Command* cmd)
205
{
206
    // create circle centerlines
207
    std::vector<Gui::SelectionObject> selection;
208
    TechDraw::DrawViewPart* objFeat;
209
    if (!_checkSel(cmd, selection, objFeat, QT_TRANSLATE_NOOP("Command","TechDraw Circle Centerlines")))
210
        return;
211
    Gui::Command::openCommand(QT_TRANSLATE_NOOP("Command", "Circle Centerlines"));
212
    const std::vector<std::string> SubNames = selection[0].getSubNames();
213
    for (const std::string& Name : SubNames) {
214
        int GeoId = TechDraw::DrawUtil::getIndexFromName(Name);
215
        TechDraw::BaseGeomPtr geom = objFeat->getGeomByIndex(GeoId);
216
        std::string GeoType = TechDraw::DrawUtil::getGeomTypeFromName(Name);
217
        if (GeoType == "Edge") {
218
            if (geom->getGeomType() == TechDraw::CIRCLE || geom->getGeomType() == TechDraw::ARCOFCIRCLE) {
219
                TechDraw::CirclePtr cgen = std::static_pointer_cast<TechDraw::Circle>(geom);
220
                // center is a scaled and rotated point
221
                Base::Vector3d center = cgen->center;
222
                center.y = -center.y;
223
                center = CosmeticVertex::makeCanonicalPoint(objFeat, center);
224
                double radius = cgen->radius / objFeat->getScale();
225
                // right, left, top, bottom are formed from a canonical point (center)
226
                // so they do not need to be changed to canonical form.
227
                Base::Vector3d right(center.x + radius + 2.0, center.y, 0.0);
228
                Base::Vector3d top(center.x, center.y + radius + 2.0, 0.0);
229
                Base::Vector3d left(center.x - radius - 2.0, center.y, 0.0);
230
                Base::Vector3d bottom(center.x, center.y - radius - 2.0, 0.0);
231
                std::string line1tag = objFeat->addCosmeticEdge(right, left);
232
                std::string line2tag = objFeat->addCosmeticEdge(top, bottom);
233
                TechDraw::CosmeticEdge* horiz = objFeat->getCosmeticEdge(line1tag);
234
                _setLineAttributes(horiz);
235
                TechDraw::CosmeticEdge* vert = objFeat->getCosmeticEdge(line2tag);
236
                _setLineAttributes(vert);
237
            }
238
        }
239
    }
240
    cmd->getSelection().clearSelection();
241
    objFeat->refreshCEGeoms();
242
    objFeat->requestPaint();
243
    Gui::Command::commitCommand();
244
}
245

246
DEF_STD_CMD_A(CmdTechDrawExtensionCircleCenterLines)
247

248
CmdTechDrawExtensionCircleCenterLines::CmdTechDrawExtensionCircleCenterLines()
249
    : Command("TechDraw_ExtensionCircleCenterLines")
250
{
251
    sAppModule = "TechDraw";
252
    sGroup = QT_TR_NOOP("TechDraw");
253
    sMenuText = QT_TR_NOOP("Add Circle Centerlines");
254
    sToolTipText = QT_TR_NOOP("Add centerlines to circles and arcs:<br>\
255
- Specify the line attributes (optional)<br>\
256
- Select one or more circles or arcs<br>\
257
- Click this tool");
258
    sWhatsThis = "TechDraw_ExtensionCircleCenterLines";
259
    sStatusTip = sMenuText;
260
    sPixmap = "TechDraw_ExtensionCircleCenterLines";
261
}
262

263
void CmdTechDrawExtensionCircleCenterLines::activated(int iMsg)
264
{
265
    Q_UNUSED(iMsg);
266
    execCircleCenterLines(this);
267
}
268

269
bool CmdTechDrawExtensionCircleCenterLines::isActive()
270
{
271
    bool havePage = DrawGuiUtil::needPage(this);
272
    bool haveView = DrawGuiUtil::needView(this);
273
    return (havePage && haveView);
274
}
275

276
//===========================================================================
277
// TechDraw_ExtensionCircleCenterLinesGroup
278
//===========================================================================
279

280
DEF_STD_CMD_ACL(CmdTechDrawExtensionCircleCenterLinesGroup)
281

282
CmdTechDrawExtensionCircleCenterLinesGroup::CmdTechDrawExtensionCircleCenterLinesGroup()
283
    : Command("TechDraw_ExtensionCircleCenterLinesGroup")
284
{
285
    sAppModule = "TechDraw";
286
    sGroup = QT_TR_NOOP("TechDraw");
287
    sMenuText = QT_TR_NOOP("Add Circle Centerlines");
288
    sToolTipText = QT_TR_NOOP("Add centerlines to circles and arcs:<br>\
289
- Specify the line attributes (optional)<br>\
290
- Select one or more circles or arcs<br>\
291
- Click this tool");
292
    sWhatsThis = "TechDraw_ExtensionCircleCenterLinesGroup";
293
    sStatusTip = sMenuText;
294
}
295

296
void CmdTechDrawExtensionCircleCenterLinesGroup::activated(int iMsg)
297
{
298
    Gui::TaskView::TaskDialog* dlg = Gui::Control().activeDialog();
299
    if (dlg) {
300
        QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Task In Progress"),
301
                             QObject::tr("Close active task dialog and try again."));
302
        return;
303
    }
304

305
    Gui::ActionGroup* pcAction = qobject_cast<Gui::ActionGroup*>(_pcAction);
306
    pcAction->setIcon(pcAction->actions().at(iMsg)->icon());
307
    switch (iMsg) {
308
        case 0://circle centerlines
309
            execCircleCenterLines(this);
310
            break;
311
        case 1://bolt circle centerlines
312
            execHoleCircle(this);
313
            break;
314
        default:
315
            Base::Console().Message("CMD::CVGrp - invalid iMsg: %d\n", iMsg);
316
    };
317
}
318

319
Gui::Action* CmdTechDrawExtensionCircleCenterLinesGroup::createAction()
320
{
321
    Gui::ActionGroup* pcAction = new Gui::ActionGroup(this, Gui::getMainWindow());
322
    pcAction->setDropDownMenu(true);
323
    applyCommandData(this->className(), pcAction);
324

325
    QAction* p1 = pcAction->addAction(QString());
326
    p1->setIcon(Gui::BitmapFactory().iconFromTheme("TechDraw_ExtensionCircleCenterLines"));
327
    p1->setObjectName(QString::fromLatin1("TechDraw_ExtensionCircleCenterLines"));
328
    p1->setWhatsThis(QString::fromLatin1("TechDraw_ExtensionCircleCenterLines"));
329
    QAction* p2 = pcAction->addAction(QString());
330
    p2->setIcon(Gui::BitmapFactory().iconFromTheme("TechDraw_ExtensionHoleCircle"));
331
    p2->setObjectName(QString::fromLatin1("TechDraw_ExtensionHoleCircle"));
332
    p2->setWhatsThis(QString::fromLatin1("TechDraw_ExtensionHoleCircle"));
333

334
    _pcAction = pcAction;
335
    languageChange();
336

337
    pcAction->setIcon(p1->icon());
338
    int defaultId = 0;
339
    pcAction->setProperty("defaultAction", QVariant(defaultId));
340

341
    return pcAction;
342
}
343

344
void CmdTechDrawExtensionCircleCenterLinesGroup::languageChange()
345
{
346
    Command::languageChange();
347

348
    if (!_pcAction)
349
        return;
350
    Gui::ActionGroup* pcAction = qobject_cast<Gui::ActionGroup*>(_pcAction);
351
    QList<QAction*> a = pcAction->actions();
352

353
    QAction* arc1 = a[0];
354
    arc1->setText(
355
        QApplication::translate("CmdTechDrawExtensionCircleCenterLines", "Add Circle Centerlines"));
356
    arc1->setToolTip(QApplication::translate("CmdTechDrawExtensionCircleCenterLines",
357
                                             "Add centerlines to circles and arcs:<br>\
358
- Specify the line attributes (optional)<br>\
359
- Select one or more circles or arcs<br>\
360
- Click this tool"));
361
    arc1->setStatusTip(arc1->text());
362
    QAction* arc2 = a[1];
363
    arc2->setText(
364
        QApplication::translate("CmdTechDrawExtensionHoleCircle", "Add Bolt Circle Centerlines"));
365
    arc2->setToolTip(QApplication::translate("CmdTechDrawExtensionHoleCircle",
366
                                             "Add centerlines to a circular pattern of circles:<br>\
367
- Specify the line attributes (optional)<br>\
368
- Select three or more circles forming a circular pattern<br>\
369
- Click this tool"));
370
    arc2->setStatusTip(arc2->text());
371
}
372

373
bool CmdTechDrawExtensionCircleCenterLinesGroup::isActive()
374
{
375
    bool havePage = DrawGuiUtil::needPage(this);
376
    bool haveView = DrawGuiUtil::needView(this, true);
377
    return (havePage && haveView);
378
}
379

380
//===========================================================================
381
// TechDraw_ExtensionThreadHoleSide
382
//===========================================================================
383

384
void execThreadHoleSide(Gui::Command* cmd)
385
{
386
    // add cosmetic thread to side view of hole
387
    std::vector<Gui::SelectionObject> selection;
388
    TechDraw::DrawViewPart* objFeat;
389
    if (!_checkSel(cmd, selection, objFeat, QT_TRANSLATE_NOOP("Command","TechDraw Thread Hole Side")))
390
        return;
391
    Gui::Command::openCommand(QT_TRANSLATE_NOOP("Command", "Cosmetic Thread Hole Side"));
392
    const std::vector<std::string> SubNames = selection[0].getSubNames();
393
    if (SubNames.size() >= 2) {
394
        _createThreadLines(SubNames, objFeat, 1.176f);
395
    }
396
    cmd->getSelection().clearSelection();
397
    objFeat->refreshCEGeoms();
398
    objFeat->requestPaint();
399
    Gui::Command::commitCommand();
400
}
401

402
DEF_STD_CMD_A(CmdTechDrawExtensionThreadHoleSide)
403

404
CmdTechDrawExtensionThreadHoleSide::CmdTechDrawExtensionThreadHoleSide()
405
    : Command("TechDraw_ExtensionThreadHoleSide")
406
{
407
    sAppModule = "TechDraw";
408
    sGroup = QT_TR_NOOP("TechDraw");
409
    sMenuText = QT_TR_NOOP("Add Cosmetic Thread Hole Side View");
410
    sToolTipText = QT_TR_NOOP("Add a cosmetic thread to the side view of a hole:<br>\
411
- Specify the line attributes (optional)<br>\
412
- Select two parallel lines<br>\
413
- Click this tool");
414
    sWhatsThis = "TechDraw_ExtensionThreadHoleSide";
415
    sStatusTip = sMenuText;
416
    sPixmap = "TechDraw_ExtensionThreadHoleSide";
417
}
418

419
void CmdTechDrawExtensionThreadHoleSide::activated(int iMsg)
420
{
421
    Q_UNUSED(iMsg);
422
    execThreadHoleSide(this);
423
}
424

425
bool CmdTechDrawExtensionThreadHoleSide::isActive()
426
{
427
    bool havePage = DrawGuiUtil::needPage(this);
428
    bool haveView = DrawGuiUtil::needView(this);
429
    return (havePage && haveView);
430
}
431

432
//===========================================================================
433
// TechDraw_ExtensionThreadBoltSide
434
//===========================================================================
435

436
void execThreadBoltSide(Gui::Command* cmd)
437
{
438
    // add cosmetic thread to side view of bolt
439
    std::vector<Gui::SelectionObject> selection;
440
    TechDraw::DrawViewPart* objFeat;
441
    if (!_checkSel(cmd, selection, objFeat, QT_TRANSLATE_NOOP("Command","TechDraw Thread Bolt Side")))
442
        return;
443
    Gui::Command::openCommand(QT_TRANSLATE_NOOP("Command", "Cosmetic Thread Bolt Side"));
444
    const std::vector<std::string> SubNames = selection[0].getSubNames();
445
    if (SubNames.size() >= 2) {
446
        _createThreadLines(SubNames, objFeat, 0.85f);
447
    }
448
    cmd->getSelection().clearSelection();
449
    objFeat->refreshCEGeoms();
450
    objFeat->requestPaint();
451
    Gui::Command::commitCommand();
452
}
453

454
DEF_STD_CMD_A(CmdTechDrawExtensionThreadBoltSide)
455

456
CmdTechDrawExtensionThreadBoltSide::CmdTechDrawExtensionThreadBoltSide()
457
    : Command("TechDraw_ExtensionThreadBoltSide")
458
{
459
    sAppModule = "TechDraw";
460
    sGroup = QT_TR_NOOP("TechDraw");
461
    sMenuText = QT_TR_NOOP("Add Cosmetic Thread Bolt Side View");
462
    sToolTipText = QT_TR_NOOP("Add a cosmetic thread to the side view of a bolt/screw/rod:<br>\
463
- Specify the line attributes (optional)<br>\
464
- Select two parallel lines<br>\
465
- Click this tool");
466
    sWhatsThis = "TechDraw_ExtensionThreadBoltSide";
467
    sStatusTip = sMenuText;
468
    sPixmap = "TechDraw_ExtensionThreadBoltSide";
469
}
470

471
void CmdTechDrawExtensionThreadBoltSide::activated(int iMsg)
472
{
473
    Q_UNUSED(iMsg);
474
    execThreadBoltSide(this);
475
}
476

477
bool CmdTechDrawExtensionThreadBoltSide::isActive()
478
{
479
    bool havePage = DrawGuiUtil::needPage(this);
480
    bool haveView = DrawGuiUtil::needView(this);
481
    return (havePage && haveView);
482
}
483

484
//===========================================================================
485
// TechDraw_ExtensionThreadHoleBottom
486
//===========================================================================
487

488
void execThreadHoleBottom(Gui::Command* cmd)
489
{
490
    // add cosmetic thread to bottom view of hole
491
    std::vector<Gui::SelectionObject> selection;
492
    TechDraw::DrawViewPart* objFeat;
493
    if (!_checkSel(cmd, selection, objFeat, QT_TRANSLATE_NOOP("Command","TechDraw Thread Hole Bottom")))
494
        return;
495
    Gui::Command::openCommand(QT_TRANSLATE_NOOP("Command", "Cosmetic Thread Hole Bottom"));
496
    const std::vector<std::string> SubNames = selection[0].getSubNames();
497
    for (const std::string& Name : SubNames) {
498
        _createThreadCircle(Name, objFeat, 1.177f);
499
    }
500
    cmd->getSelection().clearSelection();
501
    objFeat->refreshCEGeoms();
502
    objFeat->requestPaint();
503
    Gui::Command::commitCommand();
504
}
505

506
DEF_STD_CMD_A(CmdTechDrawExtensionThreadHoleBottom)
507

508
CmdTechDrawExtensionThreadHoleBottom::CmdTechDrawExtensionThreadHoleBottom()
509
    : Command("TechDraw_ExtensionThreadHoleBottom")
510
{
511
    sAppModule = "TechDraw";
512
    sGroup = QT_TR_NOOP("TechDraw");
513
    sMenuText = QT_TR_NOOP("Add Cosmetic Thread Hole Bottom View");
514
    sToolTipText = QT_TR_NOOP("Add a cosmetic thread to the top or bottom view of holes:<br>\
515
- Specify the line attributes (optional)<br>\
516
- Select one or more circles<br>\
517
- Click this tool");
518
    sWhatsThis = "TechDraw_ExtensionThreadHoleBottom";
519
    sStatusTip = sMenuText;
520
    sPixmap = "TechDraw_ExtensionThreadHoleBottom";
521
}
522

523
void CmdTechDrawExtensionThreadHoleBottom::activated(int iMsg)
524
{
525
    Q_UNUSED(iMsg);
526
    execThreadHoleBottom(this);
527
}
528

529
bool CmdTechDrawExtensionThreadHoleBottom::isActive()
530
{
531
    bool havePage = DrawGuiUtil::needPage(this);
532
    bool haveView = DrawGuiUtil::needView(this);
533
    return (havePage && haveView);
534
}
535

536
//===========================================================================
537
// TechDraw_ExtensionThreadBoltBottom
538
//===========================================================================
539

540
void execThreadBoltBottom(Gui::Command* cmd)
541
{
542
    // add cosmetic thread to bottom view of bolt
543
    std::vector<Gui::SelectionObject> selection;
544
    TechDraw::DrawViewPart* objFeat;
545
    if (!_checkSel(cmd, selection, objFeat, QT_TRANSLATE_NOOP("Command","TechDraw Thread Bolt Bottom")))
546
        return;
547
    Gui::Command::openCommand(QT_TRANSLATE_NOOP("Command", "Cosmetic Thread Bolt Bottom"));
548
    const std::vector<std::string> SubNames = selection[0].getSubNames();
549
    for (const std::string& Name : SubNames) {
550
        _createThreadCircle(Name, objFeat, 0.85f);
551
    }
552
    cmd->getSelection().clearSelection();
553
    objFeat->refreshCEGeoms();
554
    objFeat->requestPaint();
555
    Gui::Command::commitCommand();
556
}
557

558
DEF_STD_CMD_A(CmdTechDrawExtensionThreadBoltBottom)
559

560
CmdTechDrawExtensionThreadBoltBottom::CmdTechDrawExtensionThreadBoltBottom()
561
    : Command("TechDraw_ExtensionThreadBoltBottom")
562
{
563
    sAppModule = "TechDraw";
564
    sGroup = QT_TR_NOOP("TechDraw");
565
    sMenuText = QT_TR_NOOP("Add Cosmetic Thread Bolt Bottom View");
566
    sToolTipText =
567
        QT_TR_NOOP("Add a cosmetic thread to the top or bottom view of bolts/screws/rods:<br>\
568
- Specify the line attributes (optional)<br>\
569
- Select one or more circles<br>\
570
- Click this tool");
571
    sWhatsThis = "TechDraw_ExtensionThreadBoltBottom";
572
    sStatusTip = sMenuText;
573
    sPixmap = "TechDraw_ExtensionThreadBoltBottom";
574
}
575

576
void CmdTechDrawExtensionThreadBoltBottom::activated(int iMsg)
577
{
578
    Q_UNUSED(iMsg);
579
    execThreadBoltBottom(this);
580
}
581

582
bool CmdTechDrawExtensionThreadBoltBottom::isActive()
583
{
584
    bool havePage = DrawGuiUtil::needPage(this);
585
    bool haveView = DrawGuiUtil::needView(this);
586
    return (havePage && haveView);
587
}
588

589
//===========================================================================
590
// TechDraw_ExtensionThreadsGroup
591
//===========================================================================
592

593
DEF_STD_CMD_ACL(CmdTechDrawExtensionThreadsGroup)
594

595
CmdTechDrawExtensionThreadsGroup::CmdTechDrawExtensionThreadsGroup()
596
    : Command("TechDraw_ExtensionThreadsGroup")
597
{
598
    sAppModule = "TechDraw";
599
    sGroup = QT_TR_NOOP("TechDraw");
600
    sMenuText = QT_TR_NOOP("Add Cosmetic Thread Hole Side View");
601
    sToolTipText = QT_TR_NOOP("Add a cosmetic thread to the side view of a hole:<br>\
602
- Specify the line attributes (optional)<br>\
603
- Select two parallel lines<br>\
604
- Click this tool");
605
    sWhatsThis = "TechDraw_ExtensionThreadsGroup";
606
    sStatusTip = sMenuText;
607
}
608

609
void CmdTechDrawExtensionThreadsGroup::activated(int iMsg)
610
{
611
    //    Base::Console().Message("CMD::TechDrawExtensionThreadsGroup - activated(%d)\n", iMsg);
612
    Gui::TaskView::TaskDialog* dlg = Gui::Control().activeDialog();
613
    if (dlg) {
614
        QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Task In Progress"),
615
                             QObject::tr("Close active task dialog and try again."));
616
        return;
617
    }
618

619
    Gui::ActionGroup* pcAction = qobject_cast<Gui::ActionGroup*>(_pcAction);
620
    pcAction->setIcon(pcAction->actions().at(iMsg)->icon());
621
    switch (iMsg) {
622
        case 0://thread hole side view
623
            execThreadHoleSide(this);
624
            break;
625
        case 1://thread hole bottom view
626
            execThreadHoleBottom(this);
627
            break;
628
        case 2://thread bolt side view
629
            execThreadBoltSide(this);
630
            break;
631
        case 3://thread bolt bottom view
632
            execThreadBoltBottom(this);
633
            break;
634
        default:
635
            Base::Console().Message("CMD::CVGrp - invalid iMsg: %d\n", iMsg);
636
    };
637
}
638

639
Gui::Action* CmdTechDrawExtensionThreadsGroup::createAction()
640
{
641
    Gui::ActionGroup* pcAction = new Gui::ActionGroup(this, Gui::getMainWindow());
642
    pcAction->setDropDownMenu(true);
643
    applyCommandData(this->className(), pcAction);
644

645
    QAction* p1 = pcAction->addAction(QString());
646
    p1->setIcon(Gui::BitmapFactory().iconFromTheme("TechDraw_ExtensionThreadHoleSide"));
647
    p1->setObjectName(QString::fromLatin1("TechDraw_ExtensionThreadHoleSide"));
648
    p1->setWhatsThis(QString::fromLatin1("TechDraw_ExtensionThreadHoleSide"));
649
    QAction* p2 = pcAction->addAction(QString());
650
    p2->setIcon(Gui::BitmapFactory().iconFromTheme("TechDraw_ExtensionThreadHoleBottom"));
651
    p2->setObjectName(QString::fromLatin1("TechDraw_ExtensionThreadHoleBottom"));
652
    p2->setWhatsThis(QString::fromLatin1("TechDraw_ExtensionThreadHoleBottom"));
653
    QAction* p3 = pcAction->addAction(QString());
654
    p3->setIcon(Gui::BitmapFactory().iconFromTheme("TechDraw_ExtensionThreadBoltSide"));
655
    p3->setObjectName(QString::fromLatin1("TechDraw_ExtensionThreadBoltSide"));
656
    p3->setWhatsThis(QString::fromLatin1("TechDraw_ExtensionThreadBoltSide"));
657
    QAction* p4 = pcAction->addAction(QString());
658
    p4->setIcon(Gui::BitmapFactory().iconFromTheme("TechDraw_ExtensionThreadBoltBottom"));
659
    p4->setObjectName(QString::fromLatin1("TechDraw_ExtensionThreadBoltBottom"));
660
    p4->setWhatsThis(QString::fromLatin1("TechDraw_ExtensionThreadBoltBottom"));
661

662
    _pcAction = pcAction;
663
    languageChange();
664

665
    pcAction->setIcon(p1->icon());
666
    int defaultId = 0;
667
    pcAction->setProperty("defaultAction", QVariant(defaultId));
668

669
    return pcAction;
670
}
671

672
void CmdTechDrawExtensionThreadsGroup::languageChange()
673
{
674
    Command::languageChange();
675

676
    if (!_pcAction)
677
        return;
678
    Gui::ActionGroup* pcAction = qobject_cast<Gui::ActionGroup*>(_pcAction);
679
    QList<QAction*> a = pcAction->actions();
680

681
    QAction* arc1 = a[0];
682
    arc1->setText(QApplication::translate("CmdTechDrawExtensionThreadHoleSide",
683
                                          "Add Cosmetic Thread Hole Side View"));
684
    arc1->setToolTip(QApplication::translate("CmdTechDrawExtensionThreadHoleSide",
685
                                             "Add a cosmetic thread to the side view of a hole:<br>\
686
- Specify the line attributes (optional)<br>\
687
- Select two parallel lines<br>\
688
- Click this tool"));
689
    arc1->setStatusTip(arc1->text());
690
    QAction* arc2 = a[1];
691
    arc2->setText(QApplication::translate("CmdTechDrawExtensionThreadHoleBottom",
692
                                          "Add Cosmetic Thread Hole Bottom View"));
693
    arc2->setToolTip(
694
        QApplication::translate("CmdTechDrawExtensionThreadHoleBottom",
695
                                "Add a cosmetic thread to the top or bottom view of holes:<br>\
696
- Specify the line attributes (optional)<br>\
697
- Select one or more circles<br>\
698
- Click this tool"));
699
    arc2->setStatusTip(arc2->text());
700
    QAction* arc3 = a[2];
701
    arc3->setText(QApplication::translate("CmdTechDrawExtensionThreadBoltSide",
702
                                          "Add Cosmetic Thread Bolt Side View"));
703
    arc3->setToolTip(
704
        QApplication::translate("CmdTechDrawExtensionThreadBoltSide",
705
                                "Add a cosmetic thread to the side view of a bolt/screw/rod:<br>\
706
- Specify the line attributes (optional)<br>\
707
- Select two parallel lines<br>\
708
- Click this tool"));
709
    arc3->setStatusTip(arc3->text());
710
    QAction* arc4 = a[3];
711
    arc4->setText(QApplication::translate("CmdTechDrawExtensionThreadBoltBottom",
712
                                          "Add Cosmetic Thread Bolt Bottom View"));
713
    arc4->setToolTip(QApplication::translate(
714
        "CmdTechDrawExtensionThreadBoltBottom",
715
        "Add a cosmetic thread to the top or bottom view of bolts/screws/rods:<br>\
716
- Specify the line attributes (optional)<br>\
717
- Select one or more circles<br>\
718
- Click this tool"));
719
    arc4->setStatusTip(arc4->text());
720
}
721

722
bool CmdTechDrawExtensionThreadsGroup::isActive()
723
{
724
    bool havePage = DrawGuiUtil::needPage(this);
725
    bool haveView = DrawGuiUtil::needView(this, true);
726
    return (havePage && haveView);
727
}
728

729
//===========================================================================
730
// TechDraw_ExtensionSelectLineAttributes
731
//===========================================================================
732

733
DEF_STD_CMD_A(CmdTechDrawExtensionSelectLineAttributes)
734

735
CmdTechDrawExtensionSelectLineAttributes::CmdTechDrawExtensionSelectLineAttributes()
736
    : Command("TechDraw_ExtensionSelectLineAttributes")
737
{
738
    sAppModule = "TechDraw";
739
    sGroup = QT_TR_NOOP("TechDraw");
740
    sMenuText = QT_TR_NOOP("Select Line Attributes, Cascade Spacing and Delta Distance");
741
    sToolTipText = QT_TR_NOOP(
742
        "Select the attributes for new cosmetic lines and centerlines, and specify the cascade spacing and delta distance:<br>\
743
- Click this tool<br>\
744
- Specify the attributes, spacing and distance in the dialog box<br>\
745
- Press OK");
746
    sWhatsThis = "TechDraw_ExtensionSelectLineAttributes";
747
    sStatusTip = sMenuText;
748
    sPixmap = "TechDraw_ExtensionSelectLineAttributes";
749
}
750

751
void CmdTechDrawExtensionSelectLineAttributes::activated(int iMsg)
752
{
753
    Q_UNUSED(iMsg);
754
    Gui::Control().showDialog(new TaskDlgSelectLineAttributes(&_getActiveLineAttributes()));
755
}
756

757
bool CmdTechDrawExtensionSelectLineAttributes::isActive()
758
{
759
    bool havePage = DrawGuiUtil::needPage(this);
760
    bool haveView = DrawGuiUtil::needView(this);
761
    return (havePage && haveView);
762
}
763

764
//===========================================================================
765
// TechDraw_ExtensionChangeLineAttributes
766
//===========================================================================
767

768
DEF_STD_CMD_A(CmdTechDrawExtensionChangeLineAttributes)
769

770
CmdTechDrawExtensionChangeLineAttributes::CmdTechDrawExtensionChangeLineAttributes()
771
    : Command("TechDraw_ExtensionChangeLineAttributes")
772
{
773
    sAppModule = "TechDraw";
774
    sGroup = QT_TR_NOOP("TechDraw");
775
    sMenuText = QT_TR_NOOP("Change Line Attributes");
776
    sToolTipText = QT_TR_NOOP("Change the attributes of cosmetic lines and centerlines:<br>\
777
- Specify the line attributes (optional)<br>\
778
- Select one or more lines<br>\
779
- Click this tool");
780
    sWhatsThis = "TechDraw_ExtensionChangeLineAttributes";
781
    sStatusTip = sMenuText;
782
    sPixmap = "TechDraw_ExtensionChangeLineAttributes";
783
}
784

785
void CmdTechDrawExtensionChangeLineAttributes::activated(int iMsg)
786
{
787
    // change attributes (type, width, color) of a cosmetic or centerline
788
    Q_UNUSED(iMsg);
789
    std::vector<Gui::SelectionObject> selection;
790
    TechDraw::DrawViewPart* objFeat;
791
    if (!_checkSel(this, selection, objFeat, QT_TRANSLATE_NOOP("Command","TechDraw Change Line Attributes")))
792
        return;
793
    Gui::Command::openCommand(QT_TRANSLATE_NOOP("Command", "Change Line Attributes"));
794
    const std::vector<std::string> subNames = selection[0].getSubNames();
795
    for (const std::string& name : subNames) {
796
        int num = DrawUtil::getIndexFromName(name);
797
        BaseGeomPtr baseGeo = objFeat->getGeomByIndex(num);
798
        if (baseGeo) {
799
            if (baseGeo->getCosmetic()) {
800
                if (baseGeo->source() == 1) {
801
                    TechDraw::CosmeticEdge* cosEdgeTag = objFeat->getCosmeticEdgeBySelection(name);
802
                    _setLineAttributes(cosEdgeTag);
803
                }
804
                else if (baseGeo->source() == 2) {
805
                    TechDraw::CenterLine* centerLineTag = objFeat->getCenterLineBySelection(name);
806
                    _setLineAttributes(centerLineTag);
807
                }
808
            }
809
        }
810
    }
811
    getSelection().clearSelection();
812
    objFeat->refreshCEGeoms();
813
    objFeat->requestPaint();
814
    Gui::Command::commitCommand();
815
}
816

817
bool CmdTechDrawExtensionChangeLineAttributes::isActive()
818
{
819
    bool havePage = DrawGuiUtil::needPage(this);
820
    bool haveView = DrawGuiUtil::needView(this);
821
    return (havePage && haveView);
822
}
823

824
//===========================================================================
825
// TechDraw_ExtensionVertexAtIntersection
826
//===========================================================================
827

828
DEF_STD_CMD_A(CmdTechDrawExtensionVertexAtIntersection)
829

830
CmdTechDrawExtensionVertexAtIntersection::CmdTechDrawExtensionVertexAtIntersection()
831
    : Command("TechDraw_ExtensionVertexAtIntersection")
832
{
833
    sAppModule = "TechDraw";
834
    sGroup = QT_TR_NOOP("TechDraw");
835
    sMenuText = QT_TR_NOOP("Add Cosmetic Intersection Vertex(es)");
836
    sToolTipText =
837
        QT_TR_NOOP("Add cosmetic vertex(es) at the intersection(s) of selected edges:<br>\
838
- Select two edges<br>\
839
- Click this tool");
840
    sWhatsThis = "TechDraw_ExtensionVertexAtIntersection";
841
    sStatusTip = sMenuText;
842
    sPixmap = "TechDraw_ExtensionVertexAtIntersection";
843
}
844

845
void CmdTechDrawExtensionVertexAtIntersection::activated(int iMsg)
846
{
847
    Q_UNUSED(iMsg);
848
    //Base::Console().Message("VertexAtIntersection started\n");
849
    std::vector<Gui::SelectionObject> selection;
850
    TechDraw::DrawViewPart* objFeat;
851
    if (!_checkSel(this, selection, objFeat, QT_TRANSLATE_NOOP("Command","TechDraw Cosmetic Intersection Vertex(es)")))
852
        return;
853
    Gui::Command::openCommand(QT_TRANSLATE_NOOP("Command", "Cosmetic Intersection Vertex(es)"));
854
    const std::vector<std::string> SubNames = selection[0].getSubNames();
855
    if (SubNames.size() >= 2) {
856
        std::string GeoType1 = TechDraw::DrawUtil::getGeomTypeFromName(SubNames[0]);
857
        std::string GeoType2 = TechDraw::DrawUtil::getGeomTypeFromName(SubNames[1]);
858
        if (GeoType1 == "Edge" && GeoType2 == "Edge") {
859
            int GeoId1 = TechDraw::DrawUtil::getIndexFromName(SubNames[0]);
860
            TechDraw::BaseGeomPtr geom1 = objFeat->getGeomByIndex(GeoId1);
861
            int GeoId2 = TechDraw::DrawUtil::getIndexFromName(SubNames[1]);
862
            TechDraw::BaseGeomPtr geom2 = objFeat->getGeomByIndex(GeoId2);
863

864
            // double scale = objFeat->getScale();
865
            std::vector<Base::Vector3d> interPoints = geom1->intersection(geom2);
866
            for (auto pt : interPoints) {
867
                // std::string ptId = objFeat->addCosmeticVertex(pt/scale);
868
                // objFeat->add1CVToGV(ptId);
869
                // invert the point so the math works correctly
870
                Base::Vector3d temp = CosmeticVertex::makeCanonicalPoint(objFeat, pt);
871
                objFeat->addCosmeticVertex(temp);
872
            }
873
        }
874
    }
875
    getSelection().clearSelection();
876
    objFeat->refreshCVGeoms();
877
    objFeat->requestPaint();
878
    Gui::Command::commitCommand();
879
}
880

881
bool CmdTechDrawExtensionVertexAtIntersection::isActive()
882
{
883
    bool havePage = DrawGuiUtil::needPage(this);
884
    bool haveView = DrawGuiUtil::needView(this);
885
    return (havePage && haveView);
886
}
887

888
//===========================================================================
889
// TechDraw_ExtensionDrawCosmArc
890
//===========================================================================
891

892
void execDrawCosmArc(Gui::Command* cmd)
893
{
894
    //draw a cosmetic arc of circle
895
    std::vector<Gui::SelectionObject> selection;
896
    TechDraw::DrawViewPart* objFeat;
897
    if (!_checkSel(cmd, selection, objFeat, QT_TRANSLATE_NOOP("Command","TechDraw Cosmetic Arc")))
898
        return;
899
    Gui::Command::openCommand(QT_TRANSLATE_NOOP("Command", "Cosmetic Arc"));
900
    const std::vector<std::string> SubNames = selection[0].getSubNames();
901
    std::vector<Base::Vector3d> vertexPoints;
902
    vertexPoints = _getVertexPoints(SubNames, objFeat);
903
    if (vertexPoints.size() >= 3) {
904
        float arcRadius = (vertexPoints[1] - vertexPoints[0]).Length();
905
        float angle1 = _getAngle(vertexPoints[0], vertexPoints[1]);
906
        float angle2 = _getAngle(vertexPoints[0], vertexPoints[2]);
907
        TechDraw::BaseGeomPtr baseGeo = std::make_shared<TechDraw::AOC>(
908
            vertexPoints[0], arcRadius, angle1, angle2);
909
        std::string arcTag = objFeat->addCosmeticEdge(baseGeo->inverted());
910
        TechDraw::CosmeticEdge* arcEdge = objFeat->getCosmeticEdge(arcTag);
911
        _setLineAttributes(arcEdge);
912
        objFeat->refreshCEGeoms();
913
        objFeat->requestPaint();
914
        cmd->getSelection().clearSelection();
915
        Gui::Command::commitCommand();
916
    }
917
}
918

919
DEF_STD_CMD_A(CmdTechDrawExtensionDrawCosmArc)
920

921
CmdTechDrawExtensionDrawCosmArc::CmdTechDrawExtensionDrawCosmArc()
922
    : Command("TechDraw_ExtensionDrawCosmArc")
923
{
924
    sAppModule = "TechDraw";
925
    sGroup = QT_TR_NOOP("TechDraw");
926
    sMenuText = QT_TR_NOOP("Add Cosmetic Arc");
927
    sToolTipText = QT_TR_NOOP("Add a cosmetic counter clockwise arc based on three vertexes:<br>\
928
- Specify the line attributes (optional)<br>\
929
- Select vertex 1 (center point)<br>\
930
- Select vertex 2 (radius and start angle)<br>\
931
- Select vertex 3 (end angle)<br>\
932
- Click this tool");
933
    sWhatsThis = "TechDraw_ExtensionDrawCosmArc";
934
    sStatusTip = sMenuText;
935
    sPixmap = "TechDraw_ExtensionDrawCosmArc";
936
}
937

938
void CmdTechDrawExtensionDrawCosmArc::activated(int iMsg)
939
{
940
    Q_UNUSED(iMsg);
941
    //Base::Console().Message("Cosmetic Arc started\n");
942
    execDrawCosmArc(this);
943
}
944

945
bool CmdTechDrawExtensionDrawCosmArc::isActive()
946
{
947
    bool havePage = DrawGuiUtil::needPage(this);
948
    bool haveView = DrawGuiUtil::needView(this);
949
    return (havePage && haveView);
950
}
951

952
//===========================================================================
953
// TechDraw_ExtensionDrawCosmCircle
954
//===========================================================================
955

956
void execDrawCosmCircle(Gui::Command* cmd)
957
{
958
    //draw a cosmetic circle
959
    std::vector<Gui::SelectionObject> selection;
960
    TechDraw::DrawViewPart* objFeat;
961
    if (!_checkSel(cmd, selection, objFeat, QT_TRANSLATE_NOOP("Command","TechDraw Cosmetic Circle")))
962
        return;
963
    Gui::Command::openCommand(QT_TRANSLATE_NOOP("Command", "Cosmetic Circle"));
964
    const std::vector<std::string> SubNames = selection[0].getSubNames();
965
    std::vector<Base::Vector3d> vertexPoints;
966
    vertexPoints = _getVertexPoints(SubNames, objFeat);
967
    if (vertexPoints.size() >= 2) {
968
        float circleRadius = (vertexPoints[1] - vertexPoints[0]).Length();
969
        TechDraw::BaseGeomPtr baseGeo =
970
            std::make_shared<TechDraw::Circle>(vertexPoints[0], circleRadius);
971
        std::string circleTag = objFeat->addCosmeticEdge(baseGeo->inverted());
972
        TechDraw::CosmeticEdge* circleEdge = objFeat->getCosmeticEdge(circleTag);
973
        _setLineAttributes(circleEdge);
974
        objFeat->refreshCEGeoms();
975
        objFeat->requestPaint();
976
        cmd->getSelection().clearSelection();
977
        Gui::Command::commitCommand();
978
    }
979
}
980

981
DEF_STD_CMD_A(CmdTechDrawExtensionDrawCosmCircle)
982

983
CmdTechDrawExtensionDrawCosmCircle::CmdTechDrawExtensionDrawCosmCircle()
984
    : Command("TechDraw_ExtensionDrawCosmCircle")
985
{
986
    sAppModule = "TechDraw";
987
    sGroup = QT_TR_NOOP("TechDraw");
988
    sMenuText = QT_TR_NOOP("Add Cosmetic Circle");
989
    sToolTipText = QT_TR_NOOP("Add a cosmetic circle based on two vertexes:<br>\
990
- Specify the line attributes (optional)<br>\
991
- Select vertex 1 (center point)<br>\
992
- Select vertex 2 (radius)<br>\
993
- Click this tool");
994
    sWhatsThis = "TechDraw_ExtensionDrawCosmCircle";
995
    sStatusTip = sMenuText;
996
    sPixmap = "TechDraw_ExtensionDrawCosmCircle";
997
}
998

999
void CmdTechDrawExtensionDrawCosmCircle::activated(int iMsg)
1000
{
1001
    Q_UNUSED(iMsg);
1002
    //Base::Console().Message("Cosmetic Circle started\n");
1003
    execDrawCosmCircle(this);
1004
}
1005

1006
bool CmdTechDrawExtensionDrawCosmCircle::isActive()
1007
{
1008
    bool havePage = DrawGuiUtil::needPage(this);
1009
    bool haveView = DrawGuiUtil::needView(this);
1010
    return (havePage && haveView);
1011
}
1012

1013
//===========================================================================
1014
// TechDraw_ExtensionDrawCosmCircle3Points
1015
//===========================================================================
1016

1017
void execDrawCosmCircle3Points(Gui::Command* cmd)
1018
{
1019
    //draw a cosmetic circle through 3 points
1020
    std::vector<Gui::SelectionObject> selection;
1021
    TechDraw::DrawViewPart* objFeat;
1022
    if (!_checkSel(cmd, selection, objFeat, QT_TRANSLATE_NOOP("Command","TechDraw Cosmetic Circle 3 Points")))
1023
        return;
1024
    Gui::Command::openCommand(QT_TRANSLATE_NOOP("Command", "Cosmetic Circle 3 Points"));
1025
    const std::vector<std::string> SubNames = selection[0].getSubNames();
1026
    std::vector<Base::Vector3d> vertexPoints;
1027
    vertexPoints = _getVertexPoints(SubNames, objFeat);
1028
    if (vertexPoints.size() >= 3) {
1029
        Base::Vector3d circleCenter = _circleCenter(vertexPoints[0],
1030
                                                    vertexPoints[1],
1031
                                                    vertexPoints[2]);
1032
        float circleRadius = (vertexPoints[0] - circleCenter).Length();
1033
        TechDraw::BaseGeomPtr theCircle =
1034
            std::make_shared<TechDraw::Circle>(circleCenter, circleRadius);
1035
        std::string circleTag = objFeat->addCosmeticEdge(theCircle->inverted());
1036
        TechDraw::CosmeticEdge* circleEdge = objFeat->getCosmeticEdge(circleTag);
1037
        _setLineAttributes(circleEdge);
1038
        objFeat->refreshCEGeoms();
1039
        objFeat->requestPaint();
1040
        cmd->getSelection().clearSelection();
1041
        Gui::Command::commitCommand();
1042
    }
1043
}
1044

1045
DEF_STD_CMD_A(CmdTechDrawExtensionDrawCosmCircle3Points)
1046

1047
CmdTechDrawExtensionDrawCosmCircle3Points::CmdTechDrawExtensionDrawCosmCircle3Points()
1048
    : Command("TechDraw_ExtensionDrawCosmCircle3Points")
1049
{
1050
    sAppModule = "TechDraw";
1051
    sGroup = QT_TR_NOOP("TechDraw");
1052
    sMenuText = QT_TR_NOOP("Add Cosmetic Circle 3 Points");
1053
    sToolTipText = QT_TR_NOOP("Add a cosmetic circle based on three vertexes:<br>\
1054
- Specify the line attributes (optional)<br>\
1055
- Select 3 vertexes<br>\
1056
- Click this tool");
1057
    sWhatsThis = "TechDraw_ExtensionDrawCosmCircle3Points";
1058
    sStatusTip = sMenuText;
1059
    sPixmap = "TechDraw_ExtensionDrawCosmCircle3Points";
1060
}
1061

1062
void CmdTechDrawExtensionDrawCosmCircle3Points::activated(int iMsg)
1063
{
1064
    Q_UNUSED(iMsg);
1065
    //Base::Console().Message("Cosmetic Circle 3 Points started\n");
1066
    execDrawCosmCircle3Points(this);
1067
}
1068

1069
bool CmdTechDrawExtensionDrawCosmCircle3Points::isActive()
1070
{
1071
    bool havePage = DrawGuiUtil::needPage(this);
1072
    bool haveView = DrawGuiUtil::needView(this);
1073
    return (havePage && haveView);
1074
}
1075

1076
//===========================================================================
1077
// TechDraw_ExtensionDrawCirclesGroup
1078
//===========================================================================
1079

1080
DEF_STD_CMD_ACL(CmdTechDrawExtensionDrawCirclesGroup)
1081

1082
CmdTechDrawExtensionDrawCirclesGroup::CmdTechDrawExtensionDrawCirclesGroup()
1083
    : Command("TechDraw_ExtensionDrawCirclesGroup")
1084
{
1085
    sAppModule = "TechDraw";
1086
    sGroup = QT_TR_NOOP("TechDraw");
1087
    sMenuText = QT_TR_NOOP("Add Cosmetic Circle");
1088
    sToolTipText = QT_TR_NOOP("Add a cosmetic circle based on two vertexes:<br>\
1089
- Specify the line attributes (optional)<br>\
1090
- Select vertex 1 (center point)<br>\
1091
- Select vertex 2 (radius)<br>\
1092
- Click this tool");
1093
    sWhatsThis = "TechDraw_ExtensionDrawCirclesGroup";
1094
    sStatusTip = sMenuText;
1095
}
1096

1097
void CmdTechDrawExtensionDrawCirclesGroup::activated(int iMsg)
1098
{
1099
    //    Base::Console().Message("CMD::ExtensionDrawCirclesGroup - activated(%d)\n", iMsg);
1100
    Gui::TaskView::TaskDialog* dlg = Gui::Control().activeDialog();
1101
    if (dlg) {
1102
        QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Task In Progress"),
1103
                             QObject::tr("Close active task dialog and try again."));
1104
        return;
1105
    }
1106

1107
    Gui::ActionGroup* pcAction = qobject_cast<Gui::ActionGroup*>(_pcAction);
1108
    pcAction->setIcon(pcAction->actions().at(iMsg)->icon());
1109
    switch (iMsg) {
1110
        case 0://draw cosmetic circle
1111
            execDrawCosmCircle(this);
1112
            break;
1113
        case 1://draw cosmetic arc
1114
            execDrawCosmArc(this);
1115
            break;
1116
        case 2://draw cosmetic circle 3 points
1117
            execDrawCosmCircle3Points(this);
1118
            break;
1119
        default:
1120
            Base::Console().Message("CMD::CVGrp - invalid iMsg: %d\n", iMsg);
1121
    };
1122
}
1123

1124
Gui::Action* CmdTechDrawExtensionDrawCirclesGroup::createAction()
1125
{
1126
    Gui::ActionGroup* pcAction = new Gui::ActionGroup(this, Gui::getMainWindow());
1127
    pcAction->setDropDownMenu(true);
1128
    applyCommandData(this->className(), pcAction);
1129

1130
    QAction* p1 = pcAction->addAction(QString());
1131
    p1->setIcon(Gui::BitmapFactory().iconFromTheme("TechDraw_ExtensionDrawCosmCircle"));
1132
    p1->setObjectName(QString::fromLatin1("TechDraw_ExtensionDrawCosmCircle"));
1133
    p1->setWhatsThis(QString::fromLatin1("TechDraw_ExtensionDrawCosmCircle"));
1134
    QAction* p2 = pcAction->addAction(QString());
1135
    p2->setIcon(Gui::BitmapFactory().iconFromTheme("TechDraw_ExtensionDrawCosmArc"));
1136
    p2->setObjectName(QString::fromLatin1("TechDraw_ExtensionDrawCosmArc"));
1137
    p2->setWhatsThis(QString::fromLatin1("TechDraw_ExtensionDrawCosmArc"));
1138
    QAction* p3 = pcAction->addAction(QString());
1139
    p3->setIcon(Gui::BitmapFactory().iconFromTheme("TechDraw_ExtensionDrawCosmCircle3Points"));
1140
    p3->setObjectName(QString::fromLatin1("TechDraw_ExtensionDrawCosmCircle3Points"));
1141
    p3->setWhatsThis(QString::fromLatin1("TechDraw_ExtensionDrawCosmCircle3Points"));
1142

1143
    _pcAction = pcAction;
1144
    languageChange();
1145

1146
    pcAction->setIcon(p1->icon());
1147
    int defaultId = 0;
1148
    pcAction->setProperty("defaultAction", QVariant(defaultId));
1149

1150
    return pcAction;
1151
}
1152

1153
void CmdTechDrawExtensionDrawCirclesGroup::languageChange()
1154
{
1155
    Command::languageChange();
1156

1157
    if (!_pcAction)
1158
        return;
1159
    Gui::ActionGroup* pcAction = qobject_cast<Gui::ActionGroup*>(_pcAction);
1160
    QList<QAction*> a = pcAction->actions();
1161

1162
    QAction* arc1 = a[0];
1163
    arc1->setText(
1164
        QApplication::translate("CmdTechDrawExtensionDrawCosmCircle", "Add Cosmetic Circle"));
1165
    arc1->setToolTip(QApplication::translate("CmdTechDrawExtensionDrawCosmCircle",
1166
                                             "Add a cosmetic circle based on two vertexes:<br>\
1167
- Specify the line attributes (optional)<br>\
1168
- Select vertex 1 (center point)<br>\
1169
- Select vertex 2 (radius)<br>\
1170
- Click this tool"));
1171
    arc1->setStatusTip(arc1->text());
1172
    QAction* arc2 = a[1];
1173
    arc2->setText(QApplication::translate("CmdTechDrawExtensionDrawCosmArc", "Add Cosmetic Arc"));
1174
    arc2->setToolTip(
1175
        QApplication::translate("CmdTechDrawExtensionDrawCosmArc",
1176
                                "Add a cosmetic counter clockwise arc based on three vertexes:<br>\
1177
- Specify the line attributes (optional)<br>\
1178
- Select vertex 1 (center point)<br>\
1179
- Select vertex 2 (radius and start angle)<br>\
1180
- Select vertex 3 (end angle)<br>\
1181
- Click this tool"));
1182
    arc2->setStatusTip(arc2->text());
1183
    QAction* arc3 = a[2];
1184
    arc3->setText(QApplication::translate("CmdTechDrawExtensionDrawCosmCircle3Points",
1185
                                          "Add Cosmetic Circle 3 Points"));
1186
    arc3->setToolTip(QApplication::translate("CmdTechDrawExtensionDrawCosmCircle3Points",
1187
                                             "Add a cosmetic circle based on three vertexes:<br>\
1188
- Specify the line attributes (optional)<br>\
1189
- Select three vertexes<br>\
1190
- Click this tool"));
1191
    arc3->setStatusTip(arc3->text());
1192
}
1193

1194
bool CmdTechDrawExtensionDrawCirclesGroup::isActive()
1195
{
1196
    bool havePage = DrawGuiUtil::needPage(this);
1197
    bool haveView = DrawGuiUtil::needView(this, true);
1198
    return (havePage && haveView);
1199
}
1200

1201
//===========================================================================
1202
// TechDraw_ExtensionLineParallel
1203
//===========================================================================
1204

1205
void execLineParallelPerpendicular(Gui::Command* cmd, bool isParallel)
1206
{
1207
    // create a line parallel or perpendicular to another line
1208
    std::vector<Gui::SelectionObject> selection;
1209
    TechDraw::DrawViewPart* objFeat;
1210
    if (!_checkSel(cmd, selection, objFeat, QT_TRANSLATE_NOOP("Command","TechDraw Cosmetic Line Parallel/Perpendicular")))
1211
        return;
1212
    Gui::Command::openCommand(QT_TRANSLATE_NOOP("Command", "Cosmetic Line Parallel/Perpendicular"));
1213
    const std::vector<std::string> SubNames = selection[0].getSubNames();
1214
    if (SubNames.size() >= 2) {
1215
        std::string GeoType1 = TechDraw::DrawUtil::getGeomTypeFromName(SubNames[0]);
1216
        std::string GeoType2 = TechDraw::DrawUtil::getGeomTypeFromName(SubNames[1]);
1217
        int EdgeId;
1218
        int VertId;
1219
        if (GeoType1 == "Edge" && GeoType2 == "Vertex") {
1220
            EdgeId = TechDraw::DrawUtil::getIndexFromName(SubNames[0]);
1221
            VertId = TechDraw::DrawUtil::getIndexFromName(SubNames[1]);
1222
        } else if (GeoType2 == "Edge" && GeoType1 == "Vertex") {
1223
            EdgeId = TechDraw::DrawUtil::getIndexFromName(SubNames[1]);
1224
            VertId = TechDraw::DrawUtil::getIndexFromName(SubNames[0]);
1225
        } else {
1226
            // we don't have an edge + vertex as selection
1227
            return;
1228
        }
1229
        TechDraw::BaseGeomPtr geom1 = objFeat->getGeomByIndex(EdgeId);
1230
        TechDraw::GenericPtr lineGen = std::static_pointer_cast<TechDraw::Generic>(geom1);
1231
        Base::Vector3d lineStart = lineGen->points.at(0);
1232
        Base::Vector3d lineEnd = lineGen->points.at(1);
1233
        TechDraw::VertexPtr vert = objFeat->getProjVertexByIndex(VertId);
1234
        Base::Vector3d vertexPoint(vert->point().x, vert->point().y, 0.0);
1235
        Base::Vector3d halfVector = (lineEnd - lineStart) / 2.0;
1236
        if (!isParallel) {
1237
            float dummy = halfVector.x;
1238
            halfVector.x = -halfVector.y;
1239
            halfVector.y = dummy;
1240
        }
1241
        Base::Vector3d startPoint = vertexPoint + halfVector;
1242
        Base::Vector3d endPoint = vertexPoint - halfVector;
1243
        startPoint.y = -startPoint.y;
1244
        endPoint.y = -endPoint.y;
1245
        TechDraw::BaseGeomPtr cLine = CosmeticEdge::makeCanonicalLine(objFeat, startPoint, endPoint);
1246
        std::string lineTag = objFeat->addCosmeticEdge(cLine);
1247
        TechDraw::CosmeticEdge* lineEdge = objFeat->getCosmeticEdge(lineTag);
1248
        _setLineAttributes(lineEdge);
1249
        objFeat->refreshCEGeoms();
1250
        objFeat->requestPaint();
1251
        cmd->getSelection().clearSelection();
1252
    }
1253
    Gui::Command::commitCommand();
1254
}
1255

1256
DEF_STD_CMD_A(CmdTechDrawExtensionLineParallel)
1257

1258
CmdTechDrawExtensionLineParallel::CmdTechDrawExtensionLineParallel()
1259
    : Command("TechDraw_ExtensionLineParallel")
1260
{
1261
    sAppModule = "TechDraw";
1262
    sGroup = QT_TR_NOOP("TechDraw");
1263
    sMenuText = QT_TR_NOOP("Add Cosmetic Parallel Line");
1264
    sToolTipText = QT_TR_NOOP("Add a cosmetic line parallel to another line through a vertex:<br>\
1265
- Select a line<br>\
1266
- Select a vertex<br>\
1267
- Click this tool");
1268
    sWhatsThis = "TechDraw_ExtensionLineParallel";
1269
    sStatusTip = sMenuText;
1270
    sPixmap = "TechDraw_ExtensionLineParallel";
1271
}
1272

1273
void CmdTechDrawExtensionLineParallel::activated(int iMsg)
1274
{
1275
    Q_UNUSED(iMsg);
1276
    execLineParallelPerpendicular(this, true);
1277
}
1278

1279
bool CmdTechDrawExtensionLineParallel::isActive()
1280
{
1281
    bool havePage = DrawGuiUtil::needPage(this);
1282
    bool haveView = DrawGuiUtil::needView(this);
1283
    return (havePage && haveView);
1284
}
1285

1286
//===========================================================================
1287
// TechDraw_ExtensionLinePerpendicular
1288
//===========================================================================
1289

1290
DEF_STD_CMD_A(CmdTechDrawExtensionLinePerpendicular)
1291

1292
CmdTechDrawExtensionLinePerpendicular::CmdTechDrawExtensionLinePerpendicular()
1293
    : Command("TechDraw_ExtensionLinePerpendicular")
1294
{
1295
    sAppModule = "TechDraw";
1296
    sGroup = QT_TR_NOOP("TechDraw");
1297
    sMenuText = QT_TR_NOOP("Add Cosmetic Perpendicular Line");
1298
    sToolTipText =
1299
        QT_TR_NOOP("Add a cosmetic line perpendicular to another line through a vertex:<br>\
1300
- Select a line<br>\
1301
- Select a vertex<br>\
1302
- Click this tool");
1303
    sWhatsThis = "TechDraw_ExtensionLinePerpendicular";
1304
    sStatusTip = sMenuText;
1305
    sPixmap = "TechDraw_ExtensionLinePerpendicular";
1306
}
1307

1308
void CmdTechDrawExtensionLinePerpendicular::activated(int iMsg)
1309
{
1310
    Q_UNUSED(iMsg);
1311
    execLineParallelPerpendicular(this, false);
1312
}
1313

1314
bool CmdTechDrawExtensionLinePerpendicular::isActive()
1315
{
1316
    bool havePage = DrawGuiUtil::needPage(this);
1317
    bool haveView = DrawGuiUtil::needView(this);
1318
    return (havePage && haveView);
1319
}
1320

1321
//===========================================================================
1322
// TechDraw_ExtensionLinePPGroup
1323
//===========================================================================
1324

1325
DEF_STD_CMD_ACL(CmdTechDrawExtensionLinePPGroup)
1326

1327
CmdTechDrawExtensionLinePPGroup::CmdTechDrawExtensionLinePPGroup()
1328
    : Command("TechDraw_ExtensionLinePPGroup")
1329
{
1330
    sAppModule = "TechDraw";
1331
    sGroup = QT_TR_NOOP("TechDraw");
1332
    sMenuText = QT_TR_NOOP("Add Cosmetic Parallel Line");
1333
    sToolTipText = QT_TR_NOOP("Add a cosmetic line parallel to another line through a vertex:<br>\
1334
- Select a line<br>\
1335
- Select a vertex<br>\
1336
- Click this tool");
1337
    sWhatsThis = "TechDraw_ExtensionLinePPGroup";
1338
    sStatusTip = sMenuText;
1339
}
1340

1341
void CmdTechDrawExtensionLinePPGroup::activated(int iMsg)
1342
{
1343
    //    Base::Console().Message("CMD::ExtensionLinePPGroup - activated(%d)\n", iMsg);
1344
    Gui::TaskView::TaskDialog* dlg = Gui::Control().activeDialog();
1345
    if (dlg) {
1346
        QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Task In Progress"),
1347
                             QObject::tr("Close active task dialog and try again."));
1348
        return;
1349
    }
1350

1351
    Gui::ActionGroup* pcAction = qobject_cast<Gui::ActionGroup*>(_pcAction);
1352
    pcAction->setIcon(pcAction->actions().at(iMsg)->icon());
1353
    switch (iMsg) {
1354
        case 0://create parallel line
1355
            execLineParallelPerpendicular(this, true);
1356
            break;
1357
        case 1://create perpendicular line
1358
            execLineParallelPerpendicular(this, false);
1359
            break;
1360
        default:
1361
            Base::Console().Message("CMD::CVGrp - invalid iMsg: %d\n", iMsg);
1362
    };
1363
}
1364

1365
Gui::Action* CmdTechDrawExtensionLinePPGroup::createAction()
1366
{
1367
    Gui::ActionGroup* pcAction = new Gui::ActionGroup(this, Gui::getMainWindow());
1368
    pcAction->setDropDownMenu(true);
1369
    applyCommandData(this->className(), pcAction);
1370

1371
    QAction* p1 = pcAction->addAction(QString());
1372
    p1->setIcon(Gui::BitmapFactory().iconFromTheme("TechDraw_ExtensionLineParallel"));
1373
    p1->setObjectName(QString::fromLatin1("TechDraw_ExtensionLineParallel"));
1374
    p1->setWhatsThis(QString::fromLatin1("TechDraw_ExtensionLineParallel"));
1375
    QAction* p2 = pcAction->addAction(QString());
1376
    p2->setIcon(Gui::BitmapFactory().iconFromTheme("TechDraw_ExtensionLinePerpendicular"));
1377
    p2->setObjectName(QString::fromLatin1("TechDraw_ExtensionLinePerpendicular"));
1378
    p2->setWhatsThis(QString::fromLatin1("TechDraw_ExtensionLinePerpendicular"));
1379

1380
    _pcAction = pcAction;
1381
    languageChange();
1382

1383
    pcAction->setIcon(p1->icon());
1384
    int defaultId = 0;
1385
    pcAction->setProperty("defaultAction", QVariant(defaultId));
1386

1387
    return pcAction;
1388
}
1389

1390
void CmdTechDrawExtensionLinePPGroup::languageChange()
1391
{
1392
    Command::languageChange();
1393

1394
    if (!_pcAction)
1395
        return;
1396
    Gui::ActionGroup* pcAction = qobject_cast<Gui::ActionGroup*>(_pcAction);
1397
    QList<QAction*> a = pcAction->actions();
1398

1399
    QAction* arc1 = a[0];
1400
    arc1->setText(
1401
        QApplication::translate("CmdTechDrawExtensionLineParallel", "Add Cosmetic Parallel Line"));
1402
    arc1->setToolTip(
1403
        QApplication::translate("CmdTechDrawExtensionLineParallel",
1404
                                "Add a cosmetic line parallel to another line through a vertex:<br>\
1405
- Select a line<br>\
1406
- Select a vertex<br>\
1407
- Click this tool"));
1408
    arc1->setStatusTip(arc1->text());
1409
    QAction* arc2 = a[1];
1410
    arc2->setText(QApplication::translate("CmdTechDrawExtensionLinePerpendicular",
1411
                                          "Add Cosmetic Perpendicular Line"));
1412
    arc2->setToolTip(QApplication::translate(
1413
        "CmdTechDrawExtensionLinePerpendicular",
1414
        "Add a cosmetic line perpendicular to another line through a vertex:<br>\
1415
- Select a line<br>\
1416
- Select a vertex<br>\
1417
- Click this tool"));
1418
    arc2->setStatusTip(arc2->text());
1419
}
1420

1421
bool CmdTechDrawExtensionLinePPGroup::isActive()
1422
{
1423
    bool havePage = DrawGuiUtil::needPage(this);
1424
    bool haveView = DrawGuiUtil::needView(this, true);
1425
    return (havePage && haveView);
1426
}
1427

1428
//===========================================================================
1429
// TechDraw_ExtensionLockUnlockView
1430
//===========================================================================
1431

1432
DEF_STD_CMD_A(CmdTechDrawExtensionLockUnlockView)
1433

1434
CmdTechDrawExtensionLockUnlockView::CmdTechDrawExtensionLockUnlockView()
1435
    : Command("TechDraw_ExtensionLockUnlockView")
1436
{
1437
    sAppModule = "TechDraw";
1438
    sGroup = QT_TR_NOOP("TechDraw");
1439
    sMenuText = QT_TR_NOOP("Lock/Unlock View");
1440
    sToolTipText = QT_TR_NOOP("Lock or unlock the position of a view:<br>\
1441
- Select a single view<br>\
1442
- Click this tool");
1443
    sWhatsThis = "TechDraw_ExtensionLockUnlockView";
1444
    sStatusTip = sMenuText;
1445
    sPixmap = "TechDraw_ExtensionLockUnlockView";
1446
}
1447

1448
void CmdTechDrawExtensionLockUnlockView::activated(int iMsg)
1449
{
1450
    // lock/unlock a selected view
1451
    Q_UNUSED(iMsg);
1452
    std::vector<Gui::SelectionObject> selection;
1453
    TechDraw::DrawViewPart* objFeat;
1454
    if (!_checkSel(this, selection, objFeat, QT_TRANSLATE_NOOP("Command","TechDraw Lock/Unlock View")))
1455
        return;
1456
    Gui::Command::openCommand(QT_TRANSLATE_NOOP("Command", "Lock/Unlock View"));
1457
    if (objFeat->isDerivedFrom(TechDraw::DrawViewPart::getClassTypeId())) {
1458
        bool lockPosition = objFeat->LockPosition.getValue();
1459
        lockPosition = !lockPosition;
1460
        objFeat->LockPosition.setValue(lockPosition);
1461
    }
1462
    Gui::Command::commitCommand();
1463
}
1464

1465
bool CmdTechDrawExtensionLockUnlockView::isActive()
1466
{
1467
    bool havePage = DrawGuiUtil::needPage(this);
1468
    bool haveView = DrawGuiUtil::needView(this);
1469
    return (havePage && haveView);
1470
}
1471

1472
//===========================================================================
1473
// TechDraw_ExtensionExtendLine
1474
//===========================================================================
1475

1476
void execExtendShortenLine(Gui::Command* cmd, bool extend)
1477
{
1478
    // extend or shorten a cosmetic line or a centerline
1479
    std::vector<Gui::SelectionObject> selection;
1480
    TechDraw::DrawViewPart* objFeat;
1481
    if (!_checkSel(cmd, selection, objFeat, QT_TRANSLATE_NOOP("Command","TechDraw Extend/Shorten Line")))
1482
        return;
1483
    Gui::Command::openCommand(QT_TRANSLATE_NOOP("Command", "Extend/Shorten Line"));
1484
    const std::vector<std::string> subNames = selection[0].getSubNames();
1485
    if (!subNames.empty()) {
1486
        std::string name = subNames[0];
1487
        int num = DrawUtil::getIndexFromName(name);
1488
        std::string geoType = TechDraw::DrawUtil::getGeomTypeFromName(name);
1489
        if (geoType == "Edge") {
1490
            TechDraw::BaseGeomPtr baseGeo = objFeat->getGeomByIndex(num);
1491
            if (baseGeo) {
1492
                if (baseGeo->getGeomType() == TechDraw::GENERIC) {
1493
                    // start and end points are scaled and rotated. invert the points
1494
                    // so the canonicalPoint math works correctly.
1495
                    Base::Vector3d P0 = DU::invertY(baseGeo->getStartPoint());
1496
                    Base::Vector3d P1 = DU::invertY(baseGeo->getEndPoint());
1497
                    // convert start and end to unscaled, unrotated.
1498
                    P0 = CosmeticVertex::makeCanonicalPoint(objFeat, P0);
1499
                    P1 = CosmeticVertex::makeCanonicalPoint(objFeat, P1);
1500
                    // put the points back into weird Qt coord system.
1501
                    P0 = DU::invertY(P0);
1502
                    P1 = DU::invertY(P1);
1503
                    bool isCenterLine = false;
1504
                    TechDraw::CenterLine* centerEdge = nullptr;
1505
                    if (baseGeo->getCosmetic()) {
1506
                        std::string uniTag = baseGeo->getCosmeticTag();
1507
                        int oldStyle = 1;
1508
                        float oldWeight = 1.0f;
1509
                        App::Color oldColor;
1510
                        std::vector<std::string> toDelete;
1511
                        toDelete.push_back(uniTag);
1512
                        if (baseGeo->source() == 1) {
1513
                            auto cosEdge = objFeat->getCosmeticEdge(uniTag);
1514
                            oldStyle = cosEdge->m_format.m_lineNumber;
1515
                            oldWeight = cosEdge->m_format.m_weight;
1516
                            oldColor = cosEdge->m_format.m_color;
1517
                            objFeat->removeCosmeticEdge(toDelete);
1518
                        }
1519
                        else if (baseGeo->source() == 2) {
1520
                            isCenterLine = true;
1521
                            centerEdge = objFeat->getCenterLine(uniTag);
1522
                        }
1523
                        Base::Vector3d direction = (P1 - P0).Normalize();
1524
                        Base::Vector3d delta = direction * activeDimAttributes.getLineStretch();
1525
                        Base::Vector3d startPt, endPt;
1526
                        if (extend) {
1527
                            startPt = P0 - delta;
1528
                            endPt = P1 + delta;
1529
                        }
1530
                        else {
1531
                            startPt = P0 + delta;
1532
                            endPt = P1 - delta;
1533
                        }
1534
                        startPt.y = -startPt.y;
1535
                        endPt.y = -endPt.y;
1536
                        if (isCenterLine) {
1537
                            centerEdge->m_extendBy += activeDimAttributes.getLineStretch();
1538
                            objFeat->refreshCLGeoms();
1539
                        }
1540
                        else {
1541
                            std::string lineTag =
1542
                                objFeat->addCosmeticEdge(startPt, endPt);
1543
                            TechDraw::CosmeticEdge* lineEdge = objFeat->getCosmeticEdge(lineTag);
1544
                            _setLineAttributes(lineEdge, oldStyle, oldWeight, oldColor);
1545
                            objFeat->refreshCEGeoms();
1546
                        }
1547
                        objFeat->requestPaint();
1548
                    }
1549
                }
1550
            }
1551
        }
1552
    }
1553
    Gui::Command::commitCommand();
1554
}
1555

1556
DEF_STD_CMD_A(CmdTechDrawExtensionExtendLine)
1557

1558
CmdTechDrawExtensionExtendLine::CmdTechDrawExtensionExtendLine()
1559
    : Command("TechDraw_ExtensionExtendLine")
1560
{
1561
    sAppModule = "TechDraw";
1562
    sGroup = QT_TR_NOOP("TechDraw");
1563
    sMenuText = QT_TR_NOOP("Extend Line");
1564
    sToolTipText = QT_TR_NOOP("Extend a cosmetic line or centerline at both ends:<br>\
1565
- Specify the delta distance (optional)<br>\
1566
- Select a single line<br>\
1567
- Click this tool");
1568
    sWhatsThis = "TechDraw_ExtensionExtendLine";
1569
    sStatusTip = sMenuText;
1570
    sPixmap = "TechDraw_ExtensionExtendLine";
1571
}
1572

1573
void CmdTechDrawExtensionExtendLine::activated(int iMsg)
1574
{
1575
    Q_UNUSED(iMsg);
1576
    execExtendShortenLine(this, true);
1577
    ///Base::Console().Message("ExtendLine started\n");
1578
}
1579

1580
bool CmdTechDrawExtensionExtendLine::isActive()
1581
{
1582
    bool havePage = DrawGuiUtil::needPage(this);
1583
    bool haveView = DrawGuiUtil::needView(this);
1584
    return (havePage && haveView);
1585
}
1586

1587
//===========================================================================
1588
// TechDraw_ExtensionShortenLine
1589
//===========================================================================
1590

1591
DEF_STD_CMD_A(CmdTechDrawExtensionShortenLine)
1592

1593
CmdTechDrawExtensionShortenLine::CmdTechDrawExtensionShortenLine()
1594
    : Command("TechDraw_ExtensionShortenLine")
1595
{
1596
    sAppModule = "TechDraw";
1597
    sGroup = QT_TR_NOOP("TechDraw");
1598
    sMenuText = QT_TR_NOOP("Shorten Line");
1599
    sToolTipText = QT_TR_NOOP("Shorten a cosmetic line or centerline at both ends:<br>\
1600
- Specify the delta distance (optional)<br>\
1601
- Select a single line<br>\
1602
- Click this tool");
1603
    sWhatsThis = "TechDraw_ExtensionShortenLine";
1604
    sStatusTip = sMenuText;
1605
    sPixmap = "TechDraw_ExtensionShortenLine";
1606
}
1607

1608
void CmdTechDrawExtensionShortenLine::activated(int iMsg)
1609
{
1610
    Q_UNUSED(iMsg);
1611
    execExtendShortenLine(this, false);
1612
    ///Base::Console().Message("ShortenLine started\n");
1613
}
1614

1615
bool CmdTechDrawExtensionShortenLine::isActive()
1616
{
1617
    bool havePage = DrawGuiUtil::needPage(this);
1618
    bool haveView = DrawGuiUtil::needView(this);
1619
    return (havePage && haveView);
1620
}
1621

1622
//===========================================================================
1623
// TechDraw_ExtensionExtendShortenLineGroup
1624
//===========================================================================
1625

1626
DEF_STD_CMD_ACL(CmdTechDrawExtendShortenLineGroup)
1627

1628
CmdTechDrawExtendShortenLineGroup::CmdTechDrawExtendShortenLineGroup()
1629
    : Command("TechDraw_ExtensionExtendShortenLineGroup")
1630
{
1631
    sAppModule = "TechDraw";
1632
    sGroup = QT_TR_NOOP("TechDraw");
1633
    sMenuText = QT_TR_NOOP("Extend Line");
1634
    sToolTipText = QT_TR_NOOP("Extend a cosmetic line or centerline at both ends:<br>\
1635
- Specify the delta distance (optional)<br>\
1636
- Select a single line<br>\
1637
- Click this tool");
1638
    sWhatsThis = "TechDraw_ExtensionExtendShortenLineGroup";
1639
    sStatusTip = sMenuText;
1640
}
1641

1642
void CmdTechDrawExtendShortenLineGroup::activated(int iMsg)
1643
{
1644
    // Base::Console().Message("CMD::ExtendShortenLineGroup - activated(%d)\n", iMsg);
1645
    Gui::TaskView::TaskDialog* dlg = Gui::Control().activeDialog();
1646
    if (dlg) {
1647
        QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Task In Progress"),
1648
                             QObject::tr("Close active task dialog and try again."));
1649
        return;
1650
    }
1651

1652
    Gui::ActionGroup* pcAction = qobject_cast<Gui::ActionGroup*>(_pcAction);
1653
    pcAction->setIcon(pcAction->actions().at(iMsg)->icon());
1654
    switch (iMsg) {
1655
        case 0://extend a line
1656
            execExtendShortenLine(this, true);
1657
            break;
1658
        case 1://shorten line
1659
            execExtendShortenLine(this, false);
1660
            break;
1661
        default:
1662
            Base::Console().Message("CMD::CVGrp - invalid iMsg: %d\n", iMsg);
1663
    };
1664
}
1665

1666
Gui::Action* CmdTechDrawExtendShortenLineGroup::createAction()
1667
{
1668
    Gui::ActionGroup* pcAction = new Gui::ActionGroup(this, Gui::getMainWindow());
1669
    pcAction->setDropDownMenu(true);
1670
    applyCommandData(this->className(), pcAction);
1671

1672
    QAction* p1 = pcAction->addAction(QString());
1673
    p1->setIcon(Gui::BitmapFactory().iconFromTheme("TechDraw_ExtensionExtendLine"));
1674
    p1->setObjectName(QString::fromLatin1("TechDraw_ExtensionExtendLine"));
1675
    p1->setWhatsThis(QString::fromLatin1("TechDraw_ExtensionExtendLine"));
1676
    QAction* p2 = pcAction->addAction(QString());
1677
    p2->setIcon(Gui::BitmapFactory().iconFromTheme("TechDraw_ExtensionShortenLine"));
1678
    p2->setObjectName(QString::fromLatin1("TechDraw_ExtensionShortenLine"));
1679
    p2->setWhatsThis(QString::fromLatin1("TechDraw_ExtensionShortenLine"));
1680

1681
    _pcAction = pcAction;
1682
    languageChange();
1683

1684
    pcAction->setIcon(p1->icon());
1685
    int defaultId = 0;
1686
    pcAction->setProperty("defaultAction", QVariant(defaultId));
1687

1688
    return pcAction;
1689
}
1690

1691
void CmdTechDrawExtendShortenLineGroup::languageChange()
1692
{
1693
    Command::languageChange();
1694

1695
    if (!_pcAction)
1696
        return;
1697
    Gui::ActionGroup* pcAction = qobject_cast<Gui::ActionGroup*>(_pcAction);
1698
    QList<QAction*> a = pcAction->actions();
1699

1700
    QAction* arc1 = a[0];
1701
    arc1->setText(QApplication::translate("CmdTechDrawExtensionExtendLine", "Extend Line"));
1702
    arc1->setToolTip(QApplication::translate(
1703
        "CmdTechDrawExtensionExtendLine", "Extend a cosmetic line or centerline at both ends:<br>\
1704
- Specify the delta distance (optional)<br>\
1705
- Select a single line<br>\
1706
- Click this tool"));
1707
    arc1->setStatusTip(arc1->text());
1708
    QAction* arc2 = a[1];
1709
    arc2->setText(QApplication::translate("CmdTechDrawExtensionShortenLine", "Shorten Line"));
1710
    arc2->setToolTip(QApplication::translate(
1711
        "CmdTechDrawExtensionShortenLine", "Shorten a cosmetic line or centerline at both ends:<br>\
1712
- Specify the delta distance (optional)<br>\
1713
- Select a single line<br>\
1714
- Click this tool"));
1715
    arc2->setStatusTip(arc2->text());
1716
}
1717

1718
bool CmdTechDrawExtendShortenLineGroup::isActive()
1719
{
1720
    bool havePage = DrawGuiUtil::needPage(this);
1721
    bool haveView = DrawGuiUtil::needView(this, true);
1722
    return (havePage && haveView);
1723
}
1724

1725
//===========================================================================
1726
// TechDraw_ExtensionAreaAnnotation
1727
//===========================================================================
1728

1729
DEF_STD_CMD_A(CmdTechDrawExtensionAreaAnnotation)
1730

1731
CmdTechDrawExtensionAreaAnnotation::CmdTechDrawExtensionAreaAnnotation()
1732
    : Command("TechDraw_ExtensionAreaAnnotation")
1733
{
1734
    sAppModule = "TechDraw";
1735
    sGroup = QT_TR_NOOP("TechDraw");
1736
    sMenuText = QT_TR_NOOP("Calculate the area of selected faces");
1737
    sToolTipText = QT_TR_NOOP("Select several faces<br>\
1738
    - click this tool");
1739
    sWhatsThis = "TechDraw_ExtensionAreaAnnotation";
1740
    sStatusTip = sToolTipText;
1741
    sPixmap = "TechDraw_ExtensionAreaAnnotation";
1742
}
1743

1744
void CmdTechDrawExtensionAreaAnnotation::activated(int iMsg)
1745
// calculate the area of selected faces, create output in a balloon
1746
{
1747
    Q_UNUSED(iMsg);
1748
    std::vector<Gui::SelectionObject> selection;
1749
    TechDraw::DrawViewPart* objFeat;
1750
    if (!_checkSel(this, selection, objFeat, QT_TRANSLATE_NOOP("Command","TechDraw calculate selected area")))
1751
        return;
1752

1753
    // we must have at least 1 face in the selection
1754
    const std::vector<std::string> subNamesAll = selection[0].getSubNames();
1755
    std::vector<std::string> subNames;
1756
    for (auto& name : subNamesAll) {
1757
        std::string geomType = DrawUtil::getGeomTypeFromName(name);
1758
        if (geomType == "Face") {
1759
            subNames.push_back(name);
1760
        }
1761
    }
1762

1763
    if (subNames.empty()) {
1764
        QMessageBox::warning(Gui::getMainWindow(),
1765
                             QObject::tr("Incorrect selection"),
1766
                             QObject::tr("No faces in selection."));
1767
        return;
1768
    }
1769

1770
    // we have at least 1 face
1771
    Base::Vector3d center;
1772
    double totalArea = 0.0;
1773
    for (const std::string& name : subNames) {
1774
        TechDraw::FacePtr face = objFeat->getFace(name);
1775
        if (!face) {
1776
            continue;
1777
        }
1778

1779
        GProp_GProps faceProps;
1780
        BRepGProp::SurfaceProperties(face->toOccFace(), faceProps);
1781

1782
        double faceArea = faceProps.Mass();
1783
        totalArea += faceArea;
1784
        center += faceArea*DrawUtil::toVector3d(faceProps.CentreOfMass());
1785
    }
1786
    if (totalArea > 0.0) {
1787
        center /= totalArea;
1788
    }
1789

1790
    // if area calculation was successful, start the command
1791
    Gui::Command::openCommand(QT_TRANSLATE_NOOP("Command", "Calculate Face Area"));
1792
    // at first we create the balloon
1793
    std::string balloonName = _createBalloon(this, objFeat);
1794
    TechDraw::DrawViewBalloon* balloon = nullptr;
1795
    balloon = dynamic_cast<TechDraw::DrawViewBalloon*>(
1796
        this->getDocument()->getObject(balloonName.c_str()));
1797
    if (!balloon)
1798
        throw Base::TypeError("CmdTechDrawNewBalloon - balloon not found\n");
1799
    // the balloon has been created successfully
1800

1801
    // calculate needed variables
1802
    double scale = objFeat->getScale();
1803
    center = DrawUtil::invertY(center/scale);
1804
    double scale2 = scale * scale;
1805
    totalArea = totalArea / scale2;//convert from view scale to internal mm2
1806

1807
    //make area unit-aware
1808
    Base::Quantity asQuantity;
1809
    asQuantity.setValue(totalArea);
1810
    asQuantity.setUnit(Base::Unit::Area);
1811

1812
    QString qUserString = asQuantity.getUserString();
1813
    if (qUserString.endsWith(QString::fromUtf8("^2"))) {
1814
        qUserString.chop(2);
1815
        qUserString.append(QString::fromUtf8("²"));
1816
    }
1817
    std::string sUserString = Base::Tools::toStdString(qUserString);
1818

1819
    // set the attributes in the data tab's fields
1820
    //    balloon->SourceView.setValue(objFeat);
1821
    balloon->BubbleShape.setValue("Rectangle");
1822
    balloon->EndType.setValue("None");
1823
    balloon->KinkLength.setValue(0.0);
1824
    balloon->X.setValue(center.x);
1825
    balloon->Y.setValue(center.y);
1826
    balloon->OriginX.setValue(center.x);
1827
    balloon->OriginY.setValue(center.y);
1828
    balloon->ScaleType.setValue("Page");
1829
    balloon->Text.setValue(sUserString);
1830
    // look for the ballons's view provider
1831
    TechDraw::DrawPage* page = objFeat->findParentPage();
1832
    Gui::Document* guiDoc = Gui::Application::Instance->getDocument(page->getDocument());
1833
    auto viewProvider = static_cast<ViewProviderBalloon*>(guiDoc->getViewProvider(balloon));
1834
    if (viewProvider) {
1835
        // view provider successfully found,
1836
        // set the attributes in the view tab's fields
1837
        viewProvider->Fontsize.setValue(2.0);
1838
        viewProvider->LineWidth.setValue(0.75);
1839
        viewProvider->LineVisible.setValue(false);
1840
        viewProvider->Color.setValue(App::Color(1.0f, 0.0f, 0.0f));
1841
    }
1842
    Gui::Command::commitCommand();
1843
    objFeat->touch(true);
1844
    Gui::Command::updateActive();
1845
}
1846

1847
bool CmdTechDrawExtensionAreaAnnotation::isActive()
1848
{
1849
    bool havePage = DrawGuiUtil::needPage(this);
1850
    bool haveView = DrawGuiUtil::needView(this);
1851
    return (havePage && haveView);
1852
}
1853

1854
//===========================================================================
1855
// TechDraw_ExtensionArcLengthAnnotation
1856
//===========================================================================
1857

1858
DEF_STD_CMD_A(CmdTechDrawExtensionArcLengthAnnotation)
1859

1860
CmdTechDrawExtensionArcLengthAnnotation::CmdTechDrawExtensionArcLengthAnnotation()
1861
    : Command("TechDraw_ExtensionArcLengthAnnotation")
1862
{
1863
    sAppModule = "TechDraw";
1864
    sGroup = QT_TR_NOOP("TechDraw");
1865
    sMenuText = QT_TR_NOOP("Calculate the arc length of selected edges");
1866
    sToolTipText = QT_TR_NOOP("Select several edges<br>\
1867
    - click this tool");
1868
    sWhatsThis = "TechDraw_ExtensionArcLengthAnnotation";
1869
    sStatusTip = sToolTipText;
1870
    sPixmap = "TechDraw_ExtensionArcLengthAnnotation";
1871
}
1872

1873
void CmdTechDrawExtensionArcLengthAnnotation::activated(int iMsg)
1874
// Calculate the arc length of selected edge and create a balloon holding the datum
1875
{
1876
    Q_UNUSED(iMsg);
1877

1878
    std::vector<Gui::SelectionObject> selection;
1879
    TechDraw::DrawViewPart *objFeat;
1880
    if (!_checkSel(this, selection, objFeat, QT_TRANSLATE_NOOP("Command", "TechDraw calculate selected arc length"))) {
1881
        return;
1882
    }
1883

1884
    // Collect all edges in the selection
1885
    std::vector<std::string> subNames;
1886
    for (auto &name : selection[0].getSubNames()) {
1887
        if (DrawUtil::getGeomTypeFromName(name) == "Edge") {
1888
            subNames.push_back(name);
1889
        }
1890
    }
1891

1892
    if (subNames.empty()) {
1893
        QMessageBox::warning(Gui::getMainWindow(),
1894
                             QObject::tr("Incorrect selection"),
1895
                             QObject::tr("No edges in selection."));
1896
        return;
1897
    }
1898

1899
    // Now we have at least one edge
1900
    std::vector<double> lengths(subNames.size());
1901
    double totalLength = 0.0;
1902
    size_t i;
1903
    for (i = 0; i < subNames.size(); ++i) {
1904
        lengths[i] = totalLength;
1905
        TechDraw::BaseGeomPtr edge = objFeat->getEdge(subNames[i]);
1906
        if (!edge) {
1907
            continue;
1908
        }
1909

1910
        GProp_GProps edgeProps;
1911
        BRepGProp::LinearProperties(edge->getOCCEdge(), edgeProps);
1912

1913
        totalLength += edgeProps.Mass();
1914
        lengths[i] = totalLength;
1915
    }
1916

1917
    // We have calculated the length, let's start the command
1918
    Gui::Command::openCommand(QT_TRANSLATE_NOOP("Command", "Calculate Edge Length"));
1919

1920
    // First we need to create the balloon
1921
    std::string balloonName = _createBalloon(this, objFeat);
1922
    auto balloon = dynamic_cast<TechDraw::DrawViewBalloon *>(getDocument()->getObject(balloonName.c_str()));
1923
    if (!balloon) {
1924
        throw Base::TypeError("CmdTechDrawNewBalloon - balloon not found\n");
1925
    }
1926

1927
    // Find the edge halving the selected path and the offset from its starting point
1928
    double anchorLength = totalLength*0.5;
1929
    i = 0;
1930
    while (i < lengths.size() && lengths[i] < anchorLength) {
1931
        ++i;
1932
    }
1933
    if (i) {
1934
        anchorLength -= lengths[i - 1];
1935
    }
1936

1937
    // As reasonable anchor base point seems the "halving" edge endpoint
1938
    BRepAdaptor_Curve curve(objFeat->getEdge(subNames[i])->getOCCEdge());
1939
    gp_Pnt midPoint;
1940
    curve.D0(curve.LastParameter(), midPoint);
1941

1942
    // Now try to get the real path center which lies anchorLength from edge start point
1943
    GCPnts_AbscissaPoint abscissa(Precision::Confusion(), curve, anchorLength, curve.FirstParameter());
1944
    if (abscissa.IsDone()) {
1945
        curve.D0(abscissa.Parameter(), midPoint);
1946
    }
1947

1948
    double scale = objFeat->getScale();
1949
    Base::Vector3d anchor = DrawUtil::invertY(DrawUtil::toVector3d(midPoint)/scale);
1950
    totalLength /= scale;
1951

1952
    // Use virtual dimension view helper to format resulting value
1953
    TechDraw::DrawViewDimension helperDim;
1954
    std::string valueStr = helperDim.formatValue(totalLength,
1955
                                                 QString::fromUtf8(helperDim.FormatSpec.getStrValue().data()),
1956
                                                 helperDim.isMultiValueSchema() ? 0 : 1);
1957
    balloon->Text.setValue("◠ " + valueStr);
1958

1959
    // Set balloon format to be referencing dimension-like
1960
    int stdStyle = Preferences::getPreferenceGroup("Dimensions")->GetInt("StandardAndStyle",
1961
                       ViewProviderDimension::STD_STYLE_ISO_ORIENTED);
1962
    bool asmeStyle = stdStyle == ViewProviderDimension::STD_STYLE_ASME_INLINED
1963
                     || stdStyle == ViewProviderDimension::STD_STYLE_ASME_REFERENCING;
1964
    balloon->BubbleShape.setValue(asmeStyle ? "None" : "Line");
1965
    balloon->EndType.setValue(Preferences::getPreferenceGroup("Dimensions")->GetInt("ArrowStyle", 0));
1966
    balloon->OriginX.setValue(anchor.x);
1967
    balloon->OriginY.setValue(anchor.y);
1968

1969
    // Set balloon label position a bit upwards and to the right, as QGSPage::createBalloon does
1970
    double textOffset = 20.0/scale;
1971
    balloon->X.setValue(anchor.x + textOffset);
1972
    balloon->Y.setValue(anchor.y + textOffset);
1973

1974
    // Adjust the kink length accordingly to the standard used
1975
    auto viewProvider = dynamic_cast<ViewProviderBalloon *>(Gui::Application::Instance->getViewProvider(balloon));
1976
    if (viewProvider) {
1977
        balloon->KinkLength.setValue((asmeStyle ? 12.0 : 1.0)*viewProvider->LineWidth.getValue());
1978
    }
1979

1980
    // Close the command and update the view
1981
    Gui::Command::commitCommand();
1982
    objFeat->touch(true);
1983
    Gui::Command::updateActive();
1984
}
1985

1986
bool CmdTechDrawExtensionArcLengthAnnotation::isActive()
1987
{
1988
    bool havePage = DrawGuiUtil::needPage(this);
1989
    bool haveView = DrawGuiUtil::needView(this);
1990
    return (havePage && haveView);
1991
}
1992

1993
//===========================================================================
1994
// internal helper routines
1995
//===========================================================================
1996
namespace TechDrawGui
1997
{
1998

1999
LineFormat& _getActiveLineAttributes()
2000
{
2001
    static TechDraw::LineFormat attributes;
2002
    return attributes;
2003
}
2004

2005
std::string _createBalloon(Gui::Command* cmd, TechDraw::DrawViewPart* objFeat)
2006
// create a new balloon, return its name as string
2007
{
2008
    std::string featName;
2009
    TechDraw::DrawPage* page = objFeat->findParentPage();
2010
    Gui::Document* guiDoc = Gui::Application::Instance->getDocument(page->getDocument());
2011
    ViewProviderPage* pageVP = dynamic_cast<ViewProviderPage*>(guiDoc->getViewProvider(page));
2012
    if (pageVP) {
2013
        QGSPage* scenePage = pageVP->getQGSPage();
2014
        featName = scenePage->getDrawPage()->getDocument()->getUniqueObjectName("Balloon");
2015
        std::string pageName = scenePage->getDrawPage()->getNameInDocument();
2016
        cmd->doCommand(cmd->Doc,
2017
                       "App.activeDocument().addObject('TechDraw::DrawViewBalloon', '%s')",
2018
                       featName.c_str());
2019
        cmd->doCommand(cmd->Doc, "App.activeDocument().%s.SourceView = (App.activeDocument().%s)",
2020
                       featName.c_str(), objFeat->getNameInDocument());
2021

2022
        cmd->doCommand(cmd->Doc, "App.activeDocument().%s.addView(App.activeDocument().%s)",
2023
                       pageName.c_str(), featName.c_str());
2024
    }
2025
    return featName;
2026
}
2027

2028
bool _checkSel(Gui::Command* cmd, std::vector<Gui::SelectionObject>& selection,
2029
               TechDraw::DrawViewPart*& objFeat, std::string message)
2030
{
2031
    // check selection of getSelectionEx() and selection[0].getObject()
2032
    selection = cmd->getSelection().getSelectionEx();
2033
    if (selection.empty()) {
2034
        // message is translated in caller
2035
        QMessageBox::warning(Gui::getMainWindow(), QString::fromUtf8(message.c_str()),
2036
                             QObject::tr("Selection is empty"));
2037
        return false;
2038
    }
2039

2040
    objFeat = dynamic_cast<TechDraw::DrawViewPart*>(selection[0].getObject());
2041
    if (!objFeat) {
2042
        QMessageBox::warning(Gui::getMainWindow(), QString::fromUtf8(message.c_str()),
2043
                             QObject::tr("No object selected"));
2044
        return false;
2045
    }
2046

2047
    return true;
2048
}
2049

2050
//! return the vertices in the selection as [Base::Vector3d] in App coords -
2051
//! inverted, unrotated and unscaled
2052
std::vector<Base::Vector3d> _getVertexPoints(std::vector<std::string> SubNames,
2053
                                             TechDraw::DrawViewPart* objFeat)
2054
{
2055
    std::vector<Base::Vector3d> vertexPoints;
2056
    for (const std::string& Name : SubNames) {
2057
        std::string GeoType = TechDraw::DrawUtil::getGeomTypeFromName(Name);
2058
        if (GeoType == "Vertex") {
2059
            int GeoId = TechDraw::DrawUtil::getIndexFromName(Name);
2060
            TechDraw::VertexPtr vert = objFeat->getProjVertexByIndex(GeoId);
2061
            Base::Vector3d onePoint = DU::toAppSpace(*objFeat, vert->point());
2062
            vertexPoints.push_back(onePoint);
2063
        }
2064
    }
2065
    return vertexPoints;
2066
}
2067

2068
//! get angle between x-axis and the vector from center to point.
2069
//! result is [0, 360]
2070
float _getAngle(Base::Vector3d center, Base::Vector3d point)
2071
{
2072
    Base::Vector3d vecCP = point - center;
2073
    double angle = DU::angleWithX(vecCP) * 180.0 / M_PI;
2074
    return angle;
2075
}
2076

2077
Base::Vector3d _circleCenter(Base::Vector3d p1, Base::Vector3d p2, Base::Vector3d p3)
2078
{
2079
    Base::Vector2d v1(p1.x, p1.y);
2080
    Base::Vector2d v2(p2.x, p2.y);
2081
    Base::Vector2d v3(p3.x, p3.y);
2082
    Base::Vector2d c = Part::Geom2dCircle::getCircleCenter(v1, v2, v3);
2083
    return Base::Vector3d(c.x, c.y, 0.0);
2084
}
2085

2086
void _createThreadCircle(std::string Name, TechDraw::DrawViewPart* objFeat, float factor)
2087
{
2088
    // create the 3/4 arc symbolizing a thread from top seen
2089
    double scale = objFeat->getScale();
2090
    int GeoId = TechDraw::DrawUtil::getIndexFromName(Name);
2091
    TechDraw::BaseGeomPtr geom = objFeat->getGeomByIndex(GeoId);
2092
    std::string GeoType = TechDraw::DrawUtil::getGeomTypeFromName(Name);
2093

2094
    if (GeoType == "Edge" && geom->getGeomType() == TechDraw::CIRCLE) {
2095
        TechDraw::CirclePtr cgen = std::static_pointer_cast<TechDraw::Circle>(geom);
2096
        Base::Vector3d center = cgen->center;
2097
        float radius = cgen->radius;
2098
        TechDraw::BaseGeomPtr threadArc =
2099
            std::make_shared<TechDraw::AOC>(center / scale, radius * factor / scale, 255.0, 165.0);
2100
        std::string arcTag = objFeat->addCosmeticEdge(threadArc);
2101
        TechDraw::CosmeticEdge* arc = objFeat->getCosmeticEdge(arcTag);
2102
        _setLineAttributes(arc);
2103
    }
2104
}
2105

2106
void _createThreadLines(std::vector<std::string> SubNames, TechDraw::DrawViewPart* objFeat,
2107
                        float factor)
2108
{
2109
    // create symbolizing lines of a thread from the side seen
2110
    std::string GeoType0 = TechDraw::DrawUtil::getGeomTypeFromName(SubNames[0]);
2111
    std::string GeoType1 = TechDraw::DrawUtil::getGeomTypeFromName(SubNames[1]);
2112
    if ((GeoType0 == "Edge") && (GeoType1 == "Edge")) {
2113
        int GeoId0 = TechDraw::DrawUtil::getIndexFromName(SubNames[0]);
2114
        int GeoId1 = TechDraw::DrawUtil::getIndexFromName(SubNames[1]);
2115
        TechDraw::BaseGeomPtr geom0 = objFeat->getGeomByIndex(GeoId0);
2116
        TechDraw::BaseGeomPtr geom1 = objFeat->getGeomByIndex(GeoId1);
2117
        if (geom0->getGeomType() != TechDraw::GENERIC || geom1->getGeomType() != TechDraw::GENERIC) {
2118
            QMessageBox::warning(Gui::getMainWindow(), QObject::tr("TechDraw Thread Hole Side"),
2119
                                 QObject::tr("Please select two straight lines"));
2120
            return;
2121
        }
2122

2123
        TechDraw::GenericPtr line0 = std::static_pointer_cast<TechDraw::Generic>(geom0);
2124
        TechDraw::GenericPtr line1 = std::static_pointer_cast<TechDraw::Generic>(geom1);
2125
        // start and end points are scaled,rotated and inverted (CSRIx). We need to
2126
        // uninvert the points so the canonicalPoint math works correctly.
2127
        Base::Vector3d start0 = DU::invertY(line0->getStartPoint());
2128
        Base::Vector3d end0 = DU::invertY(line0->getEndPoint());
2129
        Base::Vector3d start1 = DU::invertY(line1->getStartPoint());
2130
        Base::Vector3d end1 = DU::invertY(line1->getEndPoint());
2131
        // convert start and end to unscaled, unrotated.
2132
        start0 = CosmeticVertex::makeCanonicalPoint(objFeat, start0);
2133
        start1 = CosmeticVertex::makeCanonicalPoint(objFeat, start1);
2134
        end0 = CosmeticVertex::makeCanonicalPoint(objFeat, end0);
2135
        end1 = CosmeticVertex::makeCanonicalPoint(objFeat, end1);
2136
        if (DrawUtil::circulation(start0, end0, start1)
2137
            != DrawUtil::circulation(end0, end1, start1)) {
2138
            Base::Vector3d help1 = start1;
2139
            Base::Vector3d help2 = end1;
2140
            start1 = help2;
2141
            end1 = help1;
2142
        }
2143
        float kernelDiam = (start1 - start0).Length();
2144
        float kernelFactor = (kernelDiam * factor - kernelDiam) / 2;
2145
        Base::Vector3d delta = (start1 - start0).Normalize() * kernelFactor;
2146
        // addCosmeticEdge(pt1, pt2) inverts the points before creating the edge
2147
        std::string line0Tag =
2148
            objFeat->addCosmeticEdge(start0 - delta, end0 - delta);
2149
        std::string line1Tag =
2150
            objFeat->addCosmeticEdge(start1 + delta, end1 + delta);
2151
        TechDraw::CosmeticEdge* cosTag0 = objFeat->getCosmeticEdge(line0Tag);
2152
        TechDraw::CosmeticEdge* cosTag1 = objFeat->getCosmeticEdge(line1Tag);
2153
        _setLineAttributes(cosTag0);
2154
        _setLineAttributes(cosTag1);
2155
    }
2156
}
2157

2158
void _setLineAttributes(TechDraw::CosmeticEdge* cosEdge)
2159
{
2160
    // set line attributes of a cosmetic edge
2161
    cosEdge->m_format.setStyle(_getActiveLineAttributes().getStyle());
2162
    cosEdge->m_format.setWidth(_getActiveLineAttributes().getWidth());
2163
    cosEdge->m_format.setColor(_getActiveLineAttributes().getColor());
2164
    cosEdge->m_format.setLineNumber(_getActiveLineAttributes().getLineNumber());
2165
}
2166

2167
void _setLineAttributes(TechDraw::CenterLine* cosEdge)
2168
{
2169
    // set line attributes of a cosmetic edge
2170
    cosEdge->m_format.m_style = _getActiveLineAttributes().getStyle();
2171
    cosEdge->m_format.m_weight = _getActiveLineAttributes().getWidth();
2172
    cosEdge->m_format.m_color = _getActiveLineAttributes().getColor();
2173
    cosEdge->m_format.setLineNumber(_getActiveLineAttributes().getLineNumber());
2174
}
2175

2176
void _setLineAttributes(TechDraw::CosmeticEdge* cosEdge, int style, float weight, App::Color color)
2177
{
2178
    // set line attributes of a cosmetic edge
2179
    cosEdge->m_format.m_style = _getActiveLineAttributes().getStyle();
2180
    cosEdge->m_format.m_weight = weight;
2181
    cosEdge->m_format.m_color = color;
2182
    cosEdge->m_format.setLineNumber(style);
2183
}
2184

2185
void _setLineAttributes(TechDraw::CenterLine* cosEdge, int style, float weight, App::Color color)
2186
{
2187
    // set line attributes of a centerline
2188
    cosEdge->m_format.m_style = _getActiveLineAttributes().getStyle();
2189
    cosEdge->m_format.m_weight = weight;
2190
    cosEdge->m_format.m_color = color;
2191
    cosEdge->m_format.setLineNumber(style);
2192
}
2193
}// namespace TechDrawGui
2194

2195
//------------------------------------------------------------------------------
2196
void CreateTechDrawCommandsExtensions()
2197
{
2198
    Gui::CommandManager& rcCmdMgr = Gui::Application::Instance->commandManager();
2199

2200
    rcCmdMgr.addCommand(new CmdTechDrawExtensionSelectLineAttributes());
2201
    rcCmdMgr.addCommand(new CmdTechDrawExtendShortenLineGroup());
2202
    rcCmdMgr.addCommand(new CmdTechDrawExtensionExtendLine());
2203
    rcCmdMgr.addCommand(new CmdTechDrawExtensionShortenLine());
2204
    rcCmdMgr.addCommand(new CmdTechDrawExtensionLockUnlockView());
2205
    rcCmdMgr.addCommand(new CmdTechDrawExtensionChangeLineAttributes());
2206
    rcCmdMgr.addCommand(new CmdTechDrawExtensionCircleCenterLinesGroup());
2207
    rcCmdMgr.addCommand(new CmdTechDrawExtensionCircleCenterLines());
2208
    rcCmdMgr.addCommand(new CmdTechDrawExtensionHoleCircle());
2209
    rcCmdMgr.addCommand(new CmdTechDrawExtensionVertexAtIntersection());
2210
    rcCmdMgr.addCommand(new CmdTechDrawExtensionDrawCirclesGroup());
2211
    rcCmdMgr.addCommand(new CmdTechDrawExtensionDrawCosmCircle());
2212
    rcCmdMgr.addCommand(new CmdTechDrawExtensionDrawCosmArc());
2213
    rcCmdMgr.addCommand(new CmdTechDrawExtensionDrawCosmCircle3Points());
2214
    rcCmdMgr.addCommand(new CmdTechDrawExtensionLinePPGroup());
2215
    rcCmdMgr.addCommand(new CmdTechDrawExtensionLineParallel());
2216
    rcCmdMgr.addCommand(new CmdTechDrawExtensionLinePerpendicular());
2217
    rcCmdMgr.addCommand(new CmdTechDrawExtensionThreadsGroup());
2218
    rcCmdMgr.addCommand(new CmdTechDrawExtensionThreadHoleSide());
2219
    rcCmdMgr.addCommand(new CmdTechDrawExtensionThreadBoltSide());
2220
    rcCmdMgr.addCommand(new CmdTechDrawExtensionThreadHoleBottom());
2221
    rcCmdMgr.addCommand(new CmdTechDrawExtensionThreadBoltBottom());
2222
    rcCmdMgr.addCommand(new CmdTechDrawExtensionAreaAnnotation());
2223
    rcCmdMgr.addCommand(new CmdTechDrawExtensionArcLengthAnnotation());
2224
}
2225

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.