FreeCAD

Форк
0
/
DlgExtrusion.cpp 
785 строк · 27.0 Кб
1
/***************************************************************************
2
 *   Copyright (c) 2008 Werner Mayer <wmayer[at]users.sourceforge.net>     *
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 <BRepAdaptor_Curve.hxx>
26
# include <BRep_Tool.hxx>
27
# include <Precision.hxx>
28
# include <ShapeExtend_Explorer.hxx>
29
# include <TopExp_Explorer.hxx>
30
# include <TopoDS.hxx>
31
# include <TopTools_HSequenceOfShape.hxx>
32
# include <QKeyEvent>
33
# include <QMessageBox>
34
#endif
35

36
#include <App/Application.h>
37
#include <App/Document.h>
38
#include <App/DocumentObject.h>
39
#include <App/Link.h>
40
#include <App/Part.h>
41
#include <Base/UnitsApi.h>
42
#include <Gui/Application.h>
43
#include <Gui/BitmapFactory.h>
44
#include <Gui/Command.h>
45
#include <Gui/Document.h>
46
#include <Gui/Utilities.h>
47
#include <Gui/ViewProvider.h>
48
#include <Gui/WaitCursor.h>
49

50
#include "ui_DlgExtrusion.h"
51
#include "DlgExtrusion.h"
52

53

54
FC_LOG_LEVEL_INIT("Part",true,true)
55

56
using namespace PartGui;
57

58
class DlgExtrusion::EdgeSelection : public Gui::SelectionFilterGate
59
{
60
public:
61
    bool canSelect;
62

63
    EdgeSelection()
64
        : Gui::SelectionFilterGate(nullPointer())
65
    {
66
        canSelect = false;
67
    }
68
    bool allow(App::Document* /*pDoc*/, App::DocumentObject* pObj, const char* sSubName) override
69
    {
70
        this->canSelect = false;
71

72
        if (!sSubName || sSubName[0] == '\0')
73
            return false;
74
        std::string element(sSubName);
75
        if (element.substr(0,4) != "Edge")
76
            return false;
77
        Part::TopoShape part = Part::Feature::getTopoShape(pObj);
78
        if (part.isNull()) {
79
            return false;
80
        }
81
        try {
82
            TopoDS_Shape sub = Part::Feature::getTopoShape(pObj, sSubName, true /*need element*/).getShape();
83
            if (!sub.IsNull() && sub.ShapeType() == TopAbs_EDGE) {
84
                const TopoDS_Edge& edge = TopoDS::Edge(sub);
85
                BRepAdaptor_Curve adapt(edge);
86
                if (adapt.GetType() == GeomAbs_Line) {
87
                    this->canSelect = true;
88
                    return true;
89
                }
90
            }
91
        }
92
        catch (...) {
93
        }
94

95
        return false;
96
    }
97
};
98

99
DlgExtrusion::DlgExtrusion(QWidget* parent, Qt::WindowFlags fl)
100
  : QDialog(parent, fl), ui(new Ui_DlgExtrusion), filter(nullptr)
101
{
102
    ui->setupUi(this);
103
    setupConnections();
104

105
    ui->statusLabel->clear();
106
    ui->dirX->setDecimals(Base::UnitsApi::getDecimals());
107
    ui->dirY->setDecimals(Base::UnitsApi::getDecimals());
108
    ui->dirZ->setDecimals(Base::UnitsApi::getDecimals());
109
    ui->spinLenFwd->setUnit(Base::Unit::Length);
110
    ui->spinLenFwd->setValue(10.0);
111
    ui->spinLenRev->setUnit(Base::Unit::Length);
112
    ui->spinTaperAngle->setUnit(Base::Unit::Angle);
113
    ui->spinTaperAngle->setUnit(Base::Unit::Angle);
114
    findShapes();
115

116
    Gui::ItemViewSelection sel(ui->treeWidget);
117
    sel.applyFrom(Gui::Selection().getObjectsOfType(Part::Feature::getClassTypeId()));
118
    sel.applyFrom(Gui::Selection().getObjectsOfType(App::Link::getClassTypeId()));
119
    sel.applyFrom(Gui::Selection().getObjectsOfType(App::Part::getClassTypeId()));
120

121
    this->onDirModeChanged();
122
    ui->spinLenFwd->selectAll();
123
    // Make sure that the spin box has the focus to get key events
124
    // Calling setFocus() directly doesn't work because the spin box is not
125
    // yet visible.
126
    QMetaObject::invokeMethod(ui->spinLenFwd, "setFocus", Qt::QueuedConnection);
127

128
    this->autoSolid();
129
}
130

131
/*
132
 *  Destroys the object and frees any allocated resources
133
 */
134
DlgExtrusion::~DlgExtrusion()
135
{
136
    if (filter){
137
        Gui::Selection().rmvSelectionGate();
138
        filter = nullptr;
139
    }
140

141
    // no need to delete child widgets, Qt does it all for us
142
}
143

144
void DlgExtrusion::setupConnections()
145
{
146
    // clang-format off
147
    connect(ui->rbDirModeCustom, &QRadioButton::toggled,
148
            this, &DlgExtrusion::onDirModeCustomToggled);
149
    connect(ui->rbDirModeEdge, &QRadioButton::toggled,
150
            this, &DlgExtrusion::onDirModeEdgeToggled);
151
    connect(ui->rbDirModeNormal, &QRadioButton::toggled,
152
            this, &DlgExtrusion::onDirModeNormalToggled);
153
    connect(ui->btnSelectEdge, &QPushButton::clicked,
154
            this, &DlgExtrusion::onSelectEdgeClicked);
155
    connect(ui->btnX, &QPushButton::clicked,
156
            this, &DlgExtrusion::onButtnoXClicked);
157
    connect(ui->btnY, &QPushButton::clicked,
158
            this, &DlgExtrusion::onButtonYClicked);
159
    connect(ui->btnZ, &QPushButton::clicked,
160
            this, &DlgExtrusion::onButtonZClicked);
161
    connect(ui->chkSymmetric, &QCheckBox::toggled,
162
            this, &DlgExtrusion::onCheckSymmetricToggled);
163
    connect(ui->txtLink, &QLineEdit::textChanged,
164
            this, &DlgExtrusion::onTextLinkTextChanged);
165
    // clang-format on
166
}
167

168
void DlgExtrusion::changeEvent(QEvent *e)
169
{
170
    if (e->type() == QEvent::LanguageChange) {
171
        ui->retranslateUi(this);
172
    }
173
    QDialog::changeEvent(e);
174
}
175

176
void DlgExtrusion::keyPressEvent(QKeyEvent* ke)
177
{
178
    // The extrusion dialog is embedded into a task panel
179
    // which is a parent widget and will handle the event
180
    ke->ignore();
181
}
182

183
void DlgExtrusion::onDirModeCustomToggled(bool on)
184
{
185
    if(on) //this check prevents dual fire of dirmode changed - on radio buttons, one will come on, and other will come off, causing two events.
186
        this->onDirModeChanged();
187
}
188

189
void DlgExtrusion::onDirModeEdgeToggled(bool on)
190
{
191
    if(on)
192
        this->onDirModeChanged();
193
}
194

195
void DlgExtrusion::onDirModeNormalToggled(bool on)
196
{
197
    if(on)
198
        this->onDirModeChanged();
199
}
200

201
void DlgExtrusion::onSelectEdgeClicked()
202
{
203
    if (!filter) {
204
        filter = new EdgeSelection();
205
        Gui::Selection().addSelectionGate(filter);
206
        ui->btnSelectEdge->setText(tr("Selecting..."));
207

208
        //visibility automation
209
        try{
210
            QString code = QString::fromLatin1(
211
                        "import Show\n"
212
                        "tv = Show.TempoVis(App.ActiveDocument, tag= 'PartGui::DlgExtrusion')\n"
213
                        "tv.hide([%1])"
214
                        );
215
            std::vector<App::DocumentObject*>sources = getShapesToExtrude();
216
            QString features_to_hide;
217
            for (App::DocumentObject* obj: sources){
218
                if (!obj)
219
                    continue;
220
                features_to_hide.append(QString::fromLatin1("App.ActiveDocument."));
221
                features_to_hide.append(QString::fromLatin1(obj->getNameInDocument()));
222
                features_to_hide.append(QString::fromLatin1(", \n"));
223
            }
224
            QByteArray code_2 = code.arg(features_to_hide).toLatin1();
225
            Base::Interpreter().runString(code_2.constData());
226
        } catch (Base::PyException &e){
227
            e.ReportException();
228
        }
229
    } else {
230
        Gui::Selection().rmvSelectionGate();
231
        filter = nullptr;
232
        ui->btnSelectEdge->setText(tr("Select"));
233

234
        //visibility automation
235
        try{
236
            Base::Interpreter().runString("del(tv)");
237
        } catch (Base::PyException &e){
238
            e.ReportException();
239
        }
240
    }
241
}
242

243
void DlgExtrusion::onButtnoXClicked()
244
{
245
    Base::Vector3d axis(1.0, 0.0, 0.0);
246
    if ((getDir() - axis).Length() < 1e-7)
247
        axis = axis * (-1);
248
    setDirMode(Part::Extrusion::dmCustom);
249
    setDir(axis);
250
}
251

252
void DlgExtrusion::onButtonYClicked()
253
{
254
    Base::Vector3d axis(0.0, 1.0, 0.0);
255
    if ((getDir() - axis).Length() < 1e-7)
256
        axis = axis * (-1);
257
    setDirMode(Part::Extrusion::dmCustom);
258
    setDir(axis);
259
}
260

261
void DlgExtrusion::onButtonZClicked()
262
{
263
    Base::Vector3d axis(0.0, 0.0, 1.0);
264
    if ((getDir() - axis).Length() < 1e-7)
265
        axis = axis * (-1);
266
    setDirMode(Part::Extrusion::dmCustom);
267
    setDir(axis);
268
}
269

270
void DlgExtrusion::onCheckSymmetricToggled(bool on)
271
{
272
    ui->spinLenRev->setEnabled(!on);
273
}
274

275
void DlgExtrusion::onTextLinkTextChanged(QString)
276
{
277
    this->fetchDir();
278
}
279

280
void DlgExtrusion::onDirModeChanged()
281
{
282
    Part::Extrusion::eDirMode dirMode = this->getDirMode();
283
    ui->dirX->setEnabled(dirMode == Part::Extrusion::dmCustom);
284
    ui->dirY->setEnabled(dirMode == Part::Extrusion::dmCustom);
285
    ui->dirZ->setEnabled(dirMode == Part::Extrusion::dmCustom);
286
    ui->txtLink->setEnabled(dirMode == Part::Extrusion::dmEdge);
287
    this->fetchDir();
288
}
289

290
void DlgExtrusion::onSelectionChanged(const Gui::SelectionChanges& msg)
291
{
292
    if (msg.Type == Gui::SelectionChanges::AddSelection) {
293
        if (filter && filter->canSelect) {
294
            this->setAxisLink(msg.pObjectName, msg.pSubName);
295
            this->setDirMode(Part::Extrusion::dmEdge);
296
        }
297
    }
298
}
299

300
App::DocumentObject& DlgExtrusion::getShapeToExtrude() const
301
{
302
    std::vector<App::DocumentObject*> objs = this->getShapesToExtrude();
303
    if (objs.empty())
304
        throw Base::ValueError("No shapes selected");
305
    return *(objs[0]);
306
}
307

308
void DlgExtrusion::fetchDir()
309
{
310
    bool lengths_are_at_defaults =
311
            (fabs(ui->spinLenFwd->value().getValue() - 10.0) < 1e-7)
312
            && (fabs(ui->spinLenRev->value().getValue() - 0.0) < 1e-7);
313
    bool lengths_are_zero =
314
            (fabs(ui->spinLenFwd->value().getValue() - 0.0) < 1e-7)
315
            && (fabs(ui->spinLenRev->value().getValue() - 0.0) < 1e-7);
316

317
    try{
318
        Base::Vector3d pos, dir;
319
        bool fetched = false;
320
        bool dir_has_valid_magnitude = false;
321
        if(this->getDirMode() == Part::Extrusion::dmEdge){
322
            App::PropertyLinkSub lnk; this->getAxisLink(lnk);
323
            fetched = Part::Extrusion::fetchAxisLink(lnk, pos, dir);
324
            dir_has_valid_magnitude = fetched;
325
        } else if (this->getDirMode() == Part::Extrusion::dmNormal){
326
            App::PropertyLink lnk;
327
            lnk.setValue(&this->getShapeToExtrude());
328
            dir = Part::Extrusion::calculateShapeNormal(lnk);
329
            fetched = true;
330
        }
331
        if (dir_has_valid_magnitude && lengths_are_at_defaults){
332
            ui->spinLenFwd->setValue(0);
333
        } else if (!dir_has_valid_magnitude && lengths_are_zero){
334
            ui->spinLenFwd->setValue(1.0);
335
        }
336
        if (fetched){
337
            this->setDir(dir);
338
        }
339
    } catch (Base::Exception &){
340

341
    } catch (...){
342

343
    }
344
}
345

346
void DlgExtrusion::autoSolid()
347
{
348
    try{
349
        App::DocumentObject* dobj = &this->getShapeToExtrude();
350
        Part::TopoShape shape = Part::Feature::getTopoShape(dobj);
351
        if (shape.isNull()) {
352
            return;
353
        }
354
        TopoDS_Shape sh = shape.getShape();
355
        if (sh.IsNull())
356
            return;
357
        ShapeExtend_Explorer xp;
358
        Handle(TopTools_HSequenceOfShape) leaves = xp.SeqFromCompound(sh, /*recursive= */Standard_True);
359
        int cntClosedWires = 0;
360
        for(int i = 0; i < leaves->Length(); i++){
361
            const TopoDS_Shape &leaf = leaves->Value(i+1);
362
            if (leaf.IsNull())
363
                return;
364
            if (leaf.ShapeType() == TopAbs_WIRE || leaf.ShapeType() == TopAbs_EDGE){
365
                if (BRep_Tool::IsClosed(leaf)){
366
                    cntClosedWires++;
367
                }
368
            }
369
        }
370
        ui->chkSolid->setChecked( cntClosedWires == leaves->Length() );
371
    } catch(...) {
372

373
    }
374
}
375

376
void DlgExtrusion::findShapes()
377
{
378
    App::Document* activeDoc = App::GetApplication().getActiveDocument();
379
    if (!activeDoc)
380
        return;
381
    Gui::Document* activeGui = Gui::Application::Instance->getDocument(activeDoc);
382
    this->document = activeDoc->getName();
383
    this->label = activeDoc->Label.getValue();
384

385
    std::vector<App::DocumentObject*> objs = activeDoc->getObjectsOfType<App::DocumentObject>();
386

387
    for (auto obj : objs) {
388
        Part::TopoShape topoShape = Part::Feature::getTopoShape(obj);
389
        if (topoShape.isNull()) {
390
            continue;
391
        }
392
        TopoDS_Shape shape = topoShape.getShape();
393
        if (shape.IsNull()) continue;
394
        if (canExtrude(shape)) {
395
            QTreeWidgetItem* item = new QTreeWidgetItem(ui->treeWidget);
396
            item->setText(0, QString::fromUtf8(obj->Label.getValue()));
397
            item->setData(0, Qt::UserRole, QString::fromLatin1(obj->getNameInDocument()));
398
            Gui::ViewProvider* vp = activeGui->getViewProvider(obj);
399
            if (vp)
400
                item->setIcon(0, vp->getIcon());
401
        }
402
    }
403
}
404

405
bool DlgExtrusion::canExtrude(const TopoDS_Shape& shape) const
406
{
407
    if (shape.IsNull())
408
        return false;
409
    TopAbs_ShapeEnum type = shape.ShapeType();
410
    if (type == TopAbs_VERTEX || type == TopAbs_EDGE ||
411
        type == TopAbs_WIRE || type == TopAbs_FACE ||
412
        type == TopAbs_SHELL)
413
        return true;
414
    if (type == TopAbs_COMPOUND) {
415
        TopExp_Explorer xp;
416
        xp.Init(shape,TopAbs_SOLID);
417
        while (xp.More()) {
418
            return false;
419
        }
420
        xp.Init(shape,TopAbs_COMPSOLID);
421
        while (xp.More()) {
422
            return false;
423
        }
424

425
        return true;
426
    }
427

428
    return false;
429
}
430

431
void DlgExtrusion::accept()
432
{
433
    try{
434
        apply();
435
        QDialog::accept();
436
    } catch (Base::AbortException&){
437

438
    };
439
}
440

441
void DlgExtrusion::apply()
442
{
443
    try{
444
        if (!validate())
445
            throw Base::AbortException();
446

447
        if (filter) //if still selecting edge - stop. This is important for visibility automation.
448
            this->onSelectEdgeClicked();
449

450
        Gui::WaitCursor wc;
451
        App::Document* activeDoc = App::GetApplication().getDocument(this->document.c_str());
452
        if (!activeDoc) {
453
            QMessageBox::critical(this, windowTitle(),
454
                tr("The document '%1' doesn't exist.").arg(QString::fromUtf8(this->label.c_str())));
455
            return;
456
        }
457
        activeDoc->openTransaction("Extrude");
458

459
        Base::Reference<ParameterGrp> hGrp = App::GetApplication().GetUserParameter()
460
            .GetGroup("BaseApp")->GetGroup("Preferences")->GetGroup("Mod/Part");
461
        bool addBaseName = hGrp->GetBool("AddBaseObjectName", false);
462

463
        std::vector<App::DocumentObject*> objects = this->getShapesToExtrude();
464
        for (App::DocumentObject* sourceObj: objects) {
465
            assert(sourceObj);
466

467
            if (Part::Feature::getTopoShape(sourceObj).isNull()){
468
                FC_ERR("Object " << sourceObj->getFullName()
469
                        << " is not Part object (has no OCC shape). Can't extrude it.");
470
                continue;
471
            }
472

473
            std::string name;
474
            name = sourceObj->getDocument()->getUniqueObjectName("Extrude").c_str();
475
            if (addBaseName) {
476
                //FIXME: implement
477
                //QString baseName = QString::fromLatin1("Extrude_%1").arg(sourceObjectName);
478
                //label = QString::fromLatin1("%1_Extrude").arg((*it)->text(0));
479
            }
480

481
            FCMD_OBJ_DOC_CMD(sourceObj,"addObject('Part::Extrusion','" << name << "')");
482
            auto newObj = sourceObj->getDocument()->getObject(name.c_str());
483

484
            this->writeParametersToFeature(*newObj, sourceObj);
485

486
            Gui::Command::copyVisual(newObj, "ShapeAppearance", sourceObj);
487
            Gui::Command::copyVisual(newObj, "LineColor", sourceObj);
488
            Gui::Command::copyVisual(newObj, "PointColor", sourceObj);
489

490
            FCMD_OBJ_HIDE(sourceObj);
491
        }
492

493
        activeDoc->commitTransaction();
494
        Gui::Command::updateActive();
495
    }
496
    catch (Base::AbortException&){
497
        throw;
498
    }
499
    catch (Base::Exception &err){
500
        QMessageBox::critical(this,
501
                              windowTitle(),
502
                              tr("Creating Extrusion failed.\n%1")
503
                                  .arg(QCoreApplication::translate("Exception", err.what())));
504
        return;
505
    }
506
    catch(...) {
507
        QMessageBox::critical(this, windowTitle(),
508
            tr("Creating Extrusion failed.\n%1").arg(QString::fromUtf8("Unknown error")));
509
        return;
510
    }
511
}
512

513
void DlgExtrusion::reject()
514
{
515
    if (filter) //if still selecting edge - stop.
516
        this->onSelectEdgeClicked();
517

518
    QDialog::reject();
519
}
520

521
Base::Vector3d DlgExtrusion::getDir() const
522
{
523
    return Base::Vector3d(
524
                ui->dirX->value(),
525
                ui->dirY->value(),
526
                ui->dirZ->value());
527
}
528

529
void DlgExtrusion::setDir(Base::Vector3d newDir)
530
{
531
    ui->dirX->setValue(newDir.x);
532
    ui->dirY->setValue(newDir.y);
533
    ui->dirZ->setValue(newDir.z);
534
}
535

536
Part::Extrusion::eDirMode DlgExtrusion::getDirMode() const
537
{
538
    if(ui->rbDirModeCustom->isChecked())
539
        return Part::Extrusion::dmCustom;
540
    if(ui->rbDirModeEdge->isChecked())
541
        return Part::Extrusion::dmEdge;
542
    if(ui->rbDirModeNormal->isChecked())
543
        return Part::Extrusion::dmNormal;
544

545
    //we shouldn't get here...
546
    return Part::Extrusion::dmCustom;
547
}
548

549
void DlgExtrusion::setDirMode(Part::Extrusion::eDirMode newMode)
550
{
551
    ui->rbDirModeCustom->blockSignals(true);
552
    ui->rbDirModeEdge->blockSignals(true);
553
    ui->rbDirModeNormal->blockSignals(true);
554

555
    ui->rbDirModeCustom->setChecked(newMode == Part::Extrusion::dmCustom);
556
    ui->rbDirModeEdge->setChecked(newMode == Part::Extrusion::dmEdge);
557
    ui->rbDirModeNormal->setChecked(newMode == Part::Extrusion::dmNormal);
558

559
    ui->rbDirModeCustom->blockSignals(false);
560
    ui->rbDirModeEdge->blockSignals(false);
561
    ui->rbDirModeNormal->blockSignals(false);
562
    this->onDirModeChanged();
563
}
564

565
void DlgExtrusion::getAxisLink(App::PropertyLinkSub& lnk) const
566
{
567
    QString text = ui->txtLink->text();
568

569
    if (text.length() == 0) {
570
        lnk.setValue(nullptr);
571
    } else {
572
        QStringList parts = text.split(QChar::fromLatin1(':'));
573
        App::DocumentObject* obj = App::GetApplication().getActiveDocument()->getObject(parts[0].toLatin1());
574
        if(!obj){
575
            throw Base::ValueError(tr("Object not found: %1").arg(parts[0]).toUtf8().constData());
576
        }
577
        lnk.setValue(obj);
578
        if (parts.size() == 1) {
579
            return;
580
        } else if (parts.size() == 2) {
581
            std::vector<std::string> subs;
582
            subs.emplace_back(parts[1].toLatin1().constData());
583
            lnk.setValue(obj,subs);
584
        }
585
    }
586

587
}
588

589
void DlgExtrusion::setAxisLink(const App::PropertyLinkSub& lnk)
590
{
591
    if (!lnk.getValue()){
592
        ui->txtLink->clear();
593
        return;
594
    }
595
    if (lnk.getSubValues().size() == 1){
596
        this->setAxisLink(lnk.getValue()->getNameInDocument(), lnk.getSubValues()[0].c_str());
597
    } else {
598
        this->setAxisLink(lnk.getValue()->getNameInDocument(), "");
599
    }
600
}
601

602
void DlgExtrusion::setAxisLink(const char* objname, const char* subname)
603
{
604
    if(objname && strlen(objname) > 0){
605
        QString txt = QString::fromLatin1(objname);
606
        if (subname && strlen(subname) > 0){
607
            txt = txt + QString::fromLatin1(":") + QString::fromLatin1(subname);
608
        }
609
        ui->txtLink->setText(txt);
610
    } else {
611
        ui->txtLink->clear();
612
    }
613
}
614

615
std::vector<App::DocumentObject*> DlgExtrusion::getShapesToExtrude() const
616
{
617
    QList<QTreeWidgetItem *> items = ui->treeWidget->selectedItems();
618
    App::Document* doc = App::GetApplication().getDocument(this->document.c_str());
619
    if (!doc)
620
        throw Base::RuntimeError("Document lost");
621

622
    std::vector<App::DocumentObject*> objects;
623
    for (auto item : items) {
624
        App::DocumentObject* obj = doc->getObject(item->data(0, Qt::UserRole).toString().toLatin1());
625
        if (!obj)
626
            throw Base::RuntimeError("Object not found");
627
        objects.push_back(obj);
628
    }
629
    return objects;
630
}
631

632
bool DlgExtrusion::validate()
633
{
634
    //check source shapes
635
    if (ui->treeWidget->selectedItems().isEmpty()) {
636
        QMessageBox::critical(this, windowTitle(),
637
            tr("No shapes selected for extrusion. Select some, first."));
638
        return false;
639
    }
640

641
    //check axis link
642
    QString errmsg;
643
    bool hasValidAxisLink = false;
644
    try{
645
        App::PropertyLinkSub lnk;
646
        this->getAxisLink(lnk);
647
        Base::Vector3d dir, base;
648
        hasValidAxisLink = Part::Extrusion::fetchAxisLink(lnk, base, dir);
649
    } catch(Base::Exception &err) {
650
        errmsg = QCoreApplication::translate("Exception", err.what());
651
    } catch(Standard_Failure &err) {
652
        errmsg = QString::fromLocal8Bit(err.GetMessageString());
653
    } catch(...) {
654
        errmsg = tr("Unknown error");
655
    }
656
    if (this->getDirMode() == Part::Extrusion::dmEdge && !hasValidAxisLink){
657
        if (errmsg.length() > 0)
658
            QMessageBox::critical(this, windowTitle(), tr("Extrusion direction link is invalid.\n\n%1").arg(errmsg));
659
        else
660
            QMessageBox::critical(this, windowTitle(), tr("Direction mode is to use an edge, but no edge is linked."));
661
        ui->txtLink->setFocus();
662
        return false;
663
    } else if (this->getDirMode() != Part::Extrusion::dmEdge && !hasValidAxisLink){
664
        //axis link is invalid, but it is not required by the mode. We shouldn't complain it's invalid then...
665
        ui->txtLink->clear();
666
    }
667

668
    //check normal
669
    if (this->getDirMode() == Part::Extrusion::dmNormal){
670
        errmsg.clear();
671
        try {
672
            App::PropertyLink lnk;
673
            lnk.setValue(&this->getShapeToExtrude()); //simplified - check only for the first shape.
674
            Part::Extrusion::calculateShapeNormal(lnk);
675
        } catch(Base::Exception &err) {
676
            errmsg = QCoreApplication::translate("Exception", err.what());
677
        } catch(Standard_Failure &err) {
678
            errmsg = QString::fromLocal8Bit(err.GetMessageString());
679
        } catch(...) {
680
            errmsg = QString::fromUtf8("Unknown error");
681
        }
682
        if (errmsg.length() > 0){
683
            QMessageBox::critical(this, windowTitle(), tr("Can't determine normal vector of shape to be extruded. Please use other mode. \n\n(%1)").arg(errmsg));
684
            ui->rbDirModeNormal->setFocus();
685
            return false;
686
        }
687
    }
688

689
    //check axis dir
690
    if (this->getDirMode() == Part::Extrusion::dmCustom){
691
        if(this->getDir().Length() < Precision::Confusion()){
692
            QMessageBox::critical(this, windowTitle(),
693
                tr("Extrusion direction vector is zero-length. It must be non-zero."));
694
            ui->dirX->setFocus();
695
            return false;
696
        }
697
    }
698

699
    //check lengths
700
    if (!ui->chkSymmetric->isChecked()
701
            && fabs(ui->spinLenFwd->value().getValue() + ui->spinLenRev->value().getValue()) < Precision::Confusion()
702
            && ! (fabs(ui->spinLenFwd->value().getValue() - ui->spinLenRev->value().getValue()) < Precision::Confusion())){
703
        QMessageBox::critical(this, windowTitle(),
704
            tr("Total extrusion length is zero (length1 == -length2). It must be nonzero."));
705
        ui->spinLenFwd->setFocus();
706
        return false;
707
    }
708

709
    return true;
710
}
711

712
void DlgExtrusion::writeParametersToFeature(App::DocumentObject &feature, App::DocumentObject* base) const
713
{
714
    Gui::Command::doCommand(Gui::Command::Doc,"f = App.getDocument('%s').getObject('%s')", feature.getDocument()->getName(), feature.getNameInDocument());
715

716
    if (base)
717
        Gui::Command::doCommand(Gui::Command::Doc,"f.Base = App.getDocument('%s').getObject('%s')", base->getDocument()->getName(), base->getNameInDocument());
718

719
    Part::Extrusion::eDirMode dirMode = this->getDirMode();
720
    const char* modestr = Part::Extrusion::eDirModeStrings[dirMode];
721
    Gui::Command::doCommand(Gui::Command::Doc,"f.DirMode = \"%s\"", modestr);
722

723
    if (dirMode == Part::Extrusion::dmCustom){
724
        Base::Vector3d dir = this->getDir();
725
        Gui::Command::doCommand(Gui::Command::Doc, "f.Dir = App.Vector(%.15f, %.15f, %.15f)", dir.x, dir.y, dir.z);
726
    }
727

728
    App::PropertyLinkSub lnk;
729
    this->getAxisLink(lnk);
730
    std::stringstream linkstr;
731
    if (!lnk.getValue()) {
732
        linkstr << "None";
733
    } else {
734
        linkstr << "(App.getDocument(\"" << lnk.getValue()->getDocument()->getName() <<"\")." << lnk.getValue()->getNameInDocument();
735
        linkstr << ", [";
736
        for (const std::string &str: lnk.getSubValues()){
737
            linkstr << "\"" << str << "\"";
738
        }
739
        linkstr << "])";
740
    }
741
    Gui::Command::doCommand(Gui::Command::Doc,"f.DirLink = %s", linkstr.str().c_str());
742

743
    Gui::Command::doCommand(Gui::Command::Doc,"f.LengthFwd = %.15f", ui->spinLenFwd->value().getValue());
744
    Gui::Command::doCommand(Gui::Command::Doc,"f.LengthRev = %.15f", ui->spinLenRev->value().getValue());
745

746
    Gui::Command::doCommand(Gui::Command::Doc,"f.Solid = %s", ui->chkSolid->isChecked() ? "True" : "False");
747
    Gui::Command::doCommand(Gui::Command::Doc,"f.Reversed = %s", ui->chkReversed->isChecked() ? "True" : "False");
748
    Gui::Command::doCommand(Gui::Command::Doc,"f.Symmetric = %s", ui->chkSymmetric->isChecked() ? "True" : "False");
749
    Gui::Command::doCommand(Gui::Command::Doc,"f.TaperAngle = %.15f", ui->spinTaperAngle->value().getValue());
750
    Gui::Command::doCommand(Gui::Command::Doc,"f.TaperAngleRev = %.15f", ui->spinTaperAngleRev->value().getValue());
751
}
752

753

754
// ---------------------------------------
755

756
TaskExtrusion::TaskExtrusion()
757
{
758
    widget = new DlgExtrusion();
759
    addTaskBox(Gui::BitmapFactory().pixmap("Part_Extrude"), widget);
760
}
761

762
bool TaskExtrusion::accept()
763
{
764
    widget->accept();
765
    return (widget->result() == QDialog::Accepted);
766
}
767

768
bool TaskExtrusion::reject()
769
{
770
    widget->reject();
771
    return true;
772
}
773

774
void TaskExtrusion::clicked(int id)
775
{
776
    if (id == QDialogButtonBox::Apply) {
777
        try{
778
            widget->apply();
779
        } catch (Base::AbortException&){
780

781
        };
782
    }
783
}
784

785
#include "moc_DlgExtrusion.cpp"
786

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

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

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

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