FreeCAD

Форк
0
/
CommandSimple.cpp 
493 строки · 18.4 Кб
1
/***************************************************************************
2
 *   Copyright (c) 2002 Jürgen Riegel <juergen.riegel@web.de>              *
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

24
#include "PreCompiled.h"
25
#ifndef _PreComp_
26
# include <QInputDialog>
27
#endif
28

29
#include <App/Document.h>
30
#include <App/DocumentObject.h>
31
#include <App/DocumentObserver.h>
32
#include <Base/Exception.h>
33
#include <Base/Interpreter.h>
34
#include <Gui/Application.h>
35
#include <Gui/CommandT.h>
36
#include <Gui/MainWindow.h>
37
#include <Gui/Selection.h>
38
#include <Gui/SelectionObject.h>
39
#include <Gui/WaitCursor.h>
40

41
#include "DlgPartCylinderImp.h"
42
#include "ShapeFromMesh.h"
43
#include <Mod/Part/App/PartFeature.h>
44

45

46
//===========================================================================
47
// Part_SimpleCylinder
48
//===========================================================================
49
DEF_STD_CMD_A(CmdPartSimpleCylinder)
50

51
CmdPartSimpleCylinder::CmdPartSimpleCylinder()
52
  :Command("Part_SimpleCylinder")
53
{
54
    sAppModule    = "Part";
55
    sGroup        = QT_TR_NOOP("Part");
56
    sMenuText     = QT_TR_NOOP("Create Cylinder...");
57
    sToolTipText  = QT_TR_NOOP("Create a Cylinder");
58
    sWhatsThis    = "Part_SimpleCylinder";
59
    sStatusTip    = sToolTipText;
60
    sPixmap       = "Part_Cylinder_Parametric";
61
}
62

63
void CmdPartSimpleCylinder::activated(int iMsg)
64
{
65
    Q_UNUSED(iMsg);
66
    PartGui::DlgPartCylinderImp dlg(Gui::getMainWindow());
67
    if (dlg.exec()== QDialog::Accepted) {
68
        Base::Vector3d dir = dlg.getDirection();
69
        Base::Vector3d pos = dlg.getPosition();
70
        openCommand(QT_TRANSLATE_NOOP("Command", "Create Part Cylinder"));
71
        doCommand(Doc,"from FreeCAD import Base");
72
        doCommand(Doc,"import Part");
73
        doCommand(Doc,"App.ActiveDocument.addObject(\"Part::Feature\",\"Cylinder\")"
74
                      ".Shape=Part.makeCylinder(%f,%f,"
75
                      "Base.Vector(%f,%f,%f),"
76
                      "Base.Vector(%f,%f,%f))"
77
                     ,dlg.getRadius()
78
                     ,dlg.getLength()
79
                     ,pos.x,pos.y,pos.z
80
                     ,dir.x,dir.y,dir.z);
81
        commitCommand();
82
        updateActive();
83
        doCommand(Gui, "Gui.SendMsgToActiveView(\"ViewFit\")");
84
    }
85
}
86

87
bool CmdPartSimpleCylinder::isActive()
88
{
89
    if (getActiveGuiDocument())
90
        return true;
91
    else
92
        return false;
93
}
94

95

96
//===========================================================================
97
// Part_ShapeFromMesh
98
//===========================================================================
99
DEF_STD_CMD_A(CmdPartShapeFromMesh)
100

101
CmdPartShapeFromMesh::CmdPartShapeFromMesh()
102
  :Command("Part_ShapeFromMesh")
103
{
104
    sAppModule    = "Part";
105
    sGroup        = QT_TR_NOOP("Part");
106
    sMenuText     = QT_TR_NOOP("Create shape from mesh...");
107
    sToolTipText  = QT_TR_NOOP("Create shape from selected mesh object");
108
    sWhatsThis    = "Part_ShapeFromMesh";
109
    sStatusTip    = sToolTipText;
110
    sPixmap       = "Part_Shape_from_Mesh";
111
}
112

113
void CmdPartShapeFromMesh::activated(int iMsg)
114
{
115
    Q_UNUSED(iMsg);
116
    PartGui::ShapeFromMesh dlg(Gui::getMainWindow());
117
    dlg.exec();
118
}
119

120
bool CmdPartShapeFromMesh::isActive()
121
{
122
    Base::Type meshid = Base::Type::fromName("Mesh::Feature");
123
    return Gui::Selection().countObjectsOfType(meshid) > 0;
124
}
125
//===========================================================================
126
// Part_PointsFromMesh
127
//===========================================================================
128
DEF_STD_CMD_A(CmdPartPointsFromMesh)
129

130
CmdPartPointsFromMesh::CmdPartPointsFromMesh()
131
  :Command("Part_PointsFromMesh")
132
{
133
    sAppModule    = "Part";
134
    sGroup        = QT_TR_NOOP("Part");
135
    sMenuText     = QT_TR_NOOP("Create points object from geometry");
136
    sToolTipText  = QT_TR_NOOP("Create selectable points object from selected geometric object");
137
    sWhatsThis    = "Part_PointsFromMesh";
138
    sStatusTip    = sToolTipText;
139
    sPixmap       = "Part_PointsFromMesh";
140
}
141

142
void CmdPartPointsFromMesh::activated(int iMsg)
143
{
144
    Q_UNUSED(iMsg);
145

146
    auto getDefaultDistance = [](Part::Feature* geometry) {
147
        auto bbox = geometry->Shape.getBoundingBox();
148
        int steps{20};
149
        return bbox.CalcDiagonalLength() / steps;
150
    };
151

152
    Base::Type geoid = Base::Type::fromName("App::GeoFeature");
153
    std::vector<App::DocumentObject*> geoms;
154
    geoms = Gui::Selection().getObjectsOfType(geoid);
155

156
    double distance{1.0};
157
    auto found = std::find_if(geoms.begin(), geoms.end(), [](App::DocumentObject* obj) {
158
        return Base::freecad_dynamic_cast<Part::Feature>(obj);
159
    });
160

161
    if (found != geoms.end()) {
162

163
        double defaultDistance = getDefaultDistance(Base::freecad_dynamic_cast<Part::Feature>(*found));
164

165
        double STD_OCC_TOLERANCE = 1e-6;
166

167
        int decimals = Base::UnitsApi::getDecimals();
168
        double tolerance_from_decimals = pow(10., -decimals);
169

170
        double minimal_tolerance = tolerance_from_decimals < STD_OCC_TOLERANCE ? STD_OCC_TOLERANCE : tolerance_from_decimals;
171

172
        bool ok;
173
        distance = QInputDialog::getDouble(Gui::getMainWindow(), QObject::tr("Distance in parameter space"),
174
            QObject::tr("Enter distance:"), defaultDistance, minimal_tolerance, 10.0 * defaultDistance, decimals, &ok, Qt::MSWindowsFixedSizeDialogHint);
175
        if (!ok) {
176
            return;
177
        }
178
    }
179

180
    Gui::WaitCursor wc;
181
    openCommand(QT_TRANSLATE_NOOP("Command", "Points from geometry"));
182

183
    Base::PyGILStateLocker lock;
184
    try {
185
        PyObject* module = PyImport_ImportModule("BasicShapes.Utils");
186
        if (!module) {
187
            throw Py::Exception();
188
        }
189
        Py::Module utils(module, true);
190

191
        for (auto it : geoms) {
192
            Py::Tuple args(2);
193
            args.setItem(0, Py::asObject(it->getPyObject()));
194
            args.setItem(1, Py::Float(distance));
195
            utils.callMemberFunction("showCompoundFromPoints", args);
196
        }
197
    }
198
    catch (Py::Exception&) {
199
        Base::PyException e;
200
        e.ReportException();
201
    }
202

203
    commitCommand();
204
}
205

206
bool CmdPartPointsFromMesh::isActive()
207
{
208
    Base::Type meshid = Base::Type::fromName("App::GeoFeature");
209
    return Gui::Selection().countObjectsOfType(meshid) > 0;
210
}
211

212
//===========================================================================
213
// Part_SimpleCopy
214
//===========================================================================
215
DEF_STD_CMD_A(CmdPartSimpleCopy)
216

217
CmdPartSimpleCopy::CmdPartSimpleCopy()
218
  : Command("Part_SimpleCopy")
219
{
220
    sAppModule    = "Part";
221
    sGroup        = QT_TR_NOOP("Part");
222
    sMenuText     = QT_TR_NOOP("Create simple copy");
223
    sToolTipText  = QT_TR_NOOP("Create a simple non-parametric copy");
224
    sWhatsThis    = "Part_SimpleCopy";
225
    sStatusTip    = sToolTipText;
226
    sPixmap       = "Part_3D_object";
227
}
228

229
static void _copyShape(const char *cmdName, bool resolve,bool needElement=false, bool refine=false) {
230
    Gui::WaitCursor wc;
231
    Gui::Command::openCommand(cmdName);
232
    for(auto &sel : Gui::Selection().getSelectionEx("*", App::DocumentObject::getClassTypeId(),
233
                                                    resolve ? Gui::ResolveMode::OldStyleElement : Gui::ResolveMode::NoResolve)) {
234
        std::map<std::string,App::DocumentObject*> subMap;
235
        auto obj = sel.getObject();
236
        if (!obj)
237
            continue;
238
        if (resolve || !sel.hasSubNames()) {
239
            subMap.emplace("",obj);
240
        }
241
        else {
242
            for(const auto &sub : sel.getSubNames()) {
243
                const char *element = nullptr;
244
                auto sobj = obj->resolve(sub.c_str(),nullptr,nullptr,&element);
245
                if(!sobj) continue;
246
                if(!needElement && element)
247
                    subMap.emplace(sub.substr(0,element-sub.c_str()),sobj);
248
                else
249
                    subMap.emplace(sub,sobj);
250
            }
251
            if(subMap.empty())
252
                continue;
253
        }
254
        auto parentName = Gui::Command::getObjectCmd(obj);
255
        for(auto &v : subMap) {
256
            Gui::Command::doCommand(Gui::Command::Doc,
257
                    "__shape = Part.getShape(%s,'%s',needSubElement=%s,refine=%s)%s\n"
258
                    "App.ActiveDocument.addObject('Part::Feature','%s').Shape=__shape\n"
259
                    "App.ActiveDocument.ActiveObject.Label=%s.Label\n",
260
                        parentName.c_str(), v.first.c_str(),
261
                        needElement ? "True" : "False",
262
                        refine ? "True" : "False",
263
                        needElement ? ".copy()" : "",
264
                        v.second->getNameInDocument(),
265
                        Gui::Command::getObjectCmd(v.second).c_str());
266
            auto newObj = App::GetApplication().getActiveDocument()->getActiveObject();
267
            Gui::Command::copyVisual(newObj, "ShapeAppearance", v.second);
268
            Gui::Command::copyVisual(newObj, "LineColor", v.second);
269
            Gui::Command::copyVisual(newObj, "PointColor", v.second);
270
        }
271
    }
272
    Gui::Command::commitCommand();
273
    Gui::Command::updateActive();
274
}
275

276
void CmdPartSimpleCopy::activated(int iMsg)
277
{
278
    Q_UNUSED(iMsg);
279
    _copyShape("Simple copy",true);
280
}
281

282
bool CmdPartSimpleCopy::isActive()
283
{
284
    return Gui::Selection().hasSelection();
285
}
286

287
//===========================================================================
288
// Part_TransformedCopy
289
//===========================================================================
290
DEF_STD_CMD_A(CmdPartTransformedCopy)
291

292
CmdPartTransformedCopy::CmdPartTransformedCopy()
293
  : Command("Part_TransformedCopy")
294
{
295
    sAppModule    = "Part";
296
    sGroup        = QT_TR_NOOP("Part");
297
    sMenuText     = QT_TR_NOOP("Create transformed copy");
298
    sToolTipText  = QT_TR_NOOP("Create a non-parametric copy with transformed placement");
299
    sWhatsThis    = "Part_TransformCopy";
300
    sStatusTip    = sToolTipText;
301
    sPixmap       = "Part_Transformed_Copy.svg";
302
}
303

304
void CmdPartTransformedCopy::activated(int iMsg)
305
{
306
    Q_UNUSED(iMsg);
307
    _copyShape("Transformed copy",false);
308
}
309

310
bool CmdPartTransformedCopy::isActive()
311
{
312
    return Gui::Selection().hasSelection();
313
}
314

315
//===========================================================================
316
// Part_ElementCopy
317
//===========================================================================
318
DEF_STD_CMD_A(CmdPartElementCopy)
319

320
CmdPartElementCopy::CmdPartElementCopy()
321
  : Command("Part_ElementCopy")
322
{
323
    sAppModule    = "Part";
324
    sGroup        = QT_TR_NOOP("Part");
325
    sMenuText     = QT_TR_NOOP("Create shape element copy");
326
    sToolTipText  = QT_TR_NOOP("Create a non-parametric copy of the selected shape element");
327
    sWhatsThis    = "Part_ElementCopy";
328
    sStatusTip    = sToolTipText;
329
    sPixmap       = "Part_Element_Copy.svg";
330
}
331

332
void CmdPartElementCopy::activated(int iMsg)
333
{
334
    Q_UNUSED(iMsg);
335
    _copyShape("Element copy",false,true);
336
}
337

338
bool CmdPartElementCopy::isActive()
339
{
340
    return Gui::Selection().hasSelection();
341
}
342

343
//===========================================================================
344
// Part_RefineShape
345
//===========================================================================
346
DEF_STD_CMD_A(CmdPartRefineShape)
347

348
CmdPartRefineShape::CmdPartRefineShape()
349
  : Command("Part_RefineShape")
350
{
351
    sAppModule    = "Part";
352
    sGroup        = QT_TR_NOOP("Part");
353
    sMenuText     = QT_TR_NOOP("Refine shape");
354
    sToolTipText  = QT_TR_NOOP("Refine the copy of a shape");
355
    sWhatsThis    = "Part_RefineShape";
356
    sStatusTip    = sToolTipText;
357
    sPixmap       = "Part_Refine_Shape";
358
}
359

360
void CmdPartRefineShape::activated(int iMsg)
361
{
362
    Q_UNUSED(iMsg);
363
    ParameterGrp::handle hGrp = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/Mod/Part");
364
    bool parametric = hGrp->GetBool("ParametricRefine", true);
365
    if (parametric) {
366
        Gui::WaitCursor wc;
367
        Base::Type partid = Base::Type::fromName("Part::Feature");
368
        std::vector<App::DocumentObject*> objs = Gui::Selection().getObjectsOfType(partid);
369
        openCommand(QT_TRANSLATE_NOOP("Command", "Refine shape"));
370
        std::for_each(objs.begin(), objs.end(), [](App::DocumentObject* obj) {
371
            try {
372
                App::DocumentObjectT objT(obj);
373
                Gui::cmdAppDocumentArgs(obj->getDocument(), "addObject('Part::Refine','%s')",
374
                                        obj->getNameInDocument());
375
                Gui::cmdAppDocumentArgs(obj->getDocument(), "ActiveObject.Source = %s",
376
                                        objT.getObjectPython());
377
                Gui::cmdAppDocumentArgs(obj->getDocument(), "ActiveObject.Label = %s.Label",
378
                                        objT.getObjectPython());
379
                Gui::cmdAppObjectHide(obj);
380

381
                auto newObj = App::GetApplication().getActiveDocument()->getActiveObject();
382
                Gui::copyVisualT(newObj->getNameInDocument(), "ShapeAppearance", obj->getNameInDocument());
383
                Gui::copyVisualT(newObj->getNameInDocument(), "LineColor", obj->getNameInDocument());
384
                Gui::copyVisualT(newObj->getNameInDocument(), "PointColor", obj->getNameInDocument());
385
            }
386
            catch (const Base::Exception& e) {
387
                Base::Console().Warning("%s: %s\n", obj->Label.getValue(), e.what());
388
            }
389
        });
390
        commitCommand();
391
        updateActive();
392
    }
393
    else {
394
        _copyShape("Refined copy",true,false,true);
395
    }
396
}
397

398
bool CmdPartRefineShape::isActive()
399
{
400
    return Gui::Selection().hasSelection();
401
}
402

403
//===========================================================================
404
// Part_Defeaturing
405
//===========================================================================
406
DEF_STD_CMD_A(CmdPartDefeaturing)
407

408
CmdPartDefeaturing::CmdPartDefeaturing()
409
  : Command("Part_Defeaturing")
410
{
411
    sAppModule    = "Part";
412
    sGroup        = QT_TR_NOOP("Part");
413
    sMenuText     = QT_TR_NOOP("Defeaturing");
414
    sToolTipText  = QT_TR_NOOP("Remove feature from a shape");
415
    sWhatsThis    = "Part_Defeaturing";
416
    sStatusTip    = sToolTipText;
417
    sPixmap       = "Part_Defeaturing";
418
}
419

420
void CmdPartDefeaturing::activated(int iMsg)
421
{
422
    Q_UNUSED(iMsg);
423
    Gui::WaitCursor wc;
424
    Base::Type partid = Base::Type::fromName("Part::Feature");
425
    std::vector<Gui::SelectionObject> objs = Gui::Selection().getSelectionEx(nullptr, partid);
426
    openCommand(QT_TRANSLATE_NOOP("Command", "Defeaturing"));
427
    for (std::vector<Gui::SelectionObject>::iterator it = objs.begin(); it != objs.end(); ++it) {
428
        try {
429
            std::string shape;
430
            shape.append("sh=App.");
431
            shape.append(it->getDocName());
432
            shape.append(".");
433
            shape.append(it->getFeatName());
434
            shape.append(".Shape\n");
435

436
            std::string faces;
437
            std::vector<std::string> subnames = it->getSubNames();
438
            for (const auto & subname : subnames) {
439
                faces.append("sh.");
440
                faces.append(subname);
441
                faces.append(",");
442
            }
443

444
            doCommand(Doc,"\nsh = App.getDocument('%s').%s.Shape\n"
445
                          "nsh = sh.defeaturing([%s])\n"
446
                          "if not sh.isPartner(nsh):\n"
447
                          "\t\tdefeat = App.ActiveDocument.addObject('Part::Feature','Defeatured').Shape = nsh\n"
448
                          "\t\tGui.ActiveDocument.%s.hide()\n"
449
                          "else:\n"
450
                          "\t\tFreeCAD.Console.PrintError('Defeaturing failed\\n')",
451
                          it->getDocName(),
452
                          it->getFeatName(),
453
                          faces.c_str(),
454
                          it->getFeatName());
455
        }
456
        catch (const Base::Exception& e) {
457
            Base::Console().Warning("%s: %s\n", it->getFeatName(), e.what());
458
        }
459
    }
460
    commitCommand();
461
    updateActive();
462
}
463

464
bool CmdPartDefeaturing::isActive()
465
{
466
    Base::Type partid = Base::Type::fromName("Part::Feature");
467
    std::vector<Gui::SelectionObject> objs = Gui::Selection().getSelectionEx(nullptr, partid);
468
    for (const auto & obj : objs) {
469
        std::vector<std::string> subnames = obj.getSubNames();
470
        for (const auto & subname : subnames) {
471
            if (subname.substr(0,4) == "Face") {
472
                return true;
473
            }
474
        }
475
    }
476
    return false;
477
}
478

479

480
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
481

482
void CreateSimplePartCommands()
483
{
484
    Gui::CommandManager &rcCmdMgr = Gui::Application::Instance->commandManager();
485
    rcCmdMgr.addCommand(new CmdPartSimpleCylinder());
486
    rcCmdMgr.addCommand(new CmdPartShapeFromMesh());
487
    rcCmdMgr.addCommand(new CmdPartPointsFromMesh());
488
    rcCmdMgr.addCommand(new CmdPartSimpleCopy());
489
    rcCmdMgr.addCommand(new CmdPartElementCopy());
490
    rcCmdMgr.addCommand(new CmdPartTransformedCopy());
491
    rcCmdMgr.addCommand(new CmdPartRefineShape());
492
    rcCmdMgr.addCommand(new CmdPartDefeaturing());
493
}
494

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

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

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

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