FreeCAD

Форк
0
/
Mesh.cpp 
2270 строк · 68.5 Кб
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
#ifndef _PreComp_
25
#include <algorithm>
26
#include <sstream>
27
#endif
28

29
#include <Base/Builder3D.h>
30
#include <Base/Console.h>
31
#include <Base/Converter.h>
32
#include <Base/Exception.h>
33
#include <Base/Interpreter.h>
34
#include <Base/Reader.h>
35
#include <Base/Sequencer.h>
36
#include <Base/Stream.h>
37
#include <Base/Tools.h>
38
#include <Base/ViewProj.h>
39
#include <Base/Writer.h>
40

41
#include "Core/Builder.h"
42
#include "Core/Decimation.h"
43
#include "Core/Degeneration.h"
44
#include "Core/Grid.h"
45
#include "Core/Info.h"
46
#include "Core/Iterator.h"
47
#include "Core/MeshKernel.h"
48
#include "Core/Segmentation.h"
49
#include "Core/SetOperations.h"
50
#include "Core/TopoAlgorithm.h"
51
#include "Core/Trim.h"
52
#include "Core/TrimByPlane.h"
53

54
#include "Mesh.h"
55

56

57
using namespace Mesh;
58

59
const float MeshObject::Epsilon = 1.0e-5F;
60

61
TYPESYSTEM_SOURCE(Mesh::MeshObject, Data::ComplexGeoData)
62
TYPESYSTEM_SOURCE(Mesh::MeshSegment, Data::Segment)
63

64
MeshObject::MeshObject() = default;
65

66
MeshObject::MeshObject(const MeshCore::MeshKernel& Kernel)  // NOLINT
67
    : _kernel(Kernel)
68
{
69
    // copy the mesh structure
70
}
71

72
MeshObject::MeshObject(const MeshCore::MeshKernel& Kernel, const Base::Matrix4D& Mtrx)  // NOLINT
73
    : _Mtrx(Mtrx)
74
    , _kernel(Kernel)
75
{
76
    // copy the mesh structure
77
}
78

79
MeshObject::MeshObject(const MeshObject& mesh)
80
    : _Mtrx(mesh._Mtrx)
81
    , _kernel(mesh._kernel)
82
{
83
    // copy the mesh structure
84
    copySegments(mesh);
85
}
86

87
MeshObject::MeshObject(MeshObject&& mesh)
88
    : _Mtrx(mesh._Mtrx)
89
    , _kernel(mesh._kernel)
90
{
91
    // copy the mesh structure
92
    copySegments(mesh);
93
}
94

95
MeshObject::~MeshObject() = default;
96

97
std::vector<const char*> MeshObject::getElementTypes() const
98
{
99
    std::vector<const char*> temp;
100
    temp.push_back("Mesh");
101
    temp.push_back("Segment");
102

103
    return temp;
104
}
105

106
unsigned long MeshObject::countSubElements(const char* Type) const
107
{
108
    std::string element(Type);
109
    if (element == "Mesh") {
110
        return 1;
111
    }
112
    else if (element == "Segment") {
113
        return countSegments();
114
    }
115
    return 0;
116
}
117

118
Data::Segment* MeshObject::getSubElement(const char* Type, unsigned long n) const
119
{
120
    std::string element(Type);
121
    if (element == "Mesh" && n == 0) {
122
        MeshSegment* segm = new MeshSegment();
123
        segm->mesh = new MeshObject(*this);
124
        return segm;
125
    }
126
    else if (element == "Segment" && n < countSegments()) {
127
        MeshSegment* segm = new MeshSegment();
128
        segm->mesh = new MeshObject(*this);
129
        const Segment& faces = getSegment(n);
130
        segm->segment = std::make_unique<Segment>(static_cast<MeshObject*>(segm->mesh),
131
                                                  faces.getIndices(),
132
                                                  false);
133
        return segm;
134
    }
135

136
    return nullptr;
137
}
138

139
void MeshObject::getFacesFromSubElement(const Data::Segment* element,
140
                                        std::vector<Base::Vector3d>& points,
141
                                        std::vector<Base::Vector3d>& /*pointNormals*/,
142
                                        std::vector<Facet>& faces) const
143
{
144
    if (element && element->is<MeshSegment>()) {
145
        const MeshSegment* segm = static_cast<const MeshSegment*>(element);
146
        if (segm->segment) {
147
            Base::Reference<MeshObject> submesh(
148
                segm->mesh->meshFromSegment(segm->segment->getIndices()));
149
            submesh->getFaces(points, faces, 0.0);
150
        }
151
        else {
152
            segm->mesh->getFaces(points, faces, 0.0);
153
        }
154
    }
155
}
156

157
void MeshObject::transformGeometry(const Base::Matrix4D& rclMat)
158
{
159
    MeshCore::MeshKernel kernel;
160
    swap(kernel);
161
    kernel.Transform(rclMat);
162
    swap(kernel);
163
}
164

165
void MeshObject::setTransform(const Base::Matrix4D& rclTrf)
166
{
167
    _Mtrx = rclTrf;
168
}
169

170
Base::Matrix4D MeshObject::getTransform() const
171
{
172
    return _Mtrx;
173
}
174

175
Base::BoundBox3d MeshObject::getBoundBox() const
176
{
177
    _kernel.RecalcBoundBox();
178
    Base::BoundBox3f Bnd = _kernel.GetBoundBox();
179

180
    Base::BoundBox3d Bnd2;
181
    if (Bnd.IsValid()) {
182
        for (int i = 0; i <= 7; i++) {
183
            Bnd2.Add(transformPointToOutside(Bnd.CalcPoint(Base::BoundBox3f::CORNER(i))));
184
        }
185
    }
186

187
    return Bnd2;
188
}
189

190
bool MeshObject::getCenterOfGravity(Base::Vector3d& center) const
191
{
192
    MeshCore::MeshAlgorithm alg(_kernel);
193
    Base::Vector3f pnt = alg.GetGravityPoint();
194
    center = transformPointToOutside(pnt);
195
    return true;
196
}
197

198
void MeshObject::copySegments(const MeshObject& mesh)
199
{
200
    // After copying the segments the mesh pointers must be adjusted
201
    this->_segments = mesh._segments;
202
    std::for_each(this->_segments.begin(), this->_segments.end(), [this](Segment& s) {
203
        s._mesh = this;
204
    });
205
}
206

207
void MeshObject::swapSegments(MeshObject& mesh)
208
{
209
    this->_segments.swap(mesh._segments);
210
    std::for_each(this->_segments.begin(), this->_segments.end(), [this](Segment& s) {
211
        s._mesh = this;
212
    });
213
    std::for_each(mesh._segments.begin(), mesh._segments.end(), [&mesh](Segment& s) {
214
        s._mesh = &mesh;
215
    });
216
}
217

218
MeshObject& MeshObject::operator=(const MeshObject& mesh)
219
{
220
    if (this != &mesh) {
221
        // copy the mesh structure
222
        setTransform(mesh._Mtrx);
223
        this->_kernel = mesh._kernel;
224
        copySegments(mesh);
225
    }
226

227
    return *this;
228
}
229

230
MeshObject& MeshObject::operator=(MeshObject&& mesh)
231
{
232
    if (this != &mesh) {
233
        // copy the mesh structure
234
        setTransform(mesh._Mtrx);
235
        this->_kernel = mesh._kernel;
236
        copySegments(mesh);
237
    }
238

239
    return *this;
240
}
241

242
void MeshObject::setKernel(const MeshCore::MeshKernel& m)
243
{
244
    this->_kernel = m;
245
    this->_segments.clear();
246
}
247

248
void MeshObject::swap(MeshCore::MeshKernel& Kernel)
249
{
250
    this->_kernel.Swap(Kernel);
251
    // clear the segments because we don't know how the new
252
    // topology looks like
253
    this->_segments.clear();
254
}
255

256
void MeshObject::swap(MeshObject& mesh)
257
{
258
    this->_kernel.Swap(mesh._kernel);
259
    swapSegments(mesh);
260
    Base::Matrix4D tmp = this->_Mtrx;
261
    this->_Mtrx = mesh._Mtrx;
262
    mesh._Mtrx = tmp;
263
}
264

265
std::string MeshObject::representation() const
266
{
267
    std::stringstream str;
268
    MeshCore::MeshInfo info(_kernel);
269
    info.GeneralInformation(str);
270
    return str.str();
271
}
272

273
std::string MeshObject::topologyInfo() const
274
{
275
    std::stringstream str;
276
    MeshCore::MeshInfo info(_kernel);
277
    info.TopologyInformation(str);
278
    return str.str();
279
}
280

281
unsigned long MeshObject::countPoints() const
282
{
283
    return _kernel.CountPoints();
284
}
285

286
unsigned long MeshObject::countFacets() const
287
{
288
    return _kernel.CountFacets();
289
}
290

291
unsigned long MeshObject::countEdges() const
292
{
293
    return _kernel.CountEdges();
294
}
295

296
unsigned long MeshObject::countSegments() const
297
{
298
    return this->_segments.size();
299
}
300

301
bool MeshObject::isSolid() const
302
{
303
    MeshCore::MeshEvalSolid cMeshEval(_kernel);
304
    return cMeshEval.Evaluate();
305
}
306

307
double MeshObject::getSurface() const
308
{
309
    return _kernel.GetSurface();
310
}
311

312
double MeshObject::getVolume() const
313
{
314
    return _kernel.GetVolume();
315
}
316

317
Base::Vector3d MeshObject::getPoint(PointIndex index) const
318
{
319
    MeshCore::MeshPoint vertf = _kernel.GetPoint(index);
320
    Base::Vector3d vertd(vertf.x, vertf.y, vertf.z);
321
    vertd = _Mtrx * vertd;
322
    return vertd;
323
}
324

325
MeshPoint MeshObject::getMeshPoint(PointIndex index) const
326
{
327
    MeshPoint point(getPoint(index), this, index);
328
    return point;
329
}
330

331
void MeshObject::getPoints(std::vector<Base::Vector3d>& Points,
332
                           std::vector<Base::Vector3d>& Normals,
333
                           double /*Accuracy*/,
334
                           uint16_t /*flags*/) const
335
{
336
    Points = transformPointsToOutside(_kernel.GetPoints());
337
    MeshCore::MeshRefNormalToPoints ptNormals(_kernel);
338
    Normals = transformVectorsToOutside(ptNormals.GetValues());
339
}
340

341
Mesh::Facet MeshObject::getMeshFacet(FacetIndex index) const
342
{
343
    Mesh::Facet face(_kernel.GetFacets()[index], this, index);
344
    return face;
345
}
346

347
void MeshObject::getFaces(std::vector<Base::Vector3d>& Points,
348
                          std::vector<Facet>& Topo,
349
                          double /*Accuracy*/,
350
                          uint16_t /*flags*/) const
351
{
352
    unsigned long ctpoints = _kernel.CountPoints();
353
    Points.reserve(ctpoints);
354
    for (unsigned long i = 0; i < ctpoints; i++) {
355
        Points.push_back(getPoint(i));
356
    }
357

358
    unsigned long ctfacets = _kernel.CountFacets();
359
    const MeshCore::MeshFacetArray& ary = _kernel.GetFacets();
360
    Topo.reserve(ctfacets);
361
    for (unsigned long i = 0; i < ctfacets; i++) {
362
        Facet face {};
363
        face.I1 = (unsigned int)ary[i]._aulPoints[0];
364
        face.I2 = (unsigned int)ary[i]._aulPoints[1];
365
        face.I3 = (unsigned int)ary[i]._aulPoints[2];
366
        Topo.push_back(face);
367
    }
368
}
369

370
unsigned int MeshObject::getMemSize() const
371
{
372
    return _kernel.GetMemSize();
373
}
374

375
void MeshObject::Save(Base::Writer& /*writer*/) const
376
{
377
    // this is handled by the property class
378
}
379

380
void MeshObject::SaveDocFile(Base::Writer& writer) const
381
{
382
    _kernel.Write(writer.Stream());
383
}
384

385
void MeshObject::Restore(Base::XMLReader& /*reader*/)
386
{
387
    // this is handled by the property class
388
}
389

390
void MeshObject::RestoreDocFile(Base::Reader& reader)
391
{
392
    load(reader);
393
}
394

395
void MeshObject::save(const char* file,
396
                      MeshCore::MeshIO::Format f,
397
                      const MeshCore::Material* mat,
398
                      const char* objectname) const
399
{
400
    MeshCore::MeshOutput aWriter(this->_kernel, mat);
401
    if (objectname) {
402
        aWriter.SetObjectName(objectname);
403
    }
404

405
    // go through the segment list and put them to the exporter when
406
    // the "save" flag is set
407
    std::vector<MeshCore::Group> groups;
408
    for (const auto& segment : this->_segments) {
409
        if (segment.isSaved()) {
410
            MeshCore::Group g;
411
            g.indices = segment.getIndices();
412
            g.name = segment.getName();
413
            groups.push_back(g);
414
        }
415
    }
416
    aWriter.SetGroups(groups);
417
    if (mat && mat->library.empty()) {
418
        Base::FileInfo fi(file);
419
        mat->library = fi.fileNamePure() + ".mtl";
420
    }
421

422
    aWriter.Transform(this->_Mtrx);
423
    aWriter.SaveAny(file, f);
424
}
425

426
void MeshObject::save(std::ostream& str,
427
                      MeshCore::MeshIO::Format f,
428
                      const MeshCore::Material* mat,
429
                      const char* objectname) const
430
{
431
    MeshCore::MeshOutput aWriter(this->_kernel, mat);
432
    if (objectname) {
433
        aWriter.SetObjectName(objectname);
434
    }
435

436
    // go through the segment list and put them to the exporter when
437
    // the "save" flag is set
438
    std::vector<MeshCore::Group> groups;
439
    for (const auto& segment : this->_segments) {
440
        if (segment.isSaved()) {
441
            MeshCore::Group g;
442
            g.indices = segment.getIndices();
443
            g.name = segment.getName();
444
            groups.push_back(g);
445
        }
446
    }
447
    aWriter.SetGroups(groups);
448

449
    aWriter.Transform(this->_Mtrx);
450
    aWriter.SaveFormat(str, f);
451
}
452

453
bool MeshObject::load(const char* file, MeshCore::Material* mat)
454
{
455
    MeshCore::MeshKernel kernel;
456
    MeshCore::MeshInput aReader(kernel, mat);
457
    if (!aReader.LoadAny(file)) {
458
        return false;
459
    }
460

461
    swapKernel(kernel, aReader.GetGroupNames());
462
    return true;
463
}
464

465
bool MeshObject::load(std::istream& str, MeshCore::MeshIO::Format f, MeshCore::Material* mat)
466
{
467
    MeshCore::MeshKernel kernel;
468
    MeshCore::MeshInput aReader(kernel, mat);
469
    if (!aReader.LoadFormat(str, f)) {
470
        return false;
471
    }
472

473
    swapKernel(kernel, aReader.GetGroupNames());
474
    return true;
475
}
476

477
void MeshObject::swapKernel(MeshCore::MeshKernel& kernel, const std::vector<std::string>& g)
478
{
479
    _kernel.Swap(kernel);
480
    // Some file formats define several objects per file (e.g. OBJ).
481
    // Now we mark each object as an own segment so that we can break
482
    // the object into its original objects again.
483
    this->_segments.clear();
484
    const MeshCore::MeshFacetArray& faces = _kernel.GetFacets();
485
    MeshCore::MeshFacetArray::_TConstIterator it;
486
    std::vector<FacetIndex> segment;
487
    segment.reserve(faces.size());
488
    unsigned long prop = 0;
489
    unsigned long index = 0;
490
    for (it = faces.begin(); it != faces.end(); ++it) {
491
        if (prop < it->_ulProp) {
492
            prop = it->_ulProp;
493
            if (!segment.empty()) {
494
                this->_segments.emplace_back(this, segment, true);
495
                segment.clear();
496
            }
497
        }
498

499
        segment.push_back(index++);
500
    }
501

502
    // if the whole mesh is a single object then don't mark as segment
503
    if (!segment.empty() && (segment.size() < faces.size())) {
504
        this->_segments.emplace_back(this, segment, true);
505
    }
506

507
    // apply the group names to the segments
508
    if (this->_segments.size() == g.size()) {
509
        for (std::size_t index = 0; index < this->_segments.size(); index++) {
510
            this->_segments[index].setName(g[index]);
511
        }
512
    }
513
}
514

515
void MeshObject::save(std::ostream& out) const
516
{
517
    _kernel.Write(out);
518
}
519

520
void MeshObject::load(std::istream& in)
521
{
522
    _kernel.Read(in);
523
    this->_segments.clear();
524

525
#ifndef FC_DEBUG
526
    try {
527
        MeshCore::MeshEvalNeighbourhood nb(_kernel);
528
        if (!nb.Evaluate()) {
529
            Base::Console().Warning("Errors in neighbourhood of mesh found...");
530
            _kernel.RebuildNeighbours();
531
            Base::Console().Warning("fixed\n");
532
        }
533

534
        MeshCore::MeshEvalTopology eval(_kernel);
535
        if (!eval.Evaluate()) {
536
            Base::Console().Warning("The mesh data structure has some defects\n");
537
        }
538
    }
539
    catch (const Base::MemoryException&) {
540
        // ignore memory exceptions and continue
541
        Base::Console().Log("Check for defects in mesh data structure failed\n");
542
    }
543
#endif
544
}
545

546
void MeshObject::writeInventor(std::ostream& str, float creaseangle) const
547
{
548
    const MeshCore::MeshPointArray& point = getKernel().GetPoints();
549
    const MeshCore::MeshFacetArray& faces = getKernel().GetFacets();
550

551
    std::vector<Base::Vector3f> coords;
552
    coords.reserve(point.size());
553
    std::copy(point.begin(), point.end(), std::back_inserter(coords));
554

555
    std::vector<int> indices;
556
    indices.reserve(4 * faces.size());
557
    for (const auto& it : faces) {
558
        indices.push_back(it._aulPoints[0]);
559
        indices.push_back(it._aulPoints[1]);
560
        indices.push_back(it._aulPoints[2]);
561
        indices.push_back(-1);
562
    }
563

564
    Base::InventorBuilder builder(str);
565
    builder.beginSeparator();
566
    builder.addNode(Base::TransformItem {getTransform()});
567
    Base::ShapeHintsItem shapeHints {creaseangle};
568
    builder.addNode(shapeHints);
569
    builder.addNode(Base::Coordinate3Item {coords});
570
    builder.addNode(Base::IndexedFaceSetItem {indices});
571
    builder.endSeparator();
572
}
573

574
void MeshObject::addFacet(const MeshCore::MeshGeomFacet& facet)
575
{
576
    _kernel.AddFacet(facet);
577
}
578

579
void MeshObject::addFacets(const std::vector<MeshCore::MeshGeomFacet>& facets)
580
{
581
    _kernel.AddFacets(facets);
582
}
583

584
void MeshObject::addFacets(const std::vector<MeshCore::MeshFacet>& facets, bool checkManifolds)
585
{
586
    _kernel.AddFacets(facets, checkManifolds);
587
}
588

589
void MeshObject::addFacets(const std::vector<MeshCore::MeshFacet>& facets,
590
                           const std::vector<Base::Vector3f>& points,
591
                           bool checkManifolds)
592
{
593
    _kernel.AddFacets(facets, points, checkManifolds);
594
}
595

596
void MeshObject::addFacets(const std::vector<Data::ComplexGeoData::Facet>& facets,
597
                           const std::vector<Base::Vector3d>& points,
598
                           bool checkManifolds)
599
{
600
    std::vector<MeshCore::MeshFacet> facet_v;
601
    facet_v.reserve(facets.size());
602
    for (auto facet : facets) {
603
        MeshCore::MeshFacet f;
604
        f._aulPoints[0] = facet.I1;
605
        f._aulPoints[1] = facet.I2;
606
        f._aulPoints[2] = facet.I3;
607
        facet_v.push_back(f);
608
    }
609

610
    std::vector<Base::Vector3f> point_v;
611
    point_v.reserve(points.size());
612
    for (const auto& point : points) {
613
        Base::Vector3f p((float)point.x, (float)point.y, (float)point.z);
614
        point_v.push_back(p);
615
    }
616

617
    _kernel.AddFacets(facet_v, point_v, checkManifolds);
618
}
619

620
void MeshObject::setFacets(const std::vector<MeshCore::MeshGeomFacet>& facets)
621
{
622
    _kernel = facets;
623
}
624

625
void MeshObject::setFacets(const std::vector<Data::ComplexGeoData::Facet>& facets,
626
                           const std::vector<Base::Vector3d>& points)
627
{
628
    MeshCore::MeshFacetArray facet_v;
629
    facet_v.reserve(facets.size());
630
    for (auto facet : facets) {
631
        MeshCore::MeshFacet f;
632
        f._aulPoints[0] = facet.I1;
633
        f._aulPoints[1] = facet.I2;
634
        f._aulPoints[2] = facet.I3;
635
        facet_v.push_back(f);
636
    }
637

638
    MeshCore::MeshPointArray point_v;
639
    point_v.reserve(points.size());
640
    for (const auto& point : points) {
641
        Base::Vector3f p((float)point.x, (float)point.y, (float)point.z);
642
        point_v.push_back(p);
643
    }
644

645
    _kernel.Adopt(point_v, facet_v, true);
646
}
647

648
void MeshObject::addMesh(const MeshObject& mesh)
649
{
650
    _kernel.Merge(mesh._kernel);
651
}
652

653
void MeshObject::addMesh(const MeshCore::MeshKernel& kernel)
654
{
655
    _kernel.Merge(kernel);
656
}
657

658
void MeshObject::deleteFacets(const std::vector<FacetIndex>& removeIndices)
659
{
660
    if (removeIndices.empty()) {
661
        return;
662
    }
663
    _kernel.DeleteFacets(removeIndices);
664
    deletedFacets(removeIndices);
665
}
666

667
void MeshObject::deletePoints(const std::vector<PointIndex>& removeIndices)
668
{
669
    if (removeIndices.empty()) {
670
        return;
671
    }
672
    _kernel.DeletePoints(removeIndices);
673
    this->_segments.clear();
674
}
675

676
void MeshObject::deletedFacets(const std::vector<FacetIndex>& remFacets)
677
{
678
    if (remFacets.empty()) {
679
        return;  // nothing has changed
680
    }
681
    if (this->_segments.empty()) {
682
        return;  // nothing to do
683
    }
684
    // set an array with the original indices and mark the removed as MeshCore::FACET_INDEX_MAX
685
    std::vector<FacetIndex> f_indices(_kernel.CountFacets() + remFacets.size());
686
    for (FacetIndex remFacet : remFacets) {
687
        f_indices[remFacet] = MeshCore::FACET_INDEX_MAX;
688
    }
689

690
    FacetIndex index = 0;
691
    for (FacetIndex& it : f_indices) {
692
        if (it == 0) {
693
            it = index++;
694
        }
695
    }
696

697
    // the array serves now as LUT to set the new indices in the segments
698
    for (auto& segment : this->_segments) {
699
        std::vector<FacetIndex> segm = segment._indices;
700
        for (FacetIndex& jt : segm) {
701
            jt = f_indices[jt];
702
        }
703

704
        // remove the invalid indices
705
        std::sort(segm.begin(), segm.end());
706
        std::vector<FacetIndex>::iterator ft =
707
            std::find_if(segm.begin(), segm.end(), [](FacetIndex v) {
708
                return v == MeshCore::FACET_INDEX_MAX;
709
            });
710
        if (ft != segm.end()) {
711
            segm.erase(ft, segm.end());
712
        }
713
        segment._indices = segm;
714
    }
715
}
716

717
void MeshObject::deleteSelectedFacets()
718
{
719
    std::vector<FacetIndex> facets;
720
    MeshCore::MeshAlgorithm(this->_kernel).GetFacetsFlag(facets, MeshCore::MeshFacet::SELECTED);
721
    deleteFacets(facets);
722
}
723

724
void MeshObject::deleteSelectedPoints()
725
{
726
    std::vector<PointIndex> points;
727
    MeshCore::MeshAlgorithm(this->_kernel).GetPointsFlag(points, MeshCore::MeshPoint::SELECTED);
728
    deletePoints(points);
729
}
730

731
void MeshObject::clearFacetSelection() const
732
{
733
    MeshCore::MeshAlgorithm(this->_kernel).ResetFacetFlag(MeshCore::MeshFacet::SELECTED);
734
}
735

736
void MeshObject::clearPointSelection() const
737
{
738
    MeshCore::MeshAlgorithm(this->_kernel).ResetPointFlag(MeshCore::MeshPoint::SELECTED);
739
}
740

741
void MeshObject::addFacetsToSelection(const std::vector<FacetIndex>& inds) const
742
{
743
    MeshCore::MeshAlgorithm(this->_kernel).SetFacetsFlag(inds, MeshCore::MeshFacet::SELECTED);
744
}
745

746
void MeshObject::addPointsToSelection(const std::vector<PointIndex>& inds) const
747
{
748
    MeshCore::MeshAlgorithm(this->_kernel).SetPointsFlag(inds, MeshCore::MeshPoint::SELECTED);
749
}
750

751
void MeshObject::removeFacetsFromSelection(const std::vector<FacetIndex>& inds) const
752
{
753
    MeshCore::MeshAlgorithm(this->_kernel).ResetFacetsFlag(inds, MeshCore::MeshFacet::SELECTED);
754
}
755

756
void MeshObject::removePointsFromSelection(const std::vector<PointIndex>& inds) const
757
{
758
    MeshCore::MeshAlgorithm(this->_kernel).ResetPointsFlag(inds, MeshCore::MeshPoint::SELECTED);
759
}
760

761
void MeshObject::getFacetsFromSelection(std::vector<FacetIndex>& inds) const
762
{
763
    MeshCore::MeshAlgorithm(this->_kernel).GetFacetsFlag(inds, MeshCore::MeshFacet::SELECTED);
764
}
765

766
void MeshObject::getPointsFromSelection(std::vector<PointIndex>& inds) const
767
{
768
    MeshCore::MeshAlgorithm(this->_kernel).GetPointsFlag(inds, MeshCore::MeshPoint::SELECTED);
769
}
770

771
unsigned long MeshObject::countSelectedFacets() const
772
{
773
    return MeshCore::MeshAlgorithm(this->_kernel).CountFacetFlag(MeshCore::MeshFacet::SELECTED);
774
}
775

776
bool MeshObject::hasSelectedFacets() const
777
{
778
    return (countSelectedFacets() > 0);
779
}
780

781
unsigned long MeshObject::countSelectedPoints() const
782
{
783
    return MeshCore::MeshAlgorithm(this->_kernel).CountPointFlag(MeshCore::MeshPoint::SELECTED);
784
}
785

786
bool MeshObject::hasSelectedPoints() const
787
{
788
    return (countSelectedPoints() > 0);
789
}
790

791
std::vector<PointIndex> MeshObject::getPointsFromFacets(const std::vector<FacetIndex>& facets) const
792
{
793
    return _kernel.GetFacetPoints(facets);
794
}
795

796
bool MeshObject::nearestFacetOnRay(const MeshObject::TRay& ray,
797
                                   double maxAngle,
798
                                   MeshObject::TFaceSection& output) const
799
{
800
    Base::Vector3f pnt = Base::toVector<float>(ray.first);
801
    Base::Vector3f dir = Base::toVector<float>(ray.second);
802

803
    Base::Placement plm = getPlacement();
804
    Base::Placement inv = plm.inverse();
805

806
    // transform the ray relative to the mesh kernel
807
    inv.multVec(pnt, pnt);
808
    inv.getRotation().multVec(dir, dir);
809

810
    FacetIndex index = 0;
811
    Base::Vector3f res;
812
    MeshCore::MeshAlgorithm alg(getKernel());
813

814
    if (alg.NearestFacetOnRay(pnt, dir, static_cast<float>(maxAngle), res, index)) {
815
        plm.multVec(res, res);
816
        output.first = index;
817
        output.second = Base::toVector<double>(res);
818
        return true;
819
    }
820

821
    return false;
822
}
823

824
std::vector<MeshObject::TFaceSection> MeshObject::foraminate(const TRay& ray, double maxAngle) const
825
{
826
    Base::Vector3f pnt = Base::toVector<float>(ray.first);
827
    Base::Vector3f dir = Base::toVector<float>(ray.second);
828

829
    Base::Placement plm = getPlacement();
830
    Base::Placement inv = plm.inverse();
831

832
    // transform the ray relative to the mesh kernel
833
    inv.multVec(pnt, pnt);
834
    inv.getRotation().multVec(dir, dir);
835

836
    Base::Vector3f res;
837
    MeshCore::MeshFacetIterator f_it(getKernel());
838
    int index = 0;
839

840
    std::vector<MeshObject::TFaceSection> output;
841
    for (f_it.Begin(); f_it.More(); f_it.Next(), index++) {
842
        if (f_it->Foraminate(pnt, dir, res, static_cast<float>(maxAngle))) {
843
            plm.multVec(res, res);
844

845
            MeshObject::TFaceSection section;
846
            section.first = index;
847
            section.second = Base::toVector<double>(res);
848
            output.push_back(section);
849
        }
850
    }
851

852
    return output;
853
}
854

855
void MeshObject::updateMesh(const std::vector<FacetIndex>& facets) const
856
{
857
    std::vector<PointIndex> points;
858
    points = _kernel.GetFacetPoints(facets);
859

860
    MeshCore::MeshAlgorithm alg(_kernel);
861
    alg.SetFacetsFlag(facets, MeshCore::MeshFacet::SEGMENT);
862
    alg.SetPointsFlag(points, MeshCore::MeshPoint::SEGMENT);
863
}
864

865
void MeshObject::updateMesh() const
866
{
867
    MeshCore::MeshAlgorithm alg(_kernel);
868
    alg.ResetFacetFlag(MeshCore::MeshFacet::SEGMENT);
869
    alg.ResetPointFlag(MeshCore::MeshPoint::SEGMENT);
870
    for (const auto& segment : this->_segments) {
871
        std::vector<PointIndex> points;
872
        points = _kernel.GetFacetPoints(segment.getIndices());
873
        alg.SetFacetsFlag(segment.getIndices(), MeshCore::MeshFacet::SEGMENT);
874
        alg.SetPointsFlag(points, MeshCore::MeshPoint::SEGMENT);
875
    }
876
}
877

878
std::vector<std::vector<FacetIndex>> MeshObject::getComponents() const
879
{
880
    std::vector<std::vector<FacetIndex>> segments;
881
    MeshCore::MeshComponents comp(_kernel);
882
    comp.SearchForComponents(MeshCore::MeshComponents::OverEdge, segments);
883
    return segments;
884
}
885

886
unsigned long MeshObject::countComponents() const
887
{
888
    std::vector<std::vector<FacetIndex>> segments;
889
    MeshCore::MeshComponents comp(_kernel);
890
    comp.SearchForComponents(MeshCore::MeshComponents::OverEdge, segments);
891
    return segments.size();
892
}
893

894
void MeshObject::removeComponents(unsigned long count)
895
{
896
    std::vector<FacetIndex> removeIndices;
897
    MeshCore::MeshTopoAlgorithm(_kernel).FindComponents(count, removeIndices);
898
    _kernel.DeleteFacets(removeIndices);
899
    deletedFacets(removeIndices);
900
}
901

902
unsigned long MeshObject::getPointDegree(const std::vector<FacetIndex>& indices,
903
                                         std::vector<PointIndex>& point_degree) const
904
{
905
    const MeshCore::MeshFacetArray& faces = _kernel.GetFacets();
906
    std::vector<PointIndex> pointDeg(_kernel.CountPoints());
907

908
    for (const auto& face : faces) {
909
        pointDeg[face._aulPoints[0]]++;
910
        pointDeg[face._aulPoints[1]]++;
911
        pointDeg[face._aulPoints[2]]++;
912
    }
913

914
    for (FacetIndex it : indices) {
915
        const MeshCore::MeshFacet& face = faces[it];
916
        pointDeg[face._aulPoints[0]]--;
917
        pointDeg[face._aulPoints[1]]--;
918
        pointDeg[face._aulPoints[2]]--;
919
    }
920

921
    unsigned long countInvalids = std::count_if(pointDeg.begin(), pointDeg.end(), [](PointIndex v) {
922
        return v == 0;
923
    });
924

925
    point_degree.swap(pointDeg);
926
    return countInvalids;
927
}
928

929
void MeshObject::fillupHoles(unsigned long length,
930
                             int level,
931
                             MeshCore::AbstractPolygonTriangulator& cTria)
932
{
933
    std::list<std::vector<PointIndex>> aFailed;
934
    MeshCore::MeshTopoAlgorithm topalg(_kernel);
935
    topalg.FillupHoles(length, level, cTria, aFailed);
936
}
937

938
void MeshObject::offset(float fSize)
939
{
940
    std::vector<Base::Vector3f> normals = _kernel.CalcVertexNormals();
941

942
    unsigned int i = 0;
943
    // go through all the vertex normals
944
    for (std::vector<Base::Vector3f>::iterator It = normals.begin(); It != normals.end();
945
         ++It, i++) {
946
        // and move each mesh point in the normal direction
947
        _kernel.MovePoint(i, It->Normalize() * fSize);
948
    }
949
    _kernel.RecalcBoundBox();
950
}
951

952
void MeshObject::offsetSpecial2(float fSize)
953
{
954
    Base::Builder3D builder;
955
    std::vector<Base::Vector3f> PointNormals = _kernel.CalcVertexNormals();
956
    std::vector<Base::Vector3f> FaceNormals;
957
    std::set<FacetIndex> fliped;
958

959
    MeshCore::MeshFacetIterator it(_kernel);
960
    for (it.Init(); it.More(); it.Next()) {
961
        FaceNormals.push_back(it->GetNormal().Normalize());
962
    }
963

964
    unsigned int i = 0;
965

966
    // go through all the vertex normals
967
    for (std::vector<Base::Vector3f>::iterator It = PointNormals.begin(); It != PointNormals.end();
968
         ++It, i++) {
969
        Base::Line3f line {_kernel.GetPoint(i), _kernel.GetPoint(i) + It->Normalize() * fSize};
970
        Base::DrawStyle drawStyle;
971
        builder.addNode(Base::LineItem {line, drawStyle});
972
        // and move each mesh point in the normal direction
973
        _kernel.MovePoint(i, It->Normalize() * fSize);
974
    }
975
    _kernel.RecalcBoundBox();
976

977
    MeshCore::MeshTopoAlgorithm alg(_kernel);
978

979
    for (int l = 0; l < 1; l++) {
980
        for (it.Init(), i = 0; it.More(); it.Next(), i++) {
981
            if (it->IsFlag(MeshCore::MeshFacet::INVALID)) {
982
                continue;
983
            }
984
            // calculate the angle between them
985
            float angle = acos((FaceNormals[i] * it->GetNormal())
986
                               / (it->GetNormal().Length() * FaceNormals[i].Length()));
987
            if (angle > 1.6) {
988
                Base::DrawStyle drawStyle;
989
                drawStyle.pointSize = 4.0F;
990
                Base::PointItem item {it->GetGravityPoint(),
991
                                      drawStyle,
992
                                      Base::ColorRGB {1.0F, 0.0F, 0.0F}};
993
                builder.addNode(item);
994
                fliped.insert(it.Position());
995
            }
996
        }
997

998
        // if there are no flipped triangles -> stop
999
        // int f =fliped.size();
1000
        if (fliped.empty()) {
1001
            break;
1002
        }
1003

1004
        for (FacetIndex It : fliped) {
1005
            alg.CollapseFacet(It);
1006
        }
1007
        fliped.clear();
1008
    }
1009

1010
    alg.Cleanup();
1011

1012
    // search for intersected facets
1013
    MeshCore::MeshEvalSelfIntersection eval(_kernel);
1014
    std::vector<std::pair<FacetIndex, FacetIndex>> faces;
1015
    eval.GetIntersections(faces);
1016
    builder.saveToLog();
1017
}
1018

1019
void MeshObject::offsetSpecial(float fSize, float zmax, float zmin)
1020
{
1021
    std::vector<Base::Vector3f> normals = _kernel.CalcVertexNormals();
1022

1023
    unsigned int i = 0;
1024
    // go through all the vertex normals
1025
    for (std::vector<Base::Vector3f>::iterator It = normals.begin(); It != normals.end();
1026
         ++It, i++) {
1027
        auto Pnt = _kernel.GetPoint(i);
1028
        if (Pnt.z < zmax && Pnt.z > zmin) {
1029
            Pnt.z = 0;
1030
            _kernel.MovePoint(i, Pnt.Normalize() * fSize);
1031
        }
1032
        else {
1033
            // and move each mesh point in the normal direction
1034
            _kernel.MovePoint(i, It->Normalize() * fSize);
1035
        }
1036
    }
1037
}
1038

1039
void MeshObject::clear()
1040
{
1041
    _kernel.Clear();
1042
    this->_segments.clear();
1043
    setTransform(Base::Matrix4D());
1044
}
1045

1046
void MeshObject::transformToEigenSystem()
1047
{
1048
    MeshCore::MeshEigensystem cMeshEval(_kernel);
1049
    cMeshEval.Evaluate();
1050
    this->setTransform(cMeshEval.Transform());
1051
}
1052

1053
Base::Matrix4D MeshObject::getEigenSystem(Base::Vector3d& v) const
1054
{
1055
    MeshCore::MeshEigensystem cMeshEval(_kernel);
1056
    cMeshEval.Evaluate();
1057
    Base::Vector3f uvw = cMeshEval.GetBoundings();
1058
    v.Set(uvw.x, uvw.y, uvw.z);
1059
    return cMeshEval.Transform();
1060
}
1061

1062
void MeshObject::movePoint(PointIndex index, const Base::Vector3d& v)
1063
{
1064
    // v is a vector, hence we must not apply the translation part
1065
    // of the transformation to the vector
1066
    Base::Vector3d vec(v);
1067
    vec.x += _Mtrx[0][3];
1068
    vec.y += _Mtrx[1][3];
1069
    vec.z += _Mtrx[2][3];
1070
    _kernel.MovePoint(index, transformPointToInside(vec));
1071
}
1072

1073
void MeshObject::setPoint(PointIndex index, const Base::Vector3d& p)
1074
{
1075
    _kernel.SetPoint(index, transformPointToInside(p));
1076
}
1077

1078
void MeshObject::smooth(int iterations, float d_max)
1079
{
1080
    _kernel.Smooth(iterations, d_max);
1081
}
1082

1083
void MeshObject::decimate(float fTolerance, float fReduction)
1084
{
1085
    MeshCore::MeshSimplify dm(this->_kernel);
1086
    dm.simplify(fTolerance, fReduction);
1087
}
1088

1089
void MeshObject::decimate(int targetSize)
1090
{
1091
    MeshCore::MeshSimplify dm(this->_kernel);
1092
    dm.simplify(targetSize);
1093
}
1094

1095
Base::Vector3d MeshObject::getPointNormal(PointIndex index) const
1096
{
1097
    std::vector<Base::Vector3f> temp = _kernel.CalcVertexNormals();
1098
    Base::Vector3d normal = transformVectorToOutside(temp[index]);
1099
    normal.Normalize();
1100
    return normal;
1101
}
1102

1103
std::vector<Base::Vector3d> MeshObject::getPointNormals() const
1104
{
1105
    std::vector<Base::Vector3f> temp = _kernel.CalcVertexNormals();
1106

1107
    std::vector<Base::Vector3d> normals = transformVectorsToOutside(temp);
1108
    for (auto& n : normals) {
1109
        n.Normalize();
1110
    }
1111
    return normals;
1112
}
1113

1114
void MeshObject::crossSections(const std::vector<MeshObject::TPlane>& planes,
1115
                               std::vector<MeshObject::TPolylines>& sections,
1116
                               float fMinEps,
1117
                               bool bConnectPolygons) const
1118
{
1119
    MeshCore::MeshKernel kernel(this->_kernel);
1120
    kernel.Transform(this->_Mtrx);
1121

1122
    MeshCore::MeshFacetGrid grid(kernel);
1123
    MeshCore::MeshAlgorithm algo(kernel);
1124
    for (const auto& plane : planes) {
1125
        MeshObject::TPolylines polylines;
1126
        algo.CutWithPlane(plane.first, plane.second, grid, polylines, fMinEps, bConnectPolygons);
1127
        sections.push_back(polylines);
1128
    }
1129
}
1130

1131
void MeshObject::cut(const Base::Polygon2d& polygon2d,
1132
                     const Base::ViewProjMethod& proj,
1133
                     MeshObject::CutType type)
1134
{
1135
    MeshCore::MeshKernel kernel(this->_kernel);
1136
    kernel.Transform(getTransform());
1137

1138
    MeshCore::MeshAlgorithm meshAlg(kernel);
1139
    std::vector<FacetIndex> check;
1140

1141
    bool inner {};
1142
    switch (type) {
1143
        case INNER:
1144
            inner = true;
1145
            break;
1146
        case OUTER:
1147
            inner = false;
1148
            break;
1149
        default:
1150
            inner = true;
1151
            break;
1152
    }
1153

1154
    MeshCore::MeshFacetGrid meshGrid(kernel);
1155
    meshAlg.CheckFacets(meshGrid, &proj, polygon2d, inner, check);
1156
    if (!check.empty()) {
1157
        this->deleteFacets(check);
1158
    }
1159
}
1160

1161
void MeshObject::trim(const Base::Polygon2d& polygon2d,
1162
                      const Base::ViewProjMethod& proj,
1163
                      MeshObject::CutType type)
1164
{
1165
    MeshCore::MeshKernel kernel(this->_kernel);
1166
    kernel.Transform(getTransform());
1167

1168
    MeshCore::MeshTrimming trim(kernel, &proj, polygon2d);
1169
    std::vector<FacetIndex> check;
1170
    std::vector<MeshCore::MeshGeomFacet> triangle;
1171

1172
    switch (type) {
1173
        case INNER:
1174
            trim.SetInnerOrOuter(MeshCore::MeshTrimming::INNER);
1175
            break;
1176
        case OUTER:
1177
            trim.SetInnerOrOuter(MeshCore::MeshTrimming::OUTER);
1178
            break;
1179
    }
1180

1181
    MeshCore::MeshFacetGrid meshGrid(kernel);
1182
    trim.CheckFacets(meshGrid, check);
1183
    trim.TrimFacets(check, triangle);
1184
    if (!check.empty()) {
1185
        this->deleteFacets(check);
1186
    }
1187

1188
    // Re-add some triangles
1189
    if (!triangle.empty()) {
1190
        Base::Matrix4D mat(getTransform());
1191
        mat.inverse();
1192
        for (auto& it : triangle) {
1193
            it.Transform(mat);
1194
        }
1195
        this->_kernel.AddFacets(triangle);
1196
    }
1197
}
1198

1199
void MeshObject::trimByPlane(const Base::Vector3f& base, const Base::Vector3f& normal)
1200
{
1201
    MeshCore::MeshTrimByPlane trim(this->_kernel);
1202
    std::vector<FacetIndex> trimFacets, removeFacets;
1203
    std::vector<MeshCore::MeshGeomFacet> triangle;
1204

1205
    // Apply the inverted mesh placement to the plane because the trimming is done
1206
    // on the untransformed mesh data
1207
    Base::Vector3f basePlane, normalPlane;
1208
    Base::Placement meshPlacement = getPlacement();
1209
    meshPlacement.invert();
1210
    meshPlacement.multVec(base, basePlane);
1211
    meshPlacement.getRotation().multVec(normal, normalPlane);
1212

1213
    MeshCore::MeshFacetGrid meshGrid(this->_kernel);
1214
    trim.CheckFacets(meshGrid, basePlane, normalPlane, trimFacets, removeFacets);
1215
    trim.TrimFacets(trimFacets, basePlane, normalPlane, triangle);
1216
    if (!removeFacets.empty()) {
1217
        this->deleteFacets(removeFacets);
1218
    }
1219
    if (!triangle.empty()) {
1220
        this->_kernel.AddFacets(triangle);
1221
    }
1222
}
1223

1224
MeshObject* MeshObject::unite(const MeshObject& mesh) const
1225
{
1226
    MeshCore::MeshKernel result;
1227
    MeshCore::MeshKernel kernel1(this->_kernel);
1228
    kernel1.Transform(this->_Mtrx);
1229
    MeshCore::MeshKernel kernel2(mesh._kernel);
1230
    kernel2.Transform(mesh._Mtrx);
1231
    MeshCore::SetOperations setOp(kernel1,
1232
                                  kernel2,
1233
                                  result,
1234
                                  MeshCore::SetOperations::Union,
1235
                                  Epsilon);
1236
    setOp.Do();
1237
    return new MeshObject(result);
1238
}
1239

1240
MeshObject* MeshObject::intersect(const MeshObject& mesh) const
1241
{
1242
    MeshCore::MeshKernel result;
1243
    MeshCore::MeshKernel kernel1(this->_kernel);
1244
    kernel1.Transform(this->_Mtrx);
1245
    MeshCore::MeshKernel kernel2(mesh._kernel);
1246
    kernel2.Transform(mesh._Mtrx);
1247
    MeshCore::SetOperations setOp(kernel1,
1248
                                  kernel2,
1249
                                  result,
1250
                                  MeshCore::SetOperations::Intersect,
1251
                                  Epsilon);
1252
    setOp.Do();
1253
    return new MeshObject(result);
1254
}
1255

1256
MeshObject* MeshObject::subtract(const MeshObject& mesh) const
1257
{
1258
    MeshCore::MeshKernel result;
1259
    MeshCore::MeshKernel kernel1(this->_kernel);
1260
    kernel1.Transform(this->_Mtrx);
1261
    MeshCore::MeshKernel kernel2(mesh._kernel);
1262
    kernel2.Transform(mesh._Mtrx);
1263
    MeshCore::SetOperations setOp(kernel1,
1264
                                  kernel2,
1265
                                  result,
1266
                                  MeshCore::SetOperations::Difference,
1267
                                  Epsilon);
1268
    setOp.Do();
1269
    return new MeshObject(result);
1270
}
1271

1272
MeshObject* MeshObject::inner(const MeshObject& mesh) const
1273
{
1274
    MeshCore::MeshKernel result;
1275
    MeshCore::MeshKernel kernel1(this->_kernel);
1276
    kernel1.Transform(this->_Mtrx);
1277
    MeshCore::MeshKernel kernel2(mesh._kernel);
1278
    kernel2.Transform(mesh._Mtrx);
1279
    MeshCore::SetOperations setOp(kernel1,
1280
                                  kernel2,
1281
                                  result,
1282
                                  MeshCore::SetOperations::Inner,
1283
                                  Epsilon);
1284
    setOp.Do();
1285
    return new MeshObject(result);
1286
}
1287

1288
MeshObject* MeshObject::outer(const MeshObject& mesh) const
1289
{
1290
    MeshCore::MeshKernel result;
1291
    MeshCore::MeshKernel kernel1(this->_kernel);
1292
    kernel1.Transform(this->_Mtrx);
1293
    MeshCore::MeshKernel kernel2(mesh._kernel);
1294
    kernel2.Transform(mesh._Mtrx);
1295
    MeshCore::SetOperations setOp(kernel1,
1296
                                  kernel2,
1297
                                  result,
1298
                                  MeshCore::SetOperations::Outer,
1299
                                  Epsilon);
1300
    setOp.Do();
1301
    return new MeshObject(result);
1302
}
1303

1304
std::vector<std::vector<Base::Vector3f>>
1305
MeshObject::section(const MeshObject& mesh, bool connectLines, float fMinDist) const
1306
{
1307
    MeshCore::MeshKernel kernel1(this->_kernel);
1308
    kernel1.Transform(this->_Mtrx);
1309
    MeshCore::MeshKernel kernel2(mesh._kernel);
1310
    kernel2.Transform(mesh._Mtrx);
1311
    std::vector<std::vector<Base::Vector3f>> lines;
1312

1313
    MeshCore::MeshIntersection sec(kernel1, kernel2, fMinDist);
1314
    std::list<MeshCore::MeshIntersection::Tuple> tuple;
1315
    sec.getIntersection(tuple);
1316

1317
    if (!connectLines) {
1318
        for (const auto& it : tuple) {
1319
            std::vector<Base::Vector3f> curve;
1320
            curve.push_back(it.p1);
1321
            curve.push_back(it.p2);
1322
            lines.push_back(curve);
1323
        }
1324
    }
1325
    else {
1326
        std::list<std::list<MeshCore::MeshIntersection::Triple>> triple;
1327
        sec.connectLines(false, tuple, triple);
1328

1329
        for (const auto& it : triple) {
1330
            std::vector<Base::Vector3f> curve;
1331
            curve.reserve(it.size());
1332

1333
            for (const auto& jt : it) {
1334
                curve.push_back(jt.p);
1335
            }
1336
            lines.push_back(curve);
1337
        }
1338
    }
1339

1340
    return lines;
1341
}
1342

1343
void MeshObject::refine()
1344
{
1345
    unsigned long cnt = _kernel.CountFacets();
1346
    MeshCore::MeshFacetIterator cF(_kernel);
1347
    MeshCore::MeshTopoAlgorithm topalg(_kernel);
1348

1349
    // x < 30 deg => cos(x) > sqrt(3)/2 or x > 120 deg => cos(x) < -0.5
1350
    for (unsigned long i = 0; i < cnt; i++) {
1351
        cF.Set(i);
1352
        if (!cF->IsDeformed(0.86f, -0.5f)) {
1353
            topalg.InsertVertexAndSwapEdge(i, cF->GetGravityPoint(), 0.1f);
1354
        }
1355
    }
1356

1357
    // clear the segments because we don't know how the new
1358
    // topology looks like
1359
    this->_segments.clear();
1360
}
1361

1362
void MeshObject::removeNeedles(float length)
1363
{
1364
    unsigned long count = _kernel.CountFacets();
1365
    MeshCore::MeshRemoveNeedles eval(_kernel, length);
1366
    eval.Fixup();
1367
    if (_kernel.CountFacets() < count) {
1368
        this->_segments.clear();
1369
    }
1370
}
1371

1372
void MeshObject::validateCaps(float fMaxAngle, float fSplitFactor)
1373
{
1374
    MeshCore::MeshFixCaps eval(_kernel, fMaxAngle, fSplitFactor);
1375
    eval.Fixup();
1376
}
1377

1378
void MeshObject::optimizeTopology(float fMaxAngle)
1379
{
1380
    MeshCore::MeshTopoAlgorithm topalg(_kernel);
1381
    if (fMaxAngle > 0.0f) {
1382
        topalg.OptimizeTopology(fMaxAngle);
1383
    }
1384
    else {
1385
        topalg.OptimizeTopology();
1386
    }
1387

1388
    // clear the segments because we don't know how the new
1389
    // topology looks like
1390
    this->_segments.clear();
1391
}
1392

1393
void MeshObject::optimizeEdges()
1394
{
1395
    MeshCore::MeshTopoAlgorithm topalg(_kernel);
1396
    topalg.AdjustEdgesToCurvatureDirection();
1397
}
1398

1399
void MeshObject::splitEdges()
1400
{
1401
    std::vector<std::pair<FacetIndex, FacetIndex>> adjacentFacet;
1402
    MeshCore::MeshAlgorithm alg(_kernel);
1403
    alg.ResetFacetFlag(MeshCore::MeshFacet::VISIT);
1404
    const MeshCore::MeshFacetArray& rFacets = _kernel.GetFacets();
1405
    for (MeshCore::MeshFacetArray::_TConstIterator pF = rFacets.begin(); pF != rFacets.end();
1406
         ++pF) {
1407
        int id = 2;
1408
        if (pF->_aulNeighbours[id] != MeshCore::FACET_INDEX_MAX) {
1409
            const MeshCore::MeshFacet& rFace = rFacets[pF->_aulNeighbours[id]];
1410
            if (!pF->IsFlag(MeshCore::MeshFacet::VISIT)
1411
                && !rFace.IsFlag(MeshCore::MeshFacet::VISIT)) {
1412
                pF->SetFlag(MeshCore::MeshFacet::VISIT);
1413
                rFace.SetFlag(MeshCore::MeshFacet::VISIT);
1414
                adjacentFacet.emplace_back(pF - rFacets.begin(), pF->_aulNeighbours[id]);
1415
            }
1416
        }
1417
    }
1418

1419
    MeshCore::MeshFacetIterator cIter(_kernel);
1420
    MeshCore::MeshTopoAlgorithm topalg(_kernel);
1421
    for (const auto& it : adjacentFacet) {
1422
        cIter.Set(it.first);
1423
        Base::Vector3f mid = 0.5f * (cIter->_aclPoints[0] + cIter->_aclPoints[2]);
1424
        topalg.SplitEdge(it.first, it.second, mid);
1425
    }
1426

1427
    // clear the segments because we don't know how the new
1428
    // topology looks like
1429
    this->_segments.clear();
1430
}
1431

1432
void MeshObject::splitEdge(FacetIndex facet, FacetIndex neighbour, const Base::Vector3f& v)
1433
{
1434
    MeshCore::MeshTopoAlgorithm topalg(_kernel);
1435
    topalg.SplitEdge(facet, neighbour, v);
1436
}
1437

1438
void MeshObject::splitFacet(FacetIndex facet, const Base::Vector3f& v1, const Base::Vector3f& v2)
1439
{
1440
    MeshCore::MeshTopoAlgorithm topalg(_kernel);
1441
    topalg.SplitFacet(facet, v1, v2);
1442
}
1443

1444
void MeshObject::swapEdge(FacetIndex facet, FacetIndex neighbour)
1445
{
1446
    MeshCore::MeshTopoAlgorithm topalg(_kernel);
1447
    topalg.SwapEdge(facet, neighbour);
1448
}
1449

1450
void MeshObject::collapseEdge(FacetIndex facet, FacetIndex neighbour)
1451
{
1452
    MeshCore::MeshTopoAlgorithm topalg(_kernel);
1453
    topalg.CollapseEdge(facet, neighbour);
1454

1455
    std::vector<FacetIndex> remFacets;
1456
    remFacets.push_back(facet);
1457
    remFacets.push_back(neighbour);
1458
    deletedFacets(remFacets);
1459
}
1460

1461
void MeshObject::collapseFacet(FacetIndex facet)
1462
{
1463
    MeshCore::MeshTopoAlgorithm topalg(_kernel);
1464
    topalg.CollapseFacet(facet);
1465

1466
    std::vector<FacetIndex> remFacets;
1467
    remFacets.push_back(facet);
1468
    deletedFacets(remFacets);
1469
}
1470

1471
void MeshObject::collapseFacets(const std::vector<FacetIndex>& facets)
1472
{
1473
    MeshCore::MeshTopoAlgorithm alg(_kernel);
1474
    for (FacetIndex it : facets) {
1475
        alg.CollapseFacet(it);
1476
    }
1477

1478
    deletedFacets(facets);
1479
}
1480

1481
void MeshObject::insertVertex(FacetIndex facet, const Base::Vector3f& v)
1482
{
1483
    MeshCore::MeshTopoAlgorithm topalg(_kernel);
1484
    topalg.InsertVertex(facet, v);
1485
}
1486

1487
void MeshObject::snapVertex(FacetIndex facet, const Base::Vector3f& v)
1488
{
1489
    MeshCore::MeshTopoAlgorithm topalg(_kernel);
1490
    topalg.SnapVertex(facet, v);
1491
}
1492

1493
unsigned long MeshObject::countNonUniformOrientedFacets() const
1494
{
1495
    MeshCore::MeshEvalOrientation cMeshEval(_kernel);
1496
    std::vector<FacetIndex> inds = cMeshEval.GetIndices();
1497
    return inds.size();
1498
}
1499

1500
void MeshObject::flipNormals()
1501
{
1502
    MeshCore::MeshTopoAlgorithm alg(_kernel);
1503
    alg.FlipNormals();
1504
}
1505

1506
void MeshObject::harmonizeNormals()
1507
{
1508
    MeshCore::MeshTopoAlgorithm alg(_kernel);
1509
    alg.HarmonizeNormals();
1510
}
1511

1512
bool MeshObject::hasNonManifolds() const
1513
{
1514
    MeshCore::MeshEvalTopology cMeshEval(_kernel);
1515
    return !cMeshEval.Evaluate();
1516
}
1517

1518
void MeshObject::removeNonManifolds()
1519
{
1520
    MeshCore::MeshEvalTopology f_eval(_kernel);
1521
    if (!f_eval.Evaluate()) {
1522
        MeshCore::MeshFixTopology f_fix(_kernel, f_eval.GetFacets());
1523
        f_fix.Fixup();
1524
        deletedFacets(f_fix.GetDeletedFaces());
1525
    }
1526
}
1527

1528
void MeshObject::removeNonManifoldPoints()
1529
{
1530
    MeshCore::MeshEvalPointManifolds p_eval(_kernel);
1531
    if (!p_eval.Evaluate()) {
1532
        std::vector<FacetIndex> faces;
1533
        p_eval.GetFacetIndices(faces);
1534
        deleteFacets(faces);
1535
    }
1536
}
1537

1538
bool MeshObject::hasSelfIntersections() const
1539
{
1540
    MeshCore::MeshEvalSelfIntersection cMeshEval(_kernel);
1541
    return !cMeshEval.Evaluate();
1542
}
1543

1544
MeshObject::TFacePairs MeshObject::getSelfIntersections() const
1545
{
1546
    MeshCore::MeshEvalSelfIntersection eval(getKernel());
1547
    MeshObject::TFacePairs pairs;
1548
    eval.GetIntersections(pairs);
1549
    return pairs;
1550
}
1551

1552
std::vector<Base::Line3d>
1553
MeshObject::getSelfIntersections(const MeshObject::TFacePairs& facets) const
1554
{
1555
    MeshCore::MeshEvalSelfIntersection eval(getKernel());
1556
    using Section = std::pair<Base::Vector3f, Base::Vector3f>;
1557
    std::vector<Section> selfPoints;
1558
    eval.GetIntersections(facets, selfPoints);
1559

1560
    std::vector<Base::Line3d> lines;
1561
    lines.reserve(selfPoints.size());
1562

1563
    Base::Matrix4D mat(getTransform());
1564
    std::transform(selfPoints.begin(),
1565
                   selfPoints.end(),
1566
                   std::back_inserter(lines),
1567
                   [&mat](const Section& l) {
1568
                       return Base::Line3d(mat * Base::convertTo<Base::Vector3d>(l.first),
1569
                                           mat * Base::convertTo<Base::Vector3d>(l.second));
1570
                   });
1571
    return lines;
1572
}
1573

1574
void MeshObject::removeSelfIntersections()
1575
{
1576
    std::vector<std::pair<FacetIndex, FacetIndex>> selfIntersections;
1577
    MeshCore::MeshEvalSelfIntersection cMeshEval(_kernel);
1578
    cMeshEval.GetIntersections(selfIntersections);
1579

1580
    if (!selfIntersections.empty()) {
1581
        MeshCore::MeshFixSelfIntersection cMeshFix(_kernel, selfIntersections);
1582
        deleteFacets(cMeshFix.GetFacets());
1583
    }
1584
}
1585

1586
void MeshObject::removeSelfIntersections(const std::vector<FacetIndex>& indices)
1587
{
1588
    // make sure that the number of indices is even and are in range
1589
    if (indices.size() % 2 != 0) {
1590
        return;
1591
    }
1592
    unsigned long cntfacets = _kernel.CountFacets();
1593
    if (std::find_if(indices.begin(),
1594
                     indices.end(),
1595
                     [cntfacets](FacetIndex v) {
1596
                         return v >= cntfacets;
1597
                     })
1598
        < indices.end()) {
1599
        return;
1600
    }
1601
    std::vector<std::pair<FacetIndex, FacetIndex>> selfIntersections;
1602
    std::vector<FacetIndex>::const_iterator it;
1603
    for (it = indices.begin(); it != indices.end();) {
1604
        FacetIndex id1 = *it;
1605
        ++it;
1606
        FacetIndex id2 = *it;
1607
        ++it;
1608
        selfIntersections.emplace_back(id1, id2);
1609
    }
1610

1611
    if (!selfIntersections.empty()) {
1612
        MeshCore::MeshFixSelfIntersection cMeshFix(_kernel, selfIntersections);
1613
        cMeshFix.Fixup();
1614
        this->_segments.clear();
1615
    }
1616
}
1617

1618
void MeshObject::removeFoldsOnSurface()
1619
{
1620
    std::vector<FacetIndex> indices;
1621
    MeshCore::MeshEvalFoldsOnSurface s_eval(_kernel);
1622
    MeshCore::MeshEvalFoldOversOnSurface f_eval(_kernel);
1623

1624
    f_eval.Evaluate();
1625
    std::vector<FacetIndex> inds = f_eval.GetIndices();
1626

1627
    s_eval.Evaluate();
1628
    std::vector<FacetIndex> inds1 = s_eval.GetIndices();
1629

1630
    // remove duplicates
1631
    inds.insert(inds.end(), inds1.begin(), inds1.end());
1632
    std::sort(inds.begin(), inds.end());
1633
    inds.erase(std::unique(inds.begin(), inds.end()), inds.end());
1634

1635
    if (!inds.empty()) {
1636
        deleteFacets(inds);
1637
    }
1638

1639
    // do this as additional check after removing folds on closed area
1640
    for (int i = 0; i < 5; i++) {
1641
        MeshCore::MeshEvalFoldsOnBoundary b_eval(_kernel);
1642
        if (b_eval.Evaluate()) {
1643
            break;
1644
        }
1645
        inds = b_eval.GetIndices();
1646
        if (!inds.empty()) {
1647
            deleteFacets(inds);
1648
        }
1649
    }
1650
}
1651

1652
void MeshObject::removeFullBoundaryFacets()
1653
{
1654
    std::vector<FacetIndex> facets;
1655
    if (!MeshCore::MeshEvalBorderFacet(_kernel, facets).Evaluate()) {
1656
        deleteFacets(facets);
1657
    }
1658
}
1659

1660
bool MeshObject::hasInvalidPoints() const
1661
{
1662
    MeshCore::MeshEvalNaNPoints nan(_kernel);
1663
    return !nan.GetIndices().empty();
1664
}
1665

1666
void MeshObject::removeInvalidPoints()
1667
{
1668
    MeshCore::MeshEvalNaNPoints nan(_kernel);
1669
    deletePoints(nan.GetIndices());
1670
}
1671

1672
bool MeshObject::hasPointsOnEdge() const
1673
{
1674
    MeshCore::MeshEvalPointOnEdge nan(_kernel);
1675
    return !nan.Evaluate();
1676
}
1677

1678
void MeshObject::removePointsOnEdge(bool fillBoundary)
1679
{
1680
    MeshCore::MeshFixPointOnEdge nan(_kernel, fillBoundary);
1681
    nan.Fixup();
1682
}
1683

1684
void MeshObject::mergeFacets()
1685
{
1686
    unsigned long count = _kernel.CountFacets();
1687
    MeshCore::MeshFixMergeFacets merge(_kernel);
1688
    merge.Fixup();
1689
    if (_kernel.CountFacets() < count) {
1690
        this->_segments.clear();
1691
    }
1692
}
1693

1694
void MeshObject::validateIndices()
1695
{
1696
    unsigned long count = _kernel.CountFacets();
1697

1698
    // for invalid neighbour indices we don't need to check first
1699
    // but start directly with the validation
1700
    MeshCore::MeshFixNeighbourhood fix(_kernel);
1701
    fix.Fixup();
1702

1703
    MeshCore::MeshEvalRangeFacet rf(_kernel);
1704
    if (!rf.Evaluate()) {
1705
        MeshCore::MeshFixRangeFacet fix(_kernel);
1706
        fix.Fixup();
1707
    }
1708

1709
    MeshCore::MeshEvalRangePoint rp(_kernel);
1710
    if (!rp.Evaluate()) {
1711
        MeshCore::MeshFixRangePoint fix(_kernel);
1712
        fix.Fixup();
1713
    }
1714

1715
    MeshCore::MeshEvalCorruptedFacets cf(_kernel);
1716
    if (!cf.Evaluate()) {
1717
        MeshCore::MeshFixCorruptedFacets fix(_kernel);
1718
        fix.Fixup();
1719
    }
1720

1721
    if (_kernel.CountFacets() < count) {
1722
        this->_segments.clear();
1723
    }
1724
}
1725

1726
bool MeshObject::hasInvalidNeighbourhood() const
1727
{
1728
    MeshCore::MeshEvalNeighbourhood eval(_kernel);
1729
    return !eval.Evaluate();
1730
}
1731

1732
bool MeshObject::hasPointsOutOfRange() const
1733
{
1734
    MeshCore::MeshEvalRangePoint eval(_kernel);
1735
    return !eval.Evaluate();
1736
}
1737

1738
bool MeshObject::hasFacetsOutOfRange() const
1739
{
1740
    MeshCore::MeshEvalRangeFacet eval(_kernel);
1741
    return !eval.Evaluate();
1742
}
1743

1744
bool MeshObject::hasCorruptedFacets() const
1745
{
1746
    MeshCore::MeshEvalCorruptedFacets eval(_kernel);
1747
    return !eval.Evaluate();
1748
}
1749

1750
void MeshObject::validateDeformations(float fMaxAngle, float fEps)
1751
{
1752
    unsigned long count = _kernel.CountFacets();
1753
    MeshCore::MeshFixDeformedFacets eval(_kernel,
1754
                                         Base::toRadians(15.0f),
1755
                                         Base::toRadians(150.0f),
1756
                                         fMaxAngle,
1757
                                         fEps);
1758
    eval.Fixup();
1759
    if (_kernel.CountFacets() < count) {
1760
        this->_segments.clear();
1761
    }
1762
}
1763

1764
void MeshObject::validateDegenerations(float fEps)
1765
{
1766
    unsigned long count = _kernel.CountFacets();
1767
    MeshCore::MeshFixDegeneratedFacets eval(_kernel, fEps);
1768
    eval.Fixup();
1769
    if (_kernel.CountFacets() < count) {
1770
        this->_segments.clear();
1771
    }
1772
}
1773

1774
void MeshObject::removeDuplicatedPoints()
1775
{
1776
    unsigned long count = _kernel.CountFacets();
1777
    MeshCore::MeshFixDuplicatePoints eval(_kernel);
1778
    eval.Fixup();
1779
    if (_kernel.CountFacets() < count) {
1780
        this->_segments.clear();
1781
    }
1782
}
1783

1784
void MeshObject::removeDuplicatedFacets()
1785
{
1786
    unsigned long count = _kernel.CountFacets();
1787
    MeshCore::MeshFixDuplicateFacets eval(_kernel);
1788
    eval.Fixup();
1789
    if (_kernel.CountFacets() < count) {
1790
        this->_segments.clear();
1791
    }
1792
}
1793

1794
MeshObject* MeshObject::createMeshFromList(Py::List& list)
1795
{
1796
    std::vector<MeshCore::MeshGeomFacet> facets;
1797
    MeshCore::MeshGeomFacet facet;
1798
    int i = 0;
1799
    for (Py::List::iterator it = list.begin(); it != list.end(); ++it) {
1800
        Py::List item(*it);
1801
        for (int j = 0; j < 3; j++) {
1802
            Py::Float value(item[j]);
1803
            facet._aclPoints[i][j] = (float)value;
1804
        }
1805
        if (++i == 3) {
1806
            i = 0;
1807
            facet.CalcNormal();
1808
            facets.push_back(facet);
1809
        }
1810
    }
1811

1812
    Base::EmptySequencer seq;
1813
    std::unique_ptr<MeshObject> mesh(new MeshObject);
1814
    // mesh->addFacets(facets);
1815
    mesh->getKernel() = facets;
1816
    return mesh.release();
1817
}
1818

1819
MeshObject* MeshObject::createSphere(float radius, int sampling)
1820
{
1821
    // load the 'BuildRegularGeoms' module
1822
    Base::PyGILStateLocker lock;
1823
    try {
1824
        Py::Module module(PyImport_ImportModule("BuildRegularGeoms"), true);
1825
        if (module.isNull()) {
1826
            return nullptr;
1827
        }
1828
        Py::Dict dict = module.getDict();
1829
        Py::Callable call(dict.getItem("Sphere"));
1830
        Py::Tuple args(2);
1831
        args.setItem(0, Py::Float(radius));
1832
        args.setItem(1, Py::Long(sampling));
1833
        Py::List list(call.apply(args));
1834
        return createMeshFromList(list);
1835
    }
1836
    catch (Py::Exception& e) {
1837
        e.clear();
1838
    }
1839

1840
    return nullptr;
1841
}
1842

1843
MeshObject* MeshObject::createEllipsoid(float radius1, float radius2, int sampling)
1844
{
1845
    // load the 'BuildRegularGeoms' module
1846
    Base::PyGILStateLocker lock;
1847
    try {
1848
        Py::Module module(PyImport_ImportModule("BuildRegularGeoms"), true);
1849
        if (module.isNull()) {
1850
            return nullptr;
1851
        }
1852
        Py::Dict dict = module.getDict();
1853
        Py::Callable call(dict.getItem("Ellipsoid"));
1854
        Py::Tuple args(3);
1855
        args.setItem(0, Py::Float(radius1));
1856
        args.setItem(1, Py::Float(radius2));
1857
        args.setItem(2, Py::Long(sampling));
1858
        Py::List list(call.apply(args));
1859
        return createMeshFromList(list);
1860
    }
1861
    catch (Py::Exception& e) {
1862
        e.clear();
1863
    }
1864

1865
    return nullptr;
1866
}
1867

1868
MeshObject*
1869
MeshObject::createCylinder(float radius, float length, int closed, float edgelen, int sampling)
1870
{
1871
    // load the 'BuildRegularGeoms' module
1872
    Base::PyGILStateLocker lock;
1873
    try {
1874
        Py::Module module(PyImport_ImportModule("BuildRegularGeoms"), true);
1875
        if (module.isNull()) {
1876
            return nullptr;
1877
        }
1878
        Py::Dict dict = module.getDict();
1879
        Py::Callable call(dict.getItem("Cylinder"));
1880
        Py::Tuple args(5);
1881
        args.setItem(0, Py::Float(radius));
1882
        args.setItem(1, Py::Float(length));
1883
        args.setItem(2, Py::Long(closed));
1884
        args.setItem(3, Py::Float(edgelen));
1885
        args.setItem(4, Py::Long(sampling));
1886
        Py::List list(call.apply(args));
1887
        return createMeshFromList(list);
1888
    }
1889
    catch (Py::Exception& e) {
1890
        e.clear();
1891
    }
1892

1893
    return nullptr;
1894
}
1895

1896
MeshObject* MeshObject::createCone(float radius1,
1897
                                   float radius2,
1898
                                   float len,
1899
                                   int closed,
1900
                                   float edgelen,
1901
                                   int sampling)
1902
{
1903
    // load the 'BuildRegularGeoms' module
1904
    Base::PyGILStateLocker lock;
1905
    try {
1906
        Py::Module module(PyImport_ImportModule("BuildRegularGeoms"), true);
1907
        if (module.isNull()) {
1908
            return nullptr;
1909
        }
1910
        Py::Dict dict = module.getDict();
1911
        Py::Callable call(dict.getItem("Cone"));
1912
        Py::Tuple args(6);
1913
        args.setItem(0, Py::Float(radius1));
1914
        args.setItem(1, Py::Float(radius2));
1915
        args.setItem(2, Py::Float(len));
1916
        args.setItem(3, Py::Long(closed));
1917
        args.setItem(4, Py::Float(edgelen));
1918
        args.setItem(5, Py::Long(sampling));
1919
        Py::List list(call.apply(args));
1920
        return createMeshFromList(list);
1921
    }
1922
    catch (Py::Exception& e) {
1923
        e.clear();
1924
    }
1925

1926
    return nullptr;
1927
}
1928

1929
MeshObject* MeshObject::createTorus(float radius1, float radius2, int sampling)
1930
{
1931
    // load the 'BuildRegularGeoms' module
1932
    Base::PyGILStateLocker lock;
1933
    try {
1934
        Py::Module module(PyImport_ImportModule("BuildRegularGeoms"), true);
1935
        if (module.isNull()) {
1936
            return nullptr;
1937
        }
1938
        Py::Dict dict = module.getDict();
1939
        Py::Callable call(dict.getItem("Toroid"));
1940
        Py::Tuple args(3);
1941
        args.setItem(0, Py::Float(radius1));
1942
        args.setItem(1, Py::Float(radius2));
1943
        args.setItem(2, Py::Long(sampling));
1944
        Py::List list(call.apply(args));
1945
        return createMeshFromList(list);
1946
    }
1947
    catch (Py::Exception& e) {
1948
        e.clear();
1949
    }
1950

1951
    return nullptr;
1952
}
1953

1954
MeshObject* MeshObject::createCube(float length, float width, float height)
1955
{
1956
    // load the 'BuildRegularGeoms' module
1957
    Base::PyGILStateLocker lock;
1958
    try {
1959
        Py::Module module(PyImport_ImportModule("BuildRegularGeoms"), true);
1960
        if (module.isNull()) {
1961
            return nullptr;
1962
        }
1963
        Py::Dict dict = module.getDict();
1964
        Py::Callable call(dict.getItem("Cube"));
1965
        Py::Tuple args(3);
1966
        args.setItem(0, Py::Float(length));
1967
        args.setItem(1, Py::Float(width));
1968
        args.setItem(2, Py::Float(height));
1969
        Py::List list(call.apply(args));
1970
        return createMeshFromList(list);
1971
    }
1972
    catch (Py::Exception& e) {
1973
        e.clear();
1974
    }
1975

1976
    return nullptr;
1977
}
1978

1979
MeshObject* MeshObject::createCube(float length, float width, float height, float edgelen)
1980
{
1981
    // load the 'BuildRegularGeoms' module
1982
    Base::PyGILStateLocker lock;
1983
    try {
1984
        Py::Module module(PyImport_ImportModule("BuildRegularGeoms"), true);
1985
        if (module.isNull()) {
1986
            return nullptr;
1987
        }
1988
        Py::Dict dict = module.getDict();
1989
        Py::Callable call(dict.getItem("FineCube"));
1990
        Py::Tuple args(4);
1991
        args.setItem(0, Py::Float(length));
1992
        args.setItem(1, Py::Float(width));
1993
        args.setItem(2, Py::Float(height));
1994
        args.setItem(3, Py::Float(edgelen));
1995
        Py::List list(call.apply(args));
1996
        return createMeshFromList(list);
1997
    }
1998
    catch (Py::Exception& e) {
1999
        e.clear();
2000
    }
2001

2002
    return nullptr;
2003
}
2004

2005
MeshObject* MeshObject::createCube(const Base::BoundBox3d& bbox)
2006
{
2007
    using Corner = Base::BoundBox3d::CORNER;
2008
    std::vector<MeshCore::MeshGeomFacet> facets;
2009
    auto createFacet = [&bbox](Corner p1, Corner p2, Corner p3) {
2010
        MeshCore::MeshGeomFacet facet;
2011
        facet._aclPoints[0] = Base::convertTo<Base::Vector3f>(bbox.CalcPoint(p1));
2012
        facet._aclPoints[1] = Base::convertTo<Base::Vector3f>(bbox.CalcPoint(p2));
2013
        facet._aclPoints[2] = Base::convertTo<Base::Vector3f>(bbox.CalcPoint(p3));
2014
        facet.CalcNormal();
2015
        return facet;
2016
    };
2017

2018
    facets.push_back(createFacet(Corner::TLB, Corner::TLF, Corner::TRF));
2019
    facets.push_back(createFacet(Corner::TLB, Corner::TRF, Corner::TRB));
2020
    facets.push_back(createFacet(Corner::TLB, Corner::BLF, Corner::TLF));
2021
    facets.push_back(createFacet(Corner::TLB, Corner::BLB, Corner::BLF));
2022
    facets.push_back(createFacet(Corner::TLB, Corner::TRB, Corner::BRB));
2023
    facets.push_back(createFacet(Corner::TLB, Corner::BRB, Corner::BLB));
2024
    facets.push_back(createFacet(Corner::BLB, Corner::BRF, Corner::BLF));
2025
    facets.push_back(createFacet(Corner::BLB, Corner::BRB, Corner::BRF));
2026
    facets.push_back(createFacet(Corner::TLF, Corner::BRF, Corner::TRF));
2027
    facets.push_back(createFacet(Corner::TLF, Corner::BLF, Corner::BRF));
2028
    facets.push_back(createFacet(Corner::TRF, Corner::BRB, Corner::TRB));
2029
    facets.push_back(createFacet(Corner::TRF, Corner::BRF, Corner::BRB));
2030

2031
    Base::EmptySequencer seq;
2032
    std::unique_ptr<MeshObject> mesh(new MeshObject);
2033
    mesh->getKernel() = facets;
2034
    return mesh.release();
2035
}
2036

2037
void MeshObject::addSegment(const Segment& s)
2038
{
2039
    addSegment(s.getIndices());
2040
    this->_segments.back().setName(s.getName());
2041
    this->_segments.back().setColor(s.getColor());
2042
    this->_segments.back().save(s.isSaved());
2043
    this->_segments.back()._modifykernel = s._modifykernel;
2044
}
2045

2046
void MeshObject::addSegment(const std::vector<FacetIndex>& inds)
2047
{
2048
    unsigned long maxIndex = _kernel.CountFacets();
2049
    for (FacetIndex it : inds) {
2050
        if (it >= maxIndex) {
2051
            throw Base::IndexError("Index out of range");
2052
        }
2053
    }
2054

2055
    this->_segments.emplace_back(this, inds, true);
2056
}
2057

2058
const Segment& MeshObject::getSegment(unsigned long index) const
2059
{
2060
    return this->_segments[index];
2061
}
2062

2063
Segment& MeshObject::getSegment(unsigned long index)
2064
{
2065
    return this->_segments[index];
2066
}
2067

2068
MeshObject* MeshObject::meshFromSegment(const std::vector<FacetIndex>& indices) const
2069
{
2070
    MeshCore::MeshFacetArray facets;
2071
    facets.reserve(indices.size());
2072
    const MeshCore::MeshPointArray& kernel_p = _kernel.GetPoints();
2073
    const MeshCore::MeshFacetArray& kernel_f = _kernel.GetFacets();
2074
    for (FacetIndex it : indices) {
2075
        facets.push_back(kernel_f[it]);
2076
    }
2077

2078
    MeshCore::MeshKernel kernel;
2079
    kernel.Merge(kernel_p, facets);
2080

2081
    return new MeshObject(kernel, _Mtrx);
2082
}
2083

2084
std::vector<Segment> MeshObject::getSegmentsOfType(MeshObject::GeometryType type,
2085
                                                   float dev,
2086
                                                   unsigned long minFacets) const
2087
{
2088
    std::vector<Segment> segm;
2089
    if (this->_kernel.CountFacets() == 0) {
2090
        return segm;
2091
    }
2092

2093
    MeshCore::MeshSegmentAlgorithm finder(this->_kernel);
2094
    std::shared_ptr<MeshCore::MeshDistanceSurfaceSegment> surf;
2095
    switch (type) {
2096
        case PLANE:
2097
            surf.reset(
2098
                new MeshCore::MeshDistanceGenericSurfaceFitSegment(new MeshCore::PlaneSurfaceFit,
2099
                                                                   this->_kernel,
2100
                                                                   minFacets,
2101
                                                                   dev));
2102
            break;
2103
        case CYLINDER:
2104
            surf.reset(
2105
                new MeshCore::MeshDistanceGenericSurfaceFitSegment(new MeshCore::CylinderSurfaceFit,
2106
                                                                   this->_kernel,
2107
                                                                   minFacets,
2108
                                                                   dev));
2109
            break;
2110
        case SPHERE:
2111
            surf.reset(
2112
                new MeshCore::MeshDistanceGenericSurfaceFitSegment(new MeshCore::SphereSurfaceFit,
2113
                                                                   this->_kernel,
2114
                                                                   minFacets,
2115
                                                                   dev));
2116
            break;
2117
        default:
2118
            break;
2119
    }
2120

2121
    if (surf.get()) {
2122
        std::vector<MeshCore::MeshSurfaceSegmentPtr> surfaces;
2123
        surfaces.push_back(surf);
2124
        finder.FindSegments(surfaces);
2125

2126
        const std::vector<MeshCore::MeshSegment>& data = surf->GetSegments();
2127
        for (const auto& it : data) {
2128
            segm.emplace_back(this, it, false);
2129
        }
2130
    }
2131

2132
    return segm;
2133
}
2134

2135
// ----------------------------------------------------------------------------
2136

2137
MeshObject::const_point_iterator::const_point_iterator(const MeshObject* mesh, PointIndex index)
2138
    : _mesh(mesh)
2139
    , _p_it(mesh->getKernel())
2140
{
2141
    this->_p_it.Set(index);
2142
    this->_p_it.Transform(_mesh->_Mtrx);
2143
    this->_point.Mesh = _mesh;
2144
}
2145

2146
MeshObject::const_point_iterator::const_point_iterator(const MeshObject::const_point_iterator& fi) =
2147
    default;
2148

2149
MeshObject::const_point_iterator::const_point_iterator(MeshObject::const_point_iterator&& fi) =
2150
    default;
2151

2152
MeshObject::const_point_iterator::~const_point_iterator() = default;
2153

2154
MeshObject::const_point_iterator&
2155
MeshObject::const_point_iterator::operator=(const MeshObject::const_point_iterator& pi) = default;
2156

2157
MeshObject::const_point_iterator&
2158
MeshObject::const_point_iterator::operator=(MeshObject::const_point_iterator&& pi) = default;
2159

2160
void MeshObject::const_point_iterator::dereference()
2161
{
2162
    this->_point.x = _p_it->x;
2163
    this->_point.y = _p_it->y;
2164
    this->_point.z = _p_it->z;
2165
    this->_point.Index = _p_it.Position();
2166
}
2167

2168
const MeshPoint& MeshObject::const_point_iterator::operator*()
2169
{
2170
    dereference();
2171
    return this->_point;
2172
}
2173

2174
const MeshPoint* MeshObject::const_point_iterator::operator->()
2175
{
2176
    dereference();
2177
    return &(this->_point);
2178
}
2179

2180
bool MeshObject::const_point_iterator::operator==(const MeshObject::const_point_iterator& pi) const
2181
{
2182
    return (this->_mesh == pi._mesh) && (this->_p_it == pi._p_it);
2183
}
2184

2185
bool MeshObject::const_point_iterator::operator!=(const MeshObject::const_point_iterator& pi) const
2186
{
2187
    return !operator==(pi);
2188
}
2189

2190
MeshObject::const_point_iterator& MeshObject::const_point_iterator::operator++()
2191
{
2192
    ++(this->_p_it);
2193
    return *this;
2194
}
2195

2196
MeshObject::const_point_iterator& MeshObject::const_point_iterator::operator--()
2197
{
2198
    --(this->_p_it);
2199
    return *this;
2200
}
2201

2202
// ----------------------------------------------------------------------------
2203

2204
MeshObject::const_facet_iterator::const_facet_iterator(const MeshObject* mesh, FacetIndex index)
2205
    : _mesh(mesh)
2206
    , _f_it(mesh->getKernel())
2207
{
2208
    this->_f_it.Set(index);
2209
    this->_f_it.Transform(_mesh->_Mtrx);
2210
    this->_facet.Mesh = _mesh;
2211
}
2212

2213
MeshObject::const_facet_iterator::const_facet_iterator(const MeshObject::const_facet_iterator& fi) =
2214
    default;
2215

2216
MeshObject::const_facet_iterator::const_facet_iterator(MeshObject::const_facet_iterator&& fi) =
2217
    default;
2218

2219
MeshObject::const_facet_iterator::~const_facet_iterator() = default;
2220

2221
MeshObject::const_facet_iterator&
2222
MeshObject::const_facet_iterator::operator=(const MeshObject::const_facet_iterator& fi) = default;
2223

2224
MeshObject::const_facet_iterator&
2225
MeshObject::const_facet_iterator::operator=(MeshObject::const_facet_iterator&& fi) = default;
2226

2227
void MeshObject::const_facet_iterator::dereference()
2228
{
2229
    this->_facet.MeshCore::MeshGeomFacet::operator=(*_f_it);
2230
    this->_facet.Index = _f_it.Position();
2231
    const MeshCore::MeshFacet& face = _f_it.GetReference();
2232
    for (int i = 0; i < 3; i++) {
2233
        this->_facet.PIndex[i] = face._aulPoints[i];
2234
        this->_facet.NIndex[i] = face._aulNeighbours[i];
2235
    }
2236
}
2237

2238
Facet& MeshObject::const_facet_iterator::operator*()
2239
{
2240
    dereference();
2241
    return this->_facet;
2242
}
2243

2244
Facet* MeshObject::const_facet_iterator::operator->()
2245
{
2246
    dereference();
2247
    return &(this->_facet);
2248
}
2249

2250
bool MeshObject::const_facet_iterator::operator==(const MeshObject::const_facet_iterator& fi) const
2251
{
2252
    return (this->_mesh == fi._mesh) && (this->_f_it == fi._f_it);
2253
}
2254

2255
bool MeshObject::const_facet_iterator::operator!=(const MeshObject::const_facet_iterator& fi) const
2256
{
2257
    return !operator==(fi);
2258
}
2259

2260
MeshObject::const_facet_iterator& MeshObject::const_facet_iterator::operator++()
2261
{
2262
    ++(this->_f_it);
2263
    return *this;
2264
}
2265

2266
MeshObject::const_facet_iterator& MeshObject::const_facet_iterator::operator--()
2267
{
2268
    --(this->_f_it);
2269
    return *this;
2270
}
2271

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

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

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

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