FreeCAD

Форк
0
/
ComplexGeoDataPyImp.cpp 
598 строк · 18.9 Кб
1
/***************************************************************************
2
 *   Copyright (c) 2007 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 <memory>
27
#endif
28

29
#include "ComplexGeoData.h"
30
#include "StringHasher.h"
31

32
// inclusion of the generated files (generated out of ComplexGeoDataPy.xml)
33
#include <App/ComplexGeoDataPy.h>
34
#include <App/ComplexGeoDataPy.cpp>
35
#include <App/StringHasherPy.h>
36
#include <App/StringIDPy.h>
37
#include <Base/BoundBoxPy.h>
38
#include <Base/MatrixPy.h>
39
#include <Base/PlacementPy.h>
40
#include "Base/PyWrapParseTupleAndKeywords.h"
41
#include <Base/VectorPy.h>
42
#include <Base/GeometryPyCXX.h>
43

44
using namespace Data;
45
using namespace Base;
46

47
// returns a string which represent the object e.g. when printed in python
48
std::string ComplexGeoDataPy::representation() const
49
{
50
    return {"<ComplexGeoData object>"};
51
}
52

53
PyObject* ComplexGeoDataPy::getElementTypes(PyObject *args)
54
{
55
    if (!PyArg_ParseTuple(args, ""))
56
        return nullptr;
57

58
    std::vector<const char*> types = getComplexGeoDataPtr()->getElementTypes();
59
    Py::List list;
60
    for (auto it : types) {
61
        list.append(Py::String(it));
62
    }
63
    return Py::new_reference_to(list);
64
}
65

66
PyObject* ComplexGeoDataPy::countSubElements(PyObject *args)
67
{
68
    char *type;
69
    if (!PyArg_ParseTuple(args, "s", &type))
70
        return nullptr;
71

72
    try {
73
        unsigned long count = getComplexGeoDataPtr()->countSubElements(type);
74
        return Py::new_reference_to(Py::Long(count));
75
    }
76
    catch (...) {
77
        PyErr_SetString(PyExc_RuntimeError, "failed to count sub-elements from object");
78
        return nullptr;
79
    }
80
}
81

82
PyObject* ComplexGeoDataPy::getFacesFromSubElement(PyObject *args)
83
{
84
    char *type;
85
    unsigned long index;
86
    if (!PyArg_ParseTuple(args, "sk", &type, &index))
87
        return nullptr;
88

89
    std::vector<Base::Vector3d> points;
90
    std::vector<Base::Vector3d> normals;
91
    std::vector<Data::ComplexGeoData::Facet> facets;
92
    try {
93
        std::unique_ptr<Data::Segment> segm(getComplexGeoDataPtr()->getSubElement(type, index));
94
        getComplexGeoDataPtr()->getFacesFromSubElement(segm.get(), points, normals, facets);
95
    }
96
    catch (...) {
97
        PyErr_SetString(PyExc_RuntimeError, "failed to get sub-element from object");
98
        return nullptr;
99
    }
100

101
    Py::Tuple tuple(2);
102
    Py::List vertex;
103
    for (const auto & it : points)
104
        vertex.append(Py::asObject(new Base::VectorPy(it)));
105
    tuple.setItem(0, vertex);
106
    Py::List facet;
107
    for (const auto & it : facets) {
108
        Py::Tuple f(3);
109
        f.setItem(0,Py::Int(int(it.I1)));
110
        f.setItem(1,Py::Int(int(it.I2)));
111
        f.setItem(2,Py::Int(int(it.I3)));
112
        facet.append(f);
113
    }
114
    tuple.setItem(1, facet);
115
    return Py::new_reference_to(tuple);
116
}
117

118
PyObject* ComplexGeoDataPy::getLinesFromSubElement(PyObject *args)
119
{
120
    char *type;
121
    int index;
122
    if (!PyArg_ParseTuple(args, "si", &type, &index))
123
        return nullptr;
124

125
    std::vector<Base::Vector3d> points;
126
    std::vector<Data::ComplexGeoData::Line> lines;
127
    try {
128
        std::unique_ptr<Data::Segment> segm(getComplexGeoDataPtr()->getSubElement(type, index));
129
        getComplexGeoDataPtr()->getLinesFromSubElement(segm.get(), points, lines);
130
    }
131
    catch (...) {
132
        PyErr_SetString(PyExc_RuntimeError, "failed to get sub-element from object");
133
        return nullptr;
134
    }
135

136
    Py::Tuple tuple(2);
137
    Py::List vertex;
138
    for (const auto & it : points)
139
        vertex.append(Py::asObject(new Base::VectorPy(it)));
140
    tuple.setItem(0, vertex);
141
    Py::List line;
142
    for (const auto & it : lines) {
143
        Py::Tuple l(2);
144
        l.setItem(0,Py::Int((int)it.I1));
145
        l.setItem(1,Py::Int((int)it.I2));
146
        line.append(l);
147
    }
148
    tuple.setItem(1, line);
149
    return Py::new_reference_to(tuple);
150
}
151

152
PyObject* ComplexGeoDataPy::getPoints(PyObject *args)
153
{
154
    double accuracy = 0.05;
155
    if (!PyArg_ParseTuple(args, "d", &accuracy))
156
        return nullptr;
157

158
    std::vector<Base::Vector3d> points;
159
    std::vector<Base::Vector3d> normals;
160
    try {
161
        getComplexGeoDataPtr()->getPoints(points, normals, accuracy);
162
    }
163
    catch (...) {
164
        PyErr_SetString(PyExc_RuntimeError, "failed to get sub-element from object");
165
        return nullptr;
166
    }
167

168
    Py::Tuple tuple(2);
169
    Py::List vertex;
170
    for (const auto & it : points) {
171
        vertex.append(Py::asObject(new Base::VectorPy(it)));
172
    }
173
    tuple.setItem(0, vertex);
174

175
    Py::List normal;
176
    for (const auto & it : normals) {
177
        normal.append(Py::asObject(new Base::VectorPy(it)));
178
    }
179
    tuple.setItem(1, normal);
180
    return Py::new_reference_to(tuple);
181
}
182

183
PyObject* ComplexGeoDataPy::getLines(PyObject *args)
184
{
185
    double accuracy = 0.05;
186
    if (!PyArg_ParseTuple(args, "d", &accuracy))
187
        return nullptr;
188

189
    std::vector<Base::Vector3d> points;
190
    std::vector<Data::ComplexGeoData::Line> lines;
191
    try {
192
        getComplexGeoDataPtr()->getLines(points, lines, accuracy);
193
    }
194
    catch (...) {
195
        PyErr_SetString(PyExc_RuntimeError, "failed to get sub-element from object");
196
        return nullptr;
197
    }
198

199
    Py::Tuple tuple(2);
200
    Py::List vertex;
201
    for (const auto & it : points)
202
        vertex.append(Py::asObject(new Base::VectorPy(it)));
203
    tuple.setItem(0, vertex);
204
    Py::List line;
205
    for (const auto & it : lines) {
206
        Py::Tuple l(2);
207
        l.setItem(0,Py::Int((int)it.I1));
208
        l.setItem(1,Py::Int((int)it.I2));
209
        line.append(l);
210
    }
211
    tuple.setItem(1, line);
212
    return Py::new_reference_to(tuple);
213
}
214

215
PyObject* ComplexGeoDataPy::getFaces(PyObject *args)
216
{
217
    double accuracy = 0.05;
218
    if (!PyArg_ParseTuple(args, "d", &accuracy))
219
        return nullptr;
220

221
    std::vector<Base::Vector3d> points;
222
    std::vector<Data::ComplexGeoData::Facet> facets;
223
    try {
224
        getComplexGeoDataPtr()->getFaces(points, facets, accuracy);
225
    }
226
    catch (...) {
227
        PyErr_SetString(PyExc_RuntimeError, "failed to get sub-element from object");
228
        return nullptr;
229
    }
230

231
    Py::Tuple tuple(2);
232
    Py::List vertex;
233
    for (const auto & it : points)
234
        vertex.append(Py::asObject(new Base::VectorPy(it)));
235
    tuple.setItem(0, vertex);
236
    Py::List facet;
237
    for (const auto & it : facets) {
238
        Py::Tuple f(3);
239
        f.setItem(0,Py::Int((int)it.I1));
240
        f.setItem(1,Py::Int((int)it.I2));
241
        f.setItem(2,Py::Int((int)it.I3));
242
        facet.append(f);
243
    }
244
    tuple.setItem(1, facet);
245
    return Py::new_reference_to(tuple);
246
}
247

248
PyObject* ComplexGeoDataPy::applyTranslation(PyObject *args)
249
{
250
    PyObject *obj;
251
    if (!PyArg_ParseTuple(args, "O!", &(Base::VectorPy::Type),&obj))
252
        return nullptr;
253

254
    try {
255
        Base::Vector3d move = static_cast<Base::VectorPy*>(obj)->value();
256
        getComplexGeoDataPtr()->applyTranslation(move);
257
        Py_Return;
258
    }
259
    catch (...) {
260
        PyErr_SetString(PyExc_RuntimeError, "failed to apply rotation");
261
        return nullptr;
262
    }
263
}
264

265
PyObject* ComplexGeoDataPy::applyRotation(PyObject *args)
266
{
267
    PyObject *obj;
268
    if (!PyArg_ParseTuple(args, "O!", &(Base::RotationPy::Type),&obj))
269
        return nullptr;
270

271
    try {
272
        Base::Rotation rot = static_cast<Base::RotationPy*>(obj)->value();
273
        getComplexGeoDataPtr()->applyRotation(rot);
274
        Py_Return;
275
    }
276
    catch (...) {
277
        PyErr_SetString(PyExc_RuntimeError, "failed to apply rotation");
278
        return nullptr;
279
    }
280
}
281

282
PyObject* ComplexGeoDataPy::transformGeometry(PyObject *args)
283
{
284
    PyObject *obj;
285
    if (!PyArg_ParseTuple(args, "O!", &(Base::MatrixPy::Type),&obj))
286
        return nullptr;
287

288
    try {
289
        Base::Matrix4D mat = static_cast<Base::MatrixPy*>(obj)->value();
290
        getComplexGeoDataPtr()->transformGeometry(mat);
291
        Py_Return;
292
    }
293
    catch (...) {
294
        PyErr_SetString(PyExc_RuntimeError, "failed to transform geometry");
295
        return nullptr;
296
    }
297
}
298

299
PyObject* ComplexGeoDataPy::getElementName(PyObject* args)
300
{
301
    char* input;
302
    int direction = 0;
303
    if (!PyArg_ParseTuple(args, "s|i", &input, &direction)) {
304
        return NULL;
305
    }
306

307
    Data::MappedElement res = getComplexGeoDataPtr()->getElementName(input);
308
    std::string s;
309
    if (direction == 1) {
310
        return Py::new_reference_to(Py::String(res.name.appendToBuffer(s)));
311
    }
312
    else if (direction == 0) {
313
        return Py::new_reference_to(Py::String(res.index.appendToStringBuffer(s)));
314
    }
315
    else if (Data::IndexedName(input)) {
316
        return Py::new_reference_to(Py::String(res.name.appendToBuffer(s)));
317
    }
318
    else {
319
        return Py::new_reference_to(Py::String(res.index.appendToStringBuffer(s)));
320
    }
321
}
322

323
PyObject* ComplexGeoDataPy::getElementIndexedName(PyObject* args)
324
{
325
    char* input;
326
    PyObject* returnID = Py_False;
327
    if (!PyArg_ParseTuple(args, "s|O", &input, &returnID)) {
328
        return NULL;
329
    }
330

331
    ElementIDRefs ids;
332
    Data::MappedElement res =
333
        getComplexGeoDataPtr()->getElementName(input, PyObject_IsTrue(returnID) ? &ids : nullptr);
334
    std::string s;
335
    Py::String name(res.index.appendToStringBuffer(s));
336
    if (!PyObject_IsTrue(returnID)) {
337
        return Py::new_reference_to(name);
338
    }
339

340
    Py::List list;
341
    for (auto& id : ids) {
342
        list.append(Py::Long(id.value()));
343
    }
344
    return Py::new_reference_to(Py::TupleN(name, list));
345
}
346

347
PyObject* ComplexGeoDataPy::getElementMappedName(PyObject* args)
348
{
349
    char* input;
350
    PyObject* returnID = Py_False;
351
    if (!PyArg_ParseTuple(args, "s|O", &input, &returnID)) {
352
        return NULL;
353
    }
354

355
    ElementIDRefs ids;
356
    Data::MappedElement res =
357
        getComplexGeoDataPtr()->getElementName(input, PyObject_IsTrue(returnID) ? &ids : nullptr);
358
    std::string s;
359
    Py::String name(res.name.appendToBuffer(s));
360
    if (!PyObject_IsTrue(returnID)) {
361
        return Py::new_reference_to(name);
362
    }
363

364
    Py::List list;
365
    for (auto& id : ids) {
366
        list.append(Py::Long(id.value()));
367
    }
368
    return Py::new_reference_to(Py::TupleN(name, list));
369
}
370

371
PyObject* ComplexGeoDataPy::setElementName(PyObject* args, PyObject* kwds)
372
{
373
    const char* element;
374
    const char* name = 0;
375
    const char* postfix = 0;
376
    int tag = 0;
377
    PyObject* pySid = Py_None;
378
    PyObject* overwrite = Py_False;
379

380
    const std::array<const char *,7> kwlist = {"element", "name", "postfix", "overwrite", "sid", "tag", nullptr};
381
    if (!Wrapped_ParseTupleAndKeywords(args,
382
                                     kwds,
383
                                     "s|sssOOi",
384
                                     kwlist,
385
                                     &element,
386
                                     &name,
387
                                     &postfix,
388
                                     &overwrite,
389
                                     &pySid,
390
                                     &tag)) {
391
        return NULL;
392
    }
393
    ElementIDRefs sids;
394
    if (pySid != Py_None) {
395
        if (PyObject_TypeCheck(pySid, &App::StringIDPy::Type)) {
396
            sids.push_back(static_cast<App::StringIDPy*>(pySid)->getStringIDPtr());
397
        }
398
        else if (PySequence_Check(pySid)) {
399
            Py::Sequence seq(pySid);
400
            for (auto it = seq.begin(); it != seq.end(); ++it) {
401
                auto ptr = (*it).ptr();
402
                if (PyObject_TypeCheck(ptr, &App::StringIDPy::Type)) {
403
                    sids.push_back(static_cast<App::StringIDPy*>(ptr)->getStringIDPtr());
404
                }
405
                else {
406
                    throw Py::TypeError("expect StringID in sid sequence");
407
                }
408
            }
409
        }
410
        else {
411
            throw Py::TypeError("expect sid to contain either StringID or sequence of StringID");
412
        }
413
    }
414
    PY_TRY
415
    {
416
        Data::IndexedName index(element, getComplexGeoDataPtr()->getElementTypes());
417
        Data::MappedName mapped = Data::MappedName::fromRawData(name);
418
        std::ostringstream ss;
419
        ElementMapPtr map = getComplexGeoDataPtr()->resetElementMap();
420
        map->encodeElementName(getComplexGeoDataPtr()->elementType(index),
421
                               mapped,
422
                               ss,
423
                               &sids,
424
                               tag,
425
                               postfix,
426
                               tag);
427
        Data::MappedName res =
428
            map->setElementName(index, mapped, tag, &sids, PyObject_IsTrue(overwrite));
429
        return Py::new_reference_to(Py::String(res.toString(0)));
430
    }
431
    PY_CATCH
432
}
433

434
Py::Object ComplexGeoDataPy::getHasher() const
435
{
436
    auto self = getComplexGeoDataPtr();
437
    if (!self->Hasher) {
438
        return Py::None();
439
    }
440
    return Py::Object(self->Hasher->getPyObject(), true);
441
}
442

443
Py::Dict ComplexGeoDataPy::getElementMap() const
444
{
445
    Py::Dict ret;
446
    std::string s;
447
    for (auto& v : getComplexGeoDataPtr()->getElementMap()) {
448
        s.clear();
449
        ret.setItem(v.name.toString(0), Py::String(v.index.appendToStringBuffer(s)));
450
    }
451
    return ret;
452
}
453

454
void ComplexGeoDataPy::setElementMap(Py::Dict dict)
455
{
456
    std::vector<Data::MappedElement> map;
457
    const auto& types = getComplexGeoDataPtr()->getElementTypes();
458
    for (auto it = dict.begin(); it != dict.end(); ++it) {
459
        const auto& value = *it;
460
        if (!value.first.isString() || !value.second.isString()) {
461
            throw Py::TypeError("expect only strings in the dict");
462
        }
463
        map.emplace_back(Data::MappedName(value.first.as_string().c_str()),
464
                         Data::IndexedName(Py::Object(value.second).as_string().c_str(), types));
465
    }
466
    getComplexGeoDataPtr()->setElementMap(map);
467
}
468

469
Py::Dict ComplexGeoDataPy::getElementReverseMap() const
470
{
471
    Py::Dict ret;
472
    std::string s;
473
    for (auto& v : getComplexGeoDataPtr()->getElementMap()) {
474
        s.clear();
475
        auto value = ret[Py::String(v.index.appendToStringBuffer(s))];
476
        Py::Object item(value);
477
        if (item.isNone()) {
478
            s.clear();
479
            value = Py::String(v.name.appendToBuffer(s));
480
        }
481
        else if (item.isList()) {
482
            Py::List list(item);
483
            s.clear();
484
            list.append(Py::String(v.name.appendToBuffer(s)));
485
        }
486
        else {
487
            Py::List list;
488
            list.append(item);
489
            s.clear();
490
            list.append(Py::String(v.name.appendToBuffer(s)));
491
            value = list;
492
        }
493
    }
494
    return ret;
495
}
496

497
Py::Int ComplexGeoDataPy::getElementMapSize() const
498
{
499
    return Py::Int((long)getComplexGeoDataPtr()->getElementMapSize());
500
}
501

502
void ComplexGeoDataPy::setHasher(Py::Object obj)
503
{
504
    auto self = getComplexGeoDataPtr();
505
    if (obj.isNone()) {
506
        if (self->Hasher) {
507
            self->Hasher = App::StringHasherRef();
508
            self->resetElementMap();
509
        }
510
    }
511
    else if (PyObject_TypeCheck(obj.ptr(), &App::StringHasherPy::Type)) {
512
        App::StringHasherRef ref(
513
            static_cast<App::StringHasherPy*>(obj.ptr())->getStringHasherPtr());
514
        if (self->Hasher != ref) {
515
            self->Hasher = ref;
516
            self->resetElementMap();
517
        }
518
    }
519
    else {
520
        throw Py::TypeError("invalid type");
521
    }
522
}
523

524
Py::Object ComplexGeoDataPy::getBoundBox() const
525
{
526
    return Py::BoundingBox(getComplexGeoDataPtr()->getBoundBox());
527
}
528

529
Py::Object ComplexGeoDataPy::getCenterOfGravity() const
530
{
531
    Base::Vector3d center;
532
    if (getComplexGeoDataPtr()->getCenterOfGravity(center))
533
        return Py::Vector(center);
534
    throw Py::RuntimeError("Cannot get center of gravity");
535
}
536

537
Py::Object ComplexGeoDataPy::getPlacement() const
538
{
539
    return Py::Placement(getComplexGeoDataPtr()->getPlacement());
540
}
541

542
void ComplexGeoDataPy::setPlacement(Py::Object arg)
543
{
544
    PyObject* p = arg.ptr();
545
    if (PyObject_TypeCheck(p, &(Base::PlacementPy::Type))) {
546
        Base::Placement* trf = static_cast<Base::PlacementPy*>(p)->getPlacementPtr();
547
        getComplexGeoDataPtr()->setPlacement(*trf);
548
    }
549
    else {
550
        std::string error = std::string("type must be 'Placement', not ");
551
        error += p->ob_type->tp_name;
552
        throw Py::TypeError(error);
553
    }
554
}
555

556
Py::String ComplexGeoDataPy::getElementMapVersion() const
557
{
558
    return Py::String(getComplexGeoDataPtr()->getElementMapVersion());
559
}
560

561

562
Py::Int ComplexGeoDataPy::getTag() const
563
{
564
    return Py::Int(getComplexGeoDataPtr()->Tag);
565
}
566

567
void ComplexGeoDataPy::setTag(Py::Int tag)
568
{
569
    getComplexGeoDataPtr()->Tag = tag;
570
}
571

572
PyObject* ComplexGeoDataPy::getCustomAttributes(const char* attr) const
573
{
574
    // Support for backward compatibility
575
    if (strcmp(attr, "Matrix") == 0) {
576
        Py::Matrix mat(getComplexGeoDataPtr()->getTransform());
577
        return Py::new_reference_to(mat);
578
    }
579
    return nullptr;
580
}
581

582
int ComplexGeoDataPy::setCustomAttributes(const char* attr, PyObject* obj)
583
{
584
    // Support for backward compatibility
585
    if (strcmp(attr, "Matrix") == 0) {
586
        if (PyObject_TypeCheck(obj, &(Base::MatrixPy::Type))) {
587
            Base::Matrix4D mat = static_cast<Base::MatrixPy*>(obj)->value();
588
            getComplexGeoDataPtr()->setTransform(mat);
589
            return 1;
590
        }
591
        else {
592
            std::string error = std::string("type must be 'Matrix', not ");
593
            error += obj->ob_type->tp_name;
594
            throw Py::TypeError(error);
595
        }
596
    }
597
    return 0;
598
}
599

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

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

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

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