FreeCAD

Форк
0
/
MeshProperties.cpp 
949 строк · 28.1 Кб
1
/***************************************************************************
2
 *   Copyright (c) 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
#include "PreCompiled.h"
24

25
#include <Base/Converter.h>
26
#include <Base/Exception.h>
27
#include <Base/Reader.h>
28
#include <Base/Stream.h>
29
#include <Base/VectorPy.h>
30
#include <Base/Writer.h>
31

32
#include "Core/Iterator.h"
33
#include "Core/MeshKernel.h"
34
#include "Core/MeshIO.h"
35

36
#include "MeshProperties.h"
37
#include "Mesh.h"
38
#include "MeshPy.h"
39

40

41
using namespace Mesh;
42

43
TYPESYSTEM_SOURCE(Mesh::PropertyNormalList, App::PropertyLists)
44
TYPESYSTEM_SOURCE(Mesh::PropertyCurvatureList, App::PropertyLists)
45
TYPESYSTEM_SOURCE(Mesh::PropertyMaterial, App::Property)
46
TYPESYSTEM_SOURCE(Mesh::PropertyMeshKernel, App::PropertyComplexGeoData)
47

48
PropertyNormalList::PropertyNormalList() = default;
49

50
void PropertyNormalList::setSize(int newSize)
51
{
52
    _lValueList.resize(newSize);
53
}
54

55
int PropertyNormalList::getSize() const
56
{
57
    return static_cast<int>(_lValueList.size());
58
}
59

60
void PropertyNormalList::setValue(const Base::Vector3f& lValue)
61
{
62
    aboutToSetValue();
63
    _lValueList.resize(1);
64
    _lValueList[0] = lValue;
65
    hasSetValue();
66
}
67

68
void PropertyNormalList::setValue(float x, float y, float z)
69
{
70
    aboutToSetValue();
71
    _lValueList.resize(1);
72
    _lValueList[0].Set(x, y, z);
73
    hasSetValue();
74
}
75

76
void PropertyNormalList::setValues(const std::vector<Base::Vector3f>& values)
77
{
78
    aboutToSetValue();
79
    _lValueList = values;
80
    hasSetValue();
81
}
82

83
PyObject* PropertyNormalList::getPyObject()
84
{
85
    PyObject* list = PyList_New(getSize());
86

87
    for (int i = 0; i < getSize(); i++) {
88
        PyList_SetItem(list, i, new Base::VectorPy(_lValueList[i]));
89
    }
90

91
    return list;
92
}
93

94
void PropertyNormalList::setPyObject(PyObject* value)
95
{
96
    if (PyList_Check(value)) {
97
        Py_ssize_t nSize = PyList_Size(value);
98
        std::vector<Base::Vector3f> values;
99
        values.resize(nSize);
100

101
        for (Py_ssize_t i = 0; i < nSize; ++i) {
102
            PyObject* item = PyList_GetItem(value, i);
103
            App::PropertyVector val;
104
            val.setPyObject(item);
105
            values[i] = Base::convertTo<Base::Vector3f>(val.getValue());
106
        }
107

108
        setValues(values);
109
    }
110
    else if (PyObject_TypeCheck(value, &(Base::VectorPy::Type))) {
111
        Base::VectorPy* pcObject = static_cast<Base::VectorPy*>(value);
112
        Base::Vector3d* val = pcObject->getVectorPtr();
113
        setValue(Base::convertTo<Base::Vector3f>(*val));
114
    }
115
    else if (PyTuple_Check(value) && PyTuple_Size(value) == 3) {
116
        App::PropertyVector val;
117
        val.setPyObject(value);
118
        setValue(Base::convertTo<Base::Vector3f>(val.getValue()));
119
    }
120
    else {
121
        std::string error = std::string("type must be 'Vector' or list of 'Vector', not ");
122
        error += value->ob_type->tp_name;
123
        throw Py::TypeError(error);
124
    }
125
}
126

127
void PropertyNormalList::Save(Base::Writer& writer) const
128
{
129
    if (!writer.isForceXML()) {
130
        writer.Stream() << writer.ind() << "<VectorList file=\"" << writer.addFile(getName(), this)
131
                        << "\"/>" << std::endl;
132
    }
133
}
134

135
void PropertyNormalList::Restore(Base::XMLReader& reader)
136
{
137
    reader.readElement("VectorList");
138
    std::string file(reader.getAttribute("file"));
139

140
    if (!file.empty()) {
141
        // initiate a file read
142
        reader.addFile(file.c_str(), this);
143
    }
144
}
145

146
void PropertyNormalList::SaveDocFile(Base::Writer& writer) const
147
{
148
    Base::OutputStream str(writer.Stream());
149
    uint32_t uCt = (uint32_t)getSize();
150
    str << uCt;
151
    for (auto it : _lValueList) {
152
        str << it.x << it.y << it.z;
153
    }
154
}
155

156
void PropertyNormalList::RestoreDocFile(Base::Reader& reader)
157
{
158
    Base::InputStream str(reader);
159
    uint32_t uCt = 0;
160
    str >> uCt;
161
    std::vector<Base::Vector3f> values(uCt);
162
    for (auto& it : values) {
163
        str >> it.x >> it.y >> it.z;
164
    }
165
    setValues(values);
166
}
167

168
App::Property* PropertyNormalList::Copy() const
169
{
170
    PropertyNormalList* p = new PropertyNormalList();
171
    p->_lValueList = _lValueList;
172
    return p;
173
}
174

175
void PropertyNormalList::Paste(const App::Property& from)
176
{
177
    aboutToSetValue();
178
    _lValueList = dynamic_cast<const PropertyNormalList&>(from)._lValueList;
179
    hasSetValue();
180
}
181

182
unsigned int PropertyNormalList::getMemSize() const
183
{
184
    return static_cast<unsigned int>(_lValueList.size() * sizeof(Base::Vector3f));
185
}
186

187
void PropertyNormalList::transformGeometry(const Base::Matrix4D& mat)
188
{
189
    // A normal vector is only a direction with unit length, so we only need to rotate it
190
    // (no translations or scaling)
191

192
    // Extract scale factors (assumes an orthogonal rotation matrix)
193
    // Use the fact that the length of the row vectors of R are all equal to 1
194
    // And that scaling is applied after rotating
195
    double s[3];
196
    s[0] = sqrt(mat[0][0] * mat[0][0] + mat[0][1] * mat[0][1] + mat[0][2] * mat[0][2]);
197
    s[1] = sqrt(mat[1][0] * mat[1][0] + mat[1][1] * mat[1][1] + mat[1][2] * mat[1][2]);
198
    s[2] = sqrt(mat[2][0] * mat[2][0] + mat[2][1] * mat[2][1] + mat[2][2] * mat[2][2]);
199

200
    // Set up the rotation matrix: zero the translations and make the scale factors = 1
201
    Base::Matrix4D rot;
202
    rot.setToUnity();
203
    for (unsigned short i = 0; i < 3; i++) {
204
        for (unsigned short j = 0; j < 3; j++) {
205
            rot[i][j] = mat[i][j] / s[i];
206
        }
207
    }
208

209
    aboutToSetValue();
210

211
    // Rotate the normal vectors
212
    for (int ii = 0; ii < getSize(); ii++) {
213
        set1Value(ii, rot * operator[](ii));
214
    }
215

216
    hasSetValue();
217
}
218

219
// ----------------------------------------------------------------------------
220

221
PropertyCurvatureList::PropertyCurvatureList() = default;
222

223
void PropertyCurvatureList::setValue(const CurvatureInfo& lValue)
224
{
225
    aboutToSetValue();
226
    _lValueList.resize(1);
227
    _lValueList[0] = lValue;
228
    hasSetValue();
229
}
230

231
void PropertyCurvatureList::setValues(const std::vector<CurvatureInfo>& lValues)
232
{
233
    aboutToSetValue();
234
    _lValueList = lValues;
235
    hasSetValue();
236
}
237

238
std::vector<float> PropertyCurvatureList::getCurvature(int mode) const
239
{
240
    const std::vector<Mesh::CurvatureInfo>& fCurvInfo = getValues();
241
    std::vector<float> fValues;
242
    fValues.reserve(fCurvInfo.size());
243

244
    // Mean curvature
245
    if (mode == MeanCurvature) {
246
        for (const auto& it : fCurvInfo) {
247
            fValues.push_back(0.5f * (it.fMaxCurvature + it.fMinCurvature));
248
        }
249
    }
250
    // Gaussian curvature
251
    else if (mode == GaussCurvature) {
252
        for (const auto& it : fCurvInfo) {
253
            fValues.push_back(it.fMaxCurvature * it.fMinCurvature);
254
        }
255
    }
256
    // Maximum curvature
257
    else if (mode == MaxCurvature) {
258
        for (const auto& it : fCurvInfo) {
259
            fValues.push_back(it.fMaxCurvature);
260
        }
261
    }
262
    // Minimum curvature
263
    else if (mode == MinCurvature) {
264
        for (const auto& it : fCurvInfo) {
265
            fValues.push_back(it.fMinCurvature);
266
        }
267
    }
268
    // Absolute curvature
269
    else if (mode == AbsCurvature) {
270
        for (const auto& it : fCurvInfo) {
271
            if (fabs(it.fMaxCurvature) > fabs(it.fMinCurvature)) {
272
                fValues.push_back(it.fMaxCurvature);
273
            }
274
            else {
275
                fValues.push_back(it.fMinCurvature);
276
            }
277
        }
278
    }
279

280
    return fValues;
281
}
282

283
void PropertyCurvatureList::transformGeometry(const Base::Matrix4D& mat)
284
{
285
    // The principal direction is only a vector with unit length, so we only need to rotate it
286
    // (no translations or scaling)
287

288
    // Extract scale factors (assumes an orthogonal rotation matrix)
289
    // Use the fact that the length of the row vectors of R are all equal to 1
290
    // And that scaling is applied after rotating
291
    double s[3];
292
    s[0] = sqrt(mat[0][0] * mat[0][0] + mat[0][1] * mat[0][1] + mat[0][2] * mat[0][2]);
293
    s[1] = sqrt(mat[1][0] * mat[1][0] + mat[1][1] * mat[1][1] + mat[1][2] * mat[1][2]);
294
    s[2] = sqrt(mat[2][0] * mat[2][0] + mat[2][1] * mat[2][1] + mat[2][2] * mat[2][2]);
295

296
    // Set up the rotation matrix: zero the translations and make the scale factors = 1
297
    Base::Matrix4D rot;
298
    rot.setToUnity();
299
    for (unsigned short i = 0; i < 3; i++) {
300
        for (unsigned short j = 0; j < 3; j++) {
301
            rot[i][j] = mat[i][j] / s[i];
302
        }
303
    }
304

305
    aboutToSetValue();
306

307
    // Rotate the principal directions
308
    for (int ii = 0; ii < getSize(); ii++) {
309
        CurvatureInfo ci = operator[](ii);
310
        ci.cMaxCurvDir = rot * ci.cMaxCurvDir;
311
        ci.cMinCurvDir = rot * ci.cMinCurvDir;
312
        _lValueList[ii] = ci;
313
    }
314

315
    hasSetValue();
316
}
317

318
void PropertyCurvatureList::Save(Base::Writer& writer) const
319
{
320
    if (!writer.isForceXML()) {
321
        writer.Stream() << writer.ind() << "<CurvatureList file=\""
322
                        << writer.addFile(getName(), this) << "\"/>" << std::endl;
323
    }
324
}
325

326
void PropertyCurvatureList::Restore(Base::XMLReader& reader)
327
{
328
    reader.readElement("CurvatureList");
329
    std::string file(reader.getAttribute("file"));
330

331
    if (!file.empty()) {
332
        // initiate a file read
333
        reader.addFile(file.c_str(), this);
334
    }
335
}
336

337
void PropertyCurvatureList::SaveDocFile(Base::Writer& writer) const
338
{
339
    Base::OutputStream str(writer.Stream());
340
    uint32_t uCt = (uint32_t)getSize();
341
    str << uCt;
342
    for (const auto& it : _lValueList) {
343
        str << it.fMaxCurvature << it.fMinCurvature;
344
        str << it.cMaxCurvDir.x << it.cMaxCurvDir.y << it.cMaxCurvDir.z;
345
        str << it.cMinCurvDir.x << it.cMinCurvDir.y << it.cMinCurvDir.z;
346
    }
347
}
348

349
void PropertyCurvatureList::RestoreDocFile(Base::Reader& reader)
350
{
351
    Base::InputStream str(reader);
352
    uint32_t uCt = 0;
353
    str >> uCt;
354
    std::vector<CurvatureInfo> values(uCt);
355
    for (auto& it : values) {
356
        str >> it.fMaxCurvature >> it.fMinCurvature;
357
        str >> it.cMaxCurvDir.x >> it.cMaxCurvDir.y >> it.cMaxCurvDir.z;
358
        str >> it.cMinCurvDir.x >> it.cMinCurvDir.y >> it.cMinCurvDir.z;
359
    }
360

361
    setValues(values);
362
}
363

364
PyObject* PropertyCurvatureList::getPyObject()
365
{
366
    Py::List list;
367
    for (const auto& it : _lValueList) {
368
        Py::Tuple tuple(4);
369
        tuple.setItem(0, Py::Float(it.fMaxCurvature));
370
        tuple.setItem(1, Py::Float(it.fMinCurvature));
371
        Py::Tuple maxDir(3);
372
        maxDir.setItem(0, Py::Float(it.cMaxCurvDir.x));
373
        maxDir.setItem(1, Py::Float(it.cMaxCurvDir.y));
374
        maxDir.setItem(2, Py::Float(it.cMaxCurvDir.z));
375
        tuple.setItem(2, maxDir);
376
        Py::Tuple minDir(3);
377
        minDir.setItem(0, Py::Float(it.cMinCurvDir.x));
378
        minDir.setItem(1, Py::Float(it.cMinCurvDir.y));
379
        minDir.setItem(2, Py::Float(it.cMinCurvDir.z));
380
        tuple.setItem(3, minDir);
381
        list.append(tuple);
382
    }
383

384
    return Py::new_reference_to(list);
385
}
386

387
void PropertyCurvatureList::setPyObject(PyObject* /*value*/)
388
{
389
    throw Base::AttributeError(std::string("This attribute is read-only"));
390
}
391

392
App::Property* PropertyCurvatureList::Copy() const
393
{
394
    PropertyCurvatureList* p = new PropertyCurvatureList();
395
    p->_lValueList = _lValueList;
396
    return p;
397
}
398

399
void PropertyCurvatureList::Paste(const App::Property& from)
400
{
401
    aboutToSetValue();
402
    _lValueList = dynamic_cast<const PropertyCurvatureList&>(from)._lValueList;
403
    hasSetValue();
404
}
405

406
// ----------------------------------------------------------------------------
407

408
const MeshCore::Material& PropertyMaterial::getValue() const
409
{
410
    return _material;
411
}
412

413
MeshCore::MeshIO::Binding PropertyMaterial::getBinding() const
414
{
415
    return _material.binding;
416
}
417

418
const std::vector<App::Color>& PropertyMaterial::getAmbientColor() const
419
{
420
    return _material.ambientColor;
421
}
422

423
const std::vector<App::Color>& PropertyMaterial::getDiffuseColor() const
424
{
425
    return _material.diffuseColor;
426
}
427

428
const std::vector<App::Color>& PropertyMaterial::getSpecularColor() const
429
{
430
    return _material.specularColor;
431
}
432

433
const std::vector<App::Color>& PropertyMaterial::getEmissiveColor() const
434
{
435
    return _material.emissiveColor;
436
}
437

438
const std::vector<float>& PropertyMaterial::getShininess() const
439
{
440
    return _material.shininess;
441
}
442

443
const std::vector<float>& PropertyMaterial::getTransparency() const
444
{
445
    return _material.transparency;
446
}
447

448
void PropertyMaterial::setValue(const MeshCore::Material& value)
449
{
450
    aboutToSetValue();
451
    _material = value;
452
    hasSetValue();
453
}
454

455
void PropertyMaterial::setAmbientColor(const std::vector<App::Color>& value)
456
{
457
    aboutToSetValue();
458
    _material.ambientColor = value;
459
    hasSetValue();
460
}
461

462
void PropertyMaterial::setDiffuseColor(const std::vector<App::Color>& value)
463
{
464
    aboutToSetValue();
465
    _material.diffuseColor = value;
466
    hasSetValue();
467
}
468

469
void PropertyMaterial::setSpecularColor(const std::vector<App::Color>& value)
470
{
471
    aboutToSetValue();
472
    _material.specularColor = value;
473
    hasSetValue();
474
}
475

476
void PropertyMaterial::setEmissiveColor(const std::vector<App::Color>& value)
477
{
478
    aboutToSetValue();
479
    _material.emissiveColor = value;
480
    hasSetValue();
481
}
482

483
void PropertyMaterial::setShininess(const std::vector<float>& value)
484
{
485
    aboutToSetValue();
486
    _material.shininess = value;
487
    hasSetValue();
488
}
489

490
void PropertyMaterial::setTransparency(const std::vector<float>& value)
491
{
492
    aboutToSetValue();
493
    _material.transparency = value;
494
    hasSetValue();
495
}
496

497
void PropertyMaterial::setBinding(MeshCore::MeshIO::Binding bind)
498
{
499
    aboutToSetValue();
500
    _material.binding = bind;
501
    hasSetValue();
502
}
503

504
PyObject* PropertyMaterial::getPyObject()
505
{
506
    auto getColorList = [](const std::vector<App::Color>& color) {
507
        Py::List list;
508
        for (const auto& it : color) {
509
            list.append(Py::TupleN(Py::Float(it.r), Py::Float(it.g), Py::Float(it.b)));
510
        }
511
        return list;
512
    };
513

514
    auto getFloatList = [](const std::vector<float>& value) {
515
        Py::List list;
516
        for (auto it : value) {
517
            list.append(Py::Float(it));
518
        }
519
        return list;
520
    };
521

522
    Py::Dict dict;
523
    dict.setItem("binding", Py::Long(static_cast<int>(_material.binding)));
524
    dict.setItem("ambientColor", getColorList(_material.ambientColor));
525
    dict.setItem("diffuseColor", getColorList(_material.diffuseColor));
526
    dict.setItem("specularColor", getColorList(_material.specularColor));
527
    dict.setItem("emissiveColor", getColorList(_material.emissiveColor));
528
    dict.setItem("shininess", getFloatList(_material.shininess));
529
    dict.setItem("transparency", getFloatList(_material.transparency));
530

531
    return Py::new_reference_to(dict);
532
}
533

534
void PropertyMaterial::setPyObject(PyObject* obj)
535
{
536
    auto getColorList = [](const Py::Dict& dict, const std::string& key) {
537
        std::vector<App::Color> color;
538
        if (dict.hasKey(key)) {
539
            Py::Sequence list(dict.getItem(key));
540
            color.reserve(list.size());
541
            for (const auto& it : list) {
542
                Py::Sequence tuple(it);
543
                float r = static_cast<float>(Py::Float(tuple[0]));
544
                float g = static_cast<float>(Py::Float(tuple[1]));
545
                float b = static_cast<float>(Py::Float(tuple[2]));
546
                color.emplace_back(r, g, b);
547
            }
548
        }
549
        return color;
550
    };
551

552
    auto getFloatList = [](const Py::Dict& dict, const std::string& key) {
553
        std::vector<float> value;
554
        if (dict.hasKey(key)) {
555
            Py::Sequence list(dict.getItem(key));
556
            value.reserve(list.size());
557
            for (const auto& it : list) {
558
                value.push_back(static_cast<float>(Py::Float(it)));
559
            }
560
        }
561
        return value;
562
    };
563

564
    try {
565
        MeshCore::Material material;
566
        Py::Dict dict(obj);
567

568
        if (dict.hasKey("binding")) {
569
            Py::Long binding(dict.getItem("binding"));
570
            int bind = static_cast<int>(binding);
571
            material.binding = static_cast<MeshCore::MeshIO::Binding>(bind);
572
        }
573

574
        material.ambientColor = getColorList(dict, "ambientColor");
575
        material.diffuseColor = getColorList(dict, "diffuseColor");
576
        material.specularColor = getColorList(dict, "specularColor");
577
        material.emissiveColor = getColorList(dict, "emissiveColor");
578
        material.shininess = getFloatList(dict, "shininess");
579
        material.transparency = getFloatList(dict, "transparency");
580

581
        setValue(material);
582
    }
583
    catch (Py::Exception& e) {
584
        e.clear();
585
        throw Base::TypeError("Not a dict with expected keys");
586
    }
587
}
588

589
void PropertyMaterial::Save(Base::Writer& writer) const
590
{
591
    if (!writer.isForceXML()) {
592
        writer.Stream() << writer.ind() << "<Material file=\"" << writer.addFile(getName(), this)
593
                        << "\"/>" << std::endl;
594
    }
595
}
596

597
void PropertyMaterial::Restore(Base::XMLReader& reader)
598
{
599
    reader.readElement("Material");
600
    if (reader.hasAttribute("file")) {
601
        std::string file(reader.getAttribute("file"));
602

603
        if (!file.empty()) {
604
            // initiate a file read
605
            reader.addFile(file.c_str(), this);
606
        }
607
    }
608
}
609

610
void PropertyMaterial::SaveDocFile(Base::Writer& writer) const
611
{
612
    Base::OutputStream str(writer.Stream());
613
    auto saveColor = [&str](const std::vector<App::Color>& color) {
614
        uint32_t count = static_cast<uint32_t>(color.size());
615
        str << count;
616
        for (const auto& it : color) {
617
            str << it.getPackedValue();
618
        }
619
    };
620

621
    auto saveFloat = [&str](const std::vector<float>& value) {
622
        uint32_t count = static_cast<uint32_t>(value.size());
623
        str << count;
624
        for (const auto& it : value) {
625
            str << it;
626
        }
627
    };
628

629
    uint32_t bind = static_cast<uint32_t>(_material.binding);
630
    str << bind;
631

632
    saveColor(_material.ambientColor);
633
    saveColor(_material.diffuseColor);
634
    saveColor(_material.specularColor);
635
    saveColor(_material.emissiveColor);
636
    saveFloat(_material.shininess);
637
    saveFloat(_material.transparency);
638
}
639

640
void PropertyMaterial::RestoreDocFile(Base::Reader& reader)
641
{
642
    Base::InputStream str(reader);
643
    auto restoreColor = [&str](std::vector<App::Color>& color) {
644
        uint32_t count = 0;
645
        str >> count;
646
        color.resize(count);
647
        for (auto& it : color) {
648
            uint32_t value {};  // must be 32 bit long
649
            str >> value;
650
            it.setPackedValue(value);
651
        }
652
    };
653

654
    auto restoreFloat = [&str](std::vector<float>& value) {
655
        uint32_t count = 0;
656
        str >> count;
657
        value.resize(count);
658
        for (auto& it : value) {
659
            float valueF {};
660
            str >> valueF;
661
            it = valueF;
662
        }
663
    };
664

665
    MeshCore::Material material;
666

667
    uint32_t bind = 0;
668
    str >> bind;
669
    material.binding = static_cast<MeshCore::MeshIO::Binding>(bind);
670

671
    restoreColor(material.ambientColor);
672
    restoreColor(material.diffuseColor);
673
    restoreColor(material.specularColor);
674
    restoreColor(material.emissiveColor);
675
    restoreFloat(material.shininess);
676
    restoreFloat(material.transparency);
677

678
    setValue(material);
679
}
680

681
const char* PropertyMaterial::getEditorName() const
682
{
683
    return "";
684
}
685

686
App::Property* PropertyMaterial::Copy() const
687
{
688
    PropertyMaterial* prop = new PropertyMaterial();
689
    prop->_material = _material;
690
    return prop;
691
}
692

693
void PropertyMaterial::Paste(const Property& from)
694
{
695
    aboutToSetValue();
696
    using ObjectType = std::remove_pointer<decltype(this)>::type;
697
    _material = dynamic_cast<const ObjectType&>(from)._material;
698
    hasSetValue();
699
}
700

701
unsigned int PropertyMaterial::getMemSize() const
702
{
703
    auto size = (_material.ambientColor.size() + _material.diffuseColor.size()
704
                 + _material.emissiveColor.size() + _material.specularColor.size())
705
            * sizeof(App::Color)
706
        + (_material.shininess.size() + _material.transparency.size()) * sizeof(float)
707
        + _material.library.size() + sizeof(_material);
708
    return static_cast<unsigned int>(size);
709
}
710

711
bool PropertyMaterial::isSame(const App::Property& other) const
712
{
713
    if (&other == this) {
714
        return true;
715
    }
716
    return getTypeId() == other.getTypeId()
717
        && getValue() == static_cast<decltype(this)>(&other)->getValue();
718
}
719

720
// ----------------------------------------------------------------------------
721

722
PropertyMeshKernel::PropertyMeshKernel()
723
    : _meshObject(new MeshObject())
724
{
725
    // Note: Normally this property is a member of a document object, i.e. the setValue()
726
    // method gets called in the constructor of a subclass of DocumentObject, e.g. Mesh::Feature.
727
    // This means that the created MeshObject here will be replaced and deleted immediately.
728
    // However, we anyway create this object in case we use this class in another context.
729
}
730

731
PropertyMeshKernel::~PropertyMeshKernel()
732
{
733
    if (meshPyObject) {
734
        // Note: Do not call setInvalid() of the Python binding
735
        // because the mesh should still be accessible afterwards.
736
        meshPyObject->parentProperty = nullptr;
737
        Py_DECREF(meshPyObject);
738
    }
739
}
740

741
void PropertyMeshKernel::setValuePtr(MeshObject* mesh)
742
{
743
    // use the tmp. object to guarantee that the referenced mesh is not destroyed
744
    // before calling hasSetValue()
745
    Base::Reference<MeshObject> tmp(_meshObject);
746
    aboutToSetValue();
747
    _meshObject = mesh;
748
    hasSetValue();
749
}
750

751
void PropertyMeshKernel::setValue(const MeshObject& mesh)
752
{
753
    aboutToSetValue();
754
    *_meshObject = mesh;
755
    hasSetValue();
756
}
757

758
void PropertyMeshKernel::setValue(const MeshCore::MeshKernel& mesh)
759
{
760
    aboutToSetValue();
761
    _meshObject->setKernel(mesh);
762
    hasSetValue();
763
}
764

765
void PropertyMeshKernel::swapMesh(MeshObject& mesh)
766
{
767
    aboutToSetValue();
768
    _meshObject->swap(mesh);
769
    hasSetValue();
770
}
771

772
void PropertyMeshKernel::swapMesh(MeshCore::MeshKernel& mesh)
773
{
774
    aboutToSetValue();
775
    _meshObject->swap(mesh);
776
    hasSetValue();
777
}
778

779
const MeshObject& PropertyMeshKernel::getValue() const
780
{
781
    return *_meshObject;
782
}
783

784
const MeshObject* PropertyMeshKernel::getValuePtr() const
785
{
786
    return static_cast<MeshObject*>(_meshObject);
787
}
788

789
const Data::ComplexGeoData* PropertyMeshKernel::getComplexData() const
790
{
791
    return static_cast<MeshObject*>(_meshObject);
792
}
793

794
Base::BoundBox3d PropertyMeshKernel::getBoundingBox() const
795
{
796
    return _meshObject->getBoundBox();
797
}
798

799
unsigned int PropertyMeshKernel::getMemSize() const
800
{
801
    unsigned int size = 0;
802
    size += _meshObject->getMemSize();
803

804
    return size;
805
}
806

807
MeshObject* PropertyMeshKernel::startEditing()
808
{
809
    aboutToSetValue();
810
    return static_cast<MeshObject*>(_meshObject);
811
}
812

813
void PropertyMeshKernel::finishEditing()
814
{
815
    hasSetValue();
816
}
817

818
void PropertyMeshKernel::transformGeometry(const Base::Matrix4D& rclMat)
819
{
820
    aboutToSetValue();
821
    _meshObject->transformGeometry(rclMat);
822
    hasSetValue();
823
}
824

825
void PropertyMeshKernel::setPointIndices(
826
    const std::vector<std::pair<PointIndex, Base::Vector3f>>& inds)
827
{
828
    aboutToSetValue();
829
    MeshCore::MeshKernel& kernel = _meshObject->getKernel();
830
    for (const auto& it : inds) {
831
        kernel.SetPoint(it.first, it.second);
832
    }
833
    hasSetValue();
834
}
835

836
void PropertyMeshKernel::setTransform(const Base::Matrix4D& rclTrf)
837
{
838
    _meshObject->setTransform(rclTrf);
839
}
840

841
Base::Matrix4D PropertyMeshKernel::getTransform() const
842
{
843
    return _meshObject->getTransform();
844
}
845

846
PyObject* PropertyMeshKernel::getPyObject()
847
{
848
    if (!meshPyObject) {
849
        meshPyObject = new MeshPy(
850
            &*_meshObject);  // Lgtm[cpp/resource-not-released-in-destructor] ** Not destroyed in
851
                             // this class because it is reference-counted and destroyed elsewhere
852
        meshPyObject->setConst();  // set immutable
853
        meshPyObject->parentProperty = this;
854
    }
855

856
    Py_INCREF(meshPyObject);
857
    return meshPyObject;
858
}
859

860
void PropertyMeshKernel::setPyObject(PyObject* value)
861
{
862
    if (PyObject_TypeCheck(value, &(MeshPy::Type))) {
863
        MeshPy* mesh = static_cast<MeshPy*>(value);
864
        // Do not allow to reassign the same instance
865
        if (&(*this->_meshObject) != mesh->getMeshObjectPtr()) {
866
            // Note: Copy the content, do NOT reference the same mesh object
867
            setValue(*(mesh->getMeshObjectPtr()));
868
        }
869
    }
870
    else if (PyList_Check(value)) {
871
        // new instance of MeshObject
872
        Py::List triangles(value);
873
        MeshObject* mesh = MeshObject::createMeshFromList(triangles);
874
        setValuePtr(mesh);
875
    }
876
    else {
877
        std::string error = std::string("type must be 'Mesh', not ");
878
        error += value->ob_type->tp_name;
879
        throw Base::TypeError(error);
880
    }
881
}
882

883
void PropertyMeshKernel::Save(Base::Writer& writer) const
884
{
885
    if (writer.isForceXML()) {
886
        writer.Stream() << writer.ind() << "<Mesh>" << std::endl;
887
        MeshCore::MeshOutput saver(_meshObject->getKernel());
888
        saver.SaveXML(writer);
889
    }
890
    else {
891
        writer.Stream() << writer.ind() << "<Mesh file=\"" << writer.addFile("MeshKernel.bms", this)
892
                        << "\"/>" << std::endl;
893
    }
894
}
895

896
void PropertyMeshKernel::Restore(Base::XMLReader& reader)
897
{
898
    reader.readElement("Mesh");
899
    std::string file(reader.getAttribute("file"));
900

901
    if (file.empty()) {
902
        // read XML
903
        MeshCore::MeshKernel kernel;
904
        MeshCore::MeshInput restorer(kernel);
905
        restorer.LoadXML(reader);
906

907
        // avoid to duplicate the mesh in memory
908
        MeshCore::MeshPointArray points;
909
        MeshCore::MeshFacetArray facets;
910
        kernel.Adopt(points, facets);
911

912
        aboutToSetValue();
913
        _meshObject->getKernel().Adopt(points, facets);
914
        hasSetValue();
915
    }
916
    else {
917
        // initiate a file read
918
        reader.addFile(file.c_str(), this);
919
    }
920
}
921

922
void PropertyMeshKernel::SaveDocFile(Base::Writer& writer) const
923
{
924
    _meshObject->save(writer.Stream());
925
}
926

927
void PropertyMeshKernel::RestoreDocFile(Base::Reader& reader)
928
{
929
    aboutToSetValue();
930
    _meshObject->load(reader);
931
    hasSetValue();
932
}
933

934
App::Property* PropertyMeshKernel::Copy() const
935
{
936
    // Note: Copy the content, do NOT reference the same mesh object
937
    PropertyMeshKernel* prop = new PropertyMeshKernel();
938
    *(prop->_meshObject) = *(this->_meshObject);
939
    return prop;
940
}
941

942
void PropertyMeshKernel::Paste(const App::Property& from)
943
{
944
    // Note: Copy the content, do NOT reference the same mesh object
945
    aboutToSetValue();
946
    const PropertyMeshKernel& prop = dynamic_cast<const PropertyMeshKernel&>(from);
947
    *(this->_meshObject) = *(prop._meshObject);
948
    hasSetValue();
949
}
950

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

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

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

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