1
/***************************************************************************
2
* Copyright (c) Jürgen Riegel <juergen.riegel@web.de> *
4
* This file is part of the FreeCAD CAx development system. *
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. *
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. *
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 *
21
***************************************************************************/
23
#include "PreCompiled.h"
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>
41
#include "Core/Builder.h"
42
#include "Core/Decimation.h"
43
#include "Core/Degeneration.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"
52
#include "Core/TrimByPlane.h"
59
const float MeshObject::Epsilon = 1.0e-5F;
61
TYPESYSTEM_SOURCE(Mesh::MeshObject, Data::ComplexGeoData)
62
TYPESYSTEM_SOURCE(Mesh::MeshSegment, Data::Segment)
64
MeshObject::MeshObject() = default;
66
MeshObject::MeshObject(const MeshCore::MeshKernel& Kernel) // NOLINT
69
// copy the mesh structure
72
MeshObject::MeshObject(const MeshCore::MeshKernel& Kernel, const Base::Matrix4D& Mtrx) // NOLINT
76
// copy the mesh structure
79
MeshObject::MeshObject(const MeshObject& mesh)
81
, _kernel(mesh._kernel)
83
// copy the mesh structure
87
MeshObject::MeshObject(MeshObject&& mesh)
89
, _kernel(mesh._kernel)
91
// copy the mesh structure
95
MeshObject::~MeshObject() = default;
97
std::vector<const char*> MeshObject::getElementTypes() const
99
std::vector<const char*> temp;
100
temp.push_back("Mesh");
101
temp.push_back("Segment");
106
unsigned long MeshObject::countSubElements(const char* Type) const
108
std::string element(Type);
109
if (element == "Mesh") {
112
else if (element == "Segment") {
113
return countSegments();
118
Data::Segment* MeshObject::getSubElement(const char* Type, unsigned long n) const
120
std::string element(Type);
121
if (element == "Mesh" && n == 0) {
122
MeshSegment* segm = new MeshSegment();
123
segm->mesh = new MeshObject(*this);
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),
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
144
if (element && element->is<MeshSegment>()) {
145
const MeshSegment* segm = static_cast<const MeshSegment*>(element);
147
Base::Reference<MeshObject> submesh(
148
segm->mesh->meshFromSegment(segm->segment->getIndices()));
149
submesh->getFaces(points, faces, 0.0);
152
segm->mesh->getFaces(points, faces, 0.0);
157
void MeshObject::transformGeometry(const Base::Matrix4D& rclMat)
159
MeshCore::MeshKernel kernel;
161
kernel.Transform(rclMat);
165
void MeshObject::setTransform(const Base::Matrix4D& rclTrf)
170
Base::Matrix4D MeshObject::getTransform() const
175
Base::BoundBox3d MeshObject::getBoundBox() const
177
_kernel.RecalcBoundBox();
178
Base::BoundBox3f Bnd = _kernel.GetBoundBox();
180
Base::BoundBox3d Bnd2;
182
for (int i = 0; i <= 7; i++) {
183
Bnd2.Add(transformPointToOutside(Bnd.CalcPoint(Base::BoundBox3f::CORNER(i))));
190
bool MeshObject::getCenterOfGravity(Base::Vector3d& center) const
192
MeshCore::MeshAlgorithm alg(_kernel);
193
Base::Vector3f pnt = alg.GetGravityPoint();
194
center = transformPointToOutside(pnt);
198
void MeshObject::copySegments(const MeshObject& mesh)
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) {
207
void MeshObject::swapSegments(MeshObject& mesh)
209
this->_segments.swap(mesh._segments);
210
std::for_each(this->_segments.begin(), this->_segments.end(), [this](Segment& s) {
213
std::for_each(mesh._segments.begin(), mesh._segments.end(), [&mesh](Segment& s) {
218
MeshObject& MeshObject::operator=(const MeshObject& mesh)
221
// copy the mesh structure
222
setTransform(mesh._Mtrx);
223
this->_kernel = mesh._kernel;
230
MeshObject& MeshObject::operator=(MeshObject&& mesh)
233
// copy the mesh structure
234
setTransform(mesh._Mtrx);
235
this->_kernel = mesh._kernel;
242
void MeshObject::setKernel(const MeshCore::MeshKernel& m)
245
this->_segments.clear();
248
void MeshObject::swap(MeshCore::MeshKernel& Kernel)
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();
256
void MeshObject::swap(MeshObject& mesh)
258
this->_kernel.Swap(mesh._kernel);
260
Base::Matrix4D tmp = this->_Mtrx;
261
this->_Mtrx = mesh._Mtrx;
265
std::string MeshObject::representation() const
267
std::stringstream str;
268
MeshCore::MeshInfo info(_kernel);
269
info.GeneralInformation(str);
273
std::string MeshObject::topologyInfo() const
275
std::stringstream str;
276
MeshCore::MeshInfo info(_kernel);
277
info.TopologyInformation(str);
281
unsigned long MeshObject::countPoints() const
283
return _kernel.CountPoints();
286
unsigned long MeshObject::countFacets() const
288
return _kernel.CountFacets();
291
unsigned long MeshObject::countEdges() const
293
return _kernel.CountEdges();
296
unsigned long MeshObject::countSegments() const
298
return this->_segments.size();
301
bool MeshObject::isSolid() const
303
MeshCore::MeshEvalSolid cMeshEval(_kernel);
304
return cMeshEval.Evaluate();
307
double MeshObject::getSurface() const
309
return _kernel.GetSurface();
312
double MeshObject::getVolume() const
314
return _kernel.GetVolume();
317
Base::Vector3d MeshObject::getPoint(PointIndex index) const
319
MeshCore::MeshPoint vertf = _kernel.GetPoint(index);
320
Base::Vector3d vertd(vertf.x, vertf.y, vertf.z);
321
vertd = _Mtrx * vertd;
325
MeshPoint MeshObject::getMeshPoint(PointIndex index) const
327
MeshPoint point(getPoint(index), this, index);
331
void MeshObject::getPoints(std::vector<Base::Vector3d>& Points,
332
std::vector<Base::Vector3d>& Normals,
334
uint16_t /*flags*/) const
336
Points = transformPointsToOutside(_kernel.GetPoints());
337
MeshCore::MeshRefNormalToPoints ptNormals(_kernel);
338
Normals = transformVectorsToOutside(ptNormals.GetValues());
341
Mesh::Facet MeshObject::getMeshFacet(FacetIndex index) const
343
Mesh::Facet face(_kernel.GetFacets()[index], this, index);
347
void MeshObject::getFaces(std::vector<Base::Vector3d>& Points,
348
std::vector<Facet>& Topo,
350
uint16_t /*flags*/) const
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));
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++) {
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);
370
unsigned int MeshObject::getMemSize() const
372
return _kernel.GetMemSize();
375
void MeshObject::Save(Base::Writer& /*writer*/) const
377
// this is handled by the property class
380
void MeshObject::SaveDocFile(Base::Writer& writer) const
382
_kernel.Write(writer.Stream());
385
void MeshObject::Restore(Base::XMLReader& /*reader*/)
387
// this is handled by the property class
390
void MeshObject::RestoreDocFile(Base::Reader& reader)
395
void MeshObject::save(const char* file,
396
MeshCore::MeshIO::Format f,
397
const MeshCore::Material* mat,
398
const char* objectname) const
400
MeshCore::MeshOutput aWriter(this->_kernel, mat);
402
aWriter.SetObjectName(objectname);
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()) {
411
g.indices = segment.getIndices();
412
g.name = segment.getName();
416
aWriter.SetGroups(groups);
417
if (mat && mat->library.empty()) {
418
Base::FileInfo fi(file);
419
mat->library = fi.fileNamePure() + ".mtl";
422
aWriter.Transform(this->_Mtrx);
423
aWriter.SaveAny(file, f);
426
void MeshObject::save(std::ostream& str,
427
MeshCore::MeshIO::Format f,
428
const MeshCore::Material* mat,
429
const char* objectname) const
431
MeshCore::MeshOutput aWriter(this->_kernel, mat);
433
aWriter.SetObjectName(objectname);
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()) {
442
g.indices = segment.getIndices();
443
g.name = segment.getName();
447
aWriter.SetGroups(groups);
449
aWriter.Transform(this->_Mtrx);
450
aWriter.SaveFormat(str, f);
453
bool MeshObject::load(const char* file, MeshCore::Material* mat)
455
MeshCore::MeshKernel kernel;
456
MeshCore::MeshInput aReader(kernel, mat);
457
if (!aReader.LoadAny(file)) {
461
swapKernel(kernel, aReader.GetGroupNames());
465
bool MeshObject::load(std::istream& str, MeshCore::MeshIO::Format f, MeshCore::Material* mat)
467
MeshCore::MeshKernel kernel;
468
MeshCore::MeshInput aReader(kernel, mat);
469
if (!aReader.LoadFormat(str, f)) {
473
swapKernel(kernel, aReader.GetGroupNames());
477
void MeshObject::swapKernel(MeshCore::MeshKernel& kernel, const std::vector<std::string>& g)
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) {
493
if (!segment.empty()) {
494
this->_segments.emplace_back(this, segment, true);
499
segment.push_back(index++);
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);
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]);
515
void MeshObject::save(std::ostream& out) const
520
void MeshObject::load(std::istream& in)
523
this->_segments.clear();
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");
534
MeshCore::MeshEvalTopology eval(_kernel);
535
if (!eval.Evaluate()) {
536
Base::Console().Warning("The mesh data structure has some defects\n");
539
catch (const Base::MemoryException&) {
540
// ignore memory exceptions and continue
541
Base::Console().Log("Check for defects in mesh data structure failed\n");
546
void MeshObject::writeInventor(std::ostream& str, float creaseangle) const
548
const MeshCore::MeshPointArray& point = getKernel().GetPoints();
549
const MeshCore::MeshFacetArray& faces = getKernel().GetFacets();
551
std::vector<Base::Vector3f> coords;
552
coords.reserve(point.size());
553
std::copy(point.begin(), point.end(), std::back_inserter(coords));
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);
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();
574
void MeshObject::addFacet(const MeshCore::MeshGeomFacet& facet)
576
_kernel.AddFacet(facet);
579
void MeshObject::addFacets(const std::vector<MeshCore::MeshGeomFacet>& facets)
581
_kernel.AddFacets(facets);
584
void MeshObject::addFacets(const std::vector<MeshCore::MeshFacet>& facets, bool checkManifolds)
586
_kernel.AddFacets(facets, checkManifolds);
589
void MeshObject::addFacets(const std::vector<MeshCore::MeshFacet>& facets,
590
const std::vector<Base::Vector3f>& points,
593
_kernel.AddFacets(facets, points, checkManifolds);
596
void MeshObject::addFacets(const std::vector<Data::ComplexGeoData::Facet>& facets,
597
const std::vector<Base::Vector3d>& points,
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);
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);
617
_kernel.AddFacets(facet_v, point_v, checkManifolds);
620
void MeshObject::setFacets(const std::vector<MeshCore::MeshGeomFacet>& facets)
625
void MeshObject::setFacets(const std::vector<Data::ComplexGeoData::Facet>& facets,
626
const std::vector<Base::Vector3d>& points)
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);
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);
645
_kernel.Adopt(point_v, facet_v, true);
648
void MeshObject::addMesh(const MeshObject& mesh)
650
_kernel.Merge(mesh._kernel);
653
void MeshObject::addMesh(const MeshCore::MeshKernel& kernel)
655
_kernel.Merge(kernel);
658
void MeshObject::deleteFacets(const std::vector<FacetIndex>& removeIndices)
660
if (removeIndices.empty()) {
663
_kernel.DeleteFacets(removeIndices);
664
deletedFacets(removeIndices);
667
void MeshObject::deletePoints(const std::vector<PointIndex>& removeIndices)
669
if (removeIndices.empty()) {
672
_kernel.DeletePoints(removeIndices);
673
this->_segments.clear();
676
void MeshObject::deletedFacets(const std::vector<FacetIndex>& remFacets)
678
if (remFacets.empty()) {
679
return; // nothing has changed
681
if (this->_segments.empty()) {
682
return; // nothing to do
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;
690
FacetIndex index = 0;
691
for (FacetIndex& it : f_indices) {
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) {
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;
710
if (ft != segm.end()) {
711
segm.erase(ft, segm.end());
713
segment._indices = segm;
717
void MeshObject::deleteSelectedFacets()
719
std::vector<FacetIndex> facets;
720
MeshCore::MeshAlgorithm(this->_kernel).GetFacetsFlag(facets, MeshCore::MeshFacet::SELECTED);
721
deleteFacets(facets);
724
void MeshObject::deleteSelectedPoints()
726
std::vector<PointIndex> points;
727
MeshCore::MeshAlgorithm(this->_kernel).GetPointsFlag(points, MeshCore::MeshPoint::SELECTED);
728
deletePoints(points);
731
void MeshObject::clearFacetSelection() const
733
MeshCore::MeshAlgorithm(this->_kernel).ResetFacetFlag(MeshCore::MeshFacet::SELECTED);
736
void MeshObject::clearPointSelection() const
738
MeshCore::MeshAlgorithm(this->_kernel).ResetPointFlag(MeshCore::MeshPoint::SELECTED);
741
void MeshObject::addFacetsToSelection(const std::vector<FacetIndex>& inds) const
743
MeshCore::MeshAlgorithm(this->_kernel).SetFacetsFlag(inds, MeshCore::MeshFacet::SELECTED);
746
void MeshObject::addPointsToSelection(const std::vector<PointIndex>& inds) const
748
MeshCore::MeshAlgorithm(this->_kernel).SetPointsFlag(inds, MeshCore::MeshPoint::SELECTED);
751
void MeshObject::removeFacetsFromSelection(const std::vector<FacetIndex>& inds) const
753
MeshCore::MeshAlgorithm(this->_kernel).ResetFacetsFlag(inds, MeshCore::MeshFacet::SELECTED);
756
void MeshObject::removePointsFromSelection(const std::vector<PointIndex>& inds) const
758
MeshCore::MeshAlgorithm(this->_kernel).ResetPointsFlag(inds, MeshCore::MeshPoint::SELECTED);
761
void MeshObject::getFacetsFromSelection(std::vector<FacetIndex>& inds) const
763
MeshCore::MeshAlgorithm(this->_kernel).GetFacetsFlag(inds, MeshCore::MeshFacet::SELECTED);
766
void MeshObject::getPointsFromSelection(std::vector<PointIndex>& inds) const
768
MeshCore::MeshAlgorithm(this->_kernel).GetPointsFlag(inds, MeshCore::MeshPoint::SELECTED);
771
unsigned long MeshObject::countSelectedFacets() const
773
return MeshCore::MeshAlgorithm(this->_kernel).CountFacetFlag(MeshCore::MeshFacet::SELECTED);
776
bool MeshObject::hasSelectedFacets() const
778
return (countSelectedFacets() > 0);
781
unsigned long MeshObject::countSelectedPoints() const
783
return MeshCore::MeshAlgorithm(this->_kernel).CountPointFlag(MeshCore::MeshPoint::SELECTED);
786
bool MeshObject::hasSelectedPoints() const
788
return (countSelectedPoints() > 0);
791
std::vector<PointIndex> MeshObject::getPointsFromFacets(const std::vector<FacetIndex>& facets) const
793
return _kernel.GetFacetPoints(facets);
796
bool MeshObject::nearestFacetOnRay(const MeshObject::TRay& ray,
798
MeshObject::TFaceSection& output) const
800
Base::Vector3f pnt = Base::toVector<float>(ray.first);
801
Base::Vector3f dir = Base::toVector<float>(ray.second);
803
Base::Placement plm = getPlacement();
804
Base::Placement inv = plm.inverse();
806
// transform the ray relative to the mesh kernel
807
inv.multVec(pnt, pnt);
808
inv.getRotation().multVec(dir, dir);
810
FacetIndex index = 0;
812
MeshCore::MeshAlgorithm alg(getKernel());
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);
824
std::vector<MeshObject::TFaceSection> MeshObject::foraminate(const TRay& ray, double maxAngle) const
826
Base::Vector3f pnt = Base::toVector<float>(ray.first);
827
Base::Vector3f dir = Base::toVector<float>(ray.second);
829
Base::Placement plm = getPlacement();
830
Base::Placement inv = plm.inverse();
832
// transform the ray relative to the mesh kernel
833
inv.multVec(pnt, pnt);
834
inv.getRotation().multVec(dir, dir);
837
MeshCore::MeshFacetIterator f_it(getKernel());
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);
845
MeshObject::TFaceSection section;
846
section.first = index;
847
section.second = Base::toVector<double>(res);
848
output.push_back(section);
855
void MeshObject::updateMesh(const std::vector<FacetIndex>& facets) const
857
std::vector<PointIndex> points;
858
points = _kernel.GetFacetPoints(facets);
860
MeshCore::MeshAlgorithm alg(_kernel);
861
alg.SetFacetsFlag(facets, MeshCore::MeshFacet::SEGMENT);
862
alg.SetPointsFlag(points, MeshCore::MeshPoint::SEGMENT);
865
void MeshObject::updateMesh() const
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);
878
std::vector<std::vector<FacetIndex>> MeshObject::getComponents() const
880
std::vector<std::vector<FacetIndex>> segments;
881
MeshCore::MeshComponents comp(_kernel);
882
comp.SearchForComponents(MeshCore::MeshComponents::OverEdge, segments);
886
unsigned long MeshObject::countComponents() const
888
std::vector<std::vector<FacetIndex>> segments;
889
MeshCore::MeshComponents comp(_kernel);
890
comp.SearchForComponents(MeshCore::MeshComponents::OverEdge, segments);
891
return segments.size();
894
void MeshObject::removeComponents(unsigned long count)
896
std::vector<FacetIndex> removeIndices;
897
MeshCore::MeshTopoAlgorithm(_kernel).FindComponents(count, removeIndices);
898
_kernel.DeleteFacets(removeIndices);
899
deletedFacets(removeIndices);
902
unsigned long MeshObject::getPointDegree(const std::vector<FacetIndex>& indices,
903
std::vector<PointIndex>& point_degree) const
905
const MeshCore::MeshFacetArray& faces = _kernel.GetFacets();
906
std::vector<PointIndex> pointDeg(_kernel.CountPoints());
908
for (const auto& face : faces) {
909
pointDeg[face._aulPoints[0]]++;
910
pointDeg[face._aulPoints[1]]++;
911
pointDeg[face._aulPoints[2]]++;
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]]--;
921
unsigned long countInvalids = std::count_if(pointDeg.begin(), pointDeg.end(), [](PointIndex v) {
925
point_degree.swap(pointDeg);
926
return countInvalids;
929
void MeshObject::fillupHoles(unsigned long length,
931
MeshCore::AbstractPolygonTriangulator& cTria)
933
std::list<std::vector<PointIndex>> aFailed;
934
MeshCore::MeshTopoAlgorithm topalg(_kernel);
935
topalg.FillupHoles(length, level, cTria, aFailed);
938
void MeshObject::offset(float fSize)
940
std::vector<Base::Vector3f> normals = _kernel.CalcVertexNormals();
943
// go through all the vertex normals
944
for (std::vector<Base::Vector3f>::iterator It = normals.begin(); It != normals.end();
946
// and move each mesh point in the normal direction
947
_kernel.MovePoint(i, It->Normalize() * fSize);
949
_kernel.RecalcBoundBox();
952
void MeshObject::offsetSpecial2(float fSize)
954
Base::Builder3D builder;
955
std::vector<Base::Vector3f> PointNormals = _kernel.CalcVertexNormals();
956
std::vector<Base::Vector3f> FaceNormals;
957
std::set<FacetIndex> fliped;
959
MeshCore::MeshFacetIterator it(_kernel);
960
for (it.Init(); it.More(); it.Next()) {
961
FaceNormals.push_back(it->GetNormal().Normalize());
966
// go through all the vertex normals
967
for (std::vector<Base::Vector3f>::iterator It = PointNormals.begin(); It != PointNormals.end();
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);
975
_kernel.RecalcBoundBox();
977
MeshCore::MeshTopoAlgorithm alg(_kernel);
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)) {
984
// calculate the angle between them
985
float angle = acos((FaceNormals[i] * it->GetNormal())
986
/ (it->GetNormal().Length() * FaceNormals[i].Length()));
988
Base::DrawStyle drawStyle;
989
drawStyle.pointSize = 4.0F;
990
Base::PointItem item {it->GetGravityPoint(),
992
Base::ColorRGB {1.0F, 0.0F, 0.0F}};
993
builder.addNode(item);
994
fliped.insert(it.Position());
998
// if there are no flipped triangles -> stop
999
// int f =fliped.size();
1000
if (fliped.empty()) {
1004
for (FacetIndex It : fliped) {
1005
alg.CollapseFacet(It);
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();
1019
void MeshObject::offsetSpecial(float fSize, float zmax, float zmin)
1021
std::vector<Base::Vector3f> normals = _kernel.CalcVertexNormals();
1024
// go through all the vertex normals
1025
for (std::vector<Base::Vector3f>::iterator It = normals.begin(); It != normals.end();
1027
auto Pnt = _kernel.GetPoint(i);
1028
if (Pnt.z < zmax && Pnt.z > zmin) {
1030
_kernel.MovePoint(i, Pnt.Normalize() * fSize);
1033
// and move each mesh point in the normal direction
1034
_kernel.MovePoint(i, It->Normalize() * fSize);
1039
void MeshObject::clear()
1042
this->_segments.clear();
1043
setTransform(Base::Matrix4D());
1046
void MeshObject::transformToEigenSystem()
1048
MeshCore::MeshEigensystem cMeshEval(_kernel);
1049
cMeshEval.Evaluate();
1050
this->setTransform(cMeshEval.Transform());
1053
Base::Matrix4D MeshObject::getEigenSystem(Base::Vector3d& v) const
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();
1062
void MeshObject::movePoint(PointIndex index, const Base::Vector3d& v)
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));
1073
void MeshObject::setPoint(PointIndex index, const Base::Vector3d& p)
1075
_kernel.SetPoint(index, transformPointToInside(p));
1078
void MeshObject::smooth(int iterations, float d_max)
1080
_kernel.Smooth(iterations, d_max);
1083
void MeshObject::decimate(float fTolerance, float fReduction)
1085
MeshCore::MeshSimplify dm(this->_kernel);
1086
dm.simplify(fTolerance, fReduction);
1089
void MeshObject::decimate(int targetSize)
1091
MeshCore::MeshSimplify dm(this->_kernel);
1092
dm.simplify(targetSize);
1095
Base::Vector3d MeshObject::getPointNormal(PointIndex index) const
1097
std::vector<Base::Vector3f> temp = _kernel.CalcVertexNormals();
1098
Base::Vector3d normal = transformVectorToOutside(temp[index]);
1103
std::vector<Base::Vector3d> MeshObject::getPointNormals() const
1105
std::vector<Base::Vector3f> temp = _kernel.CalcVertexNormals();
1107
std::vector<Base::Vector3d> normals = transformVectorsToOutside(temp);
1108
for (auto& n : normals) {
1114
void MeshObject::crossSections(const std::vector<MeshObject::TPlane>& planes,
1115
std::vector<MeshObject::TPolylines>& sections,
1117
bool bConnectPolygons) const
1119
MeshCore::MeshKernel kernel(this->_kernel);
1120
kernel.Transform(this->_Mtrx);
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);
1131
void MeshObject::cut(const Base::Polygon2d& polygon2d,
1132
const Base::ViewProjMethod& proj,
1133
MeshObject::CutType type)
1135
MeshCore::MeshKernel kernel(this->_kernel);
1136
kernel.Transform(getTransform());
1138
MeshCore::MeshAlgorithm meshAlg(kernel);
1139
std::vector<FacetIndex> check;
1154
MeshCore::MeshFacetGrid meshGrid(kernel);
1155
meshAlg.CheckFacets(meshGrid, &proj, polygon2d, inner, check);
1156
if (!check.empty()) {
1157
this->deleteFacets(check);
1161
void MeshObject::trim(const Base::Polygon2d& polygon2d,
1162
const Base::ViewProjMethod& proj,
1163
MeshObject::CutType type)
1165
MeshCore::MeshKernel kernel(this->_kernel);
1166
kernel.Transform(getTransform());
1168
MeshCore::MeshTrimming trim(kernel, &proj, polygon2d);
1169
std::vector<FacetIndex> check;
1170
std::vector<MeshCore::MeshGeomFacet> triangle;
1174
trim.SetInnerOrOuter(MeshCore::MeshTrimming::INNER);
1177
trim.SetInnerOrOuter(MeshCore::MeshTrimming::OUTER);
1181
MeshCore::MeshFacetGrid meshGrid(kernel);
1182
trim.CheckFacets(meshGrid, check);
1183
trim.TrimFacets(check, triangle);
1184
if (!check.empty()) {
1185
this->deleteFacets(check);
1188
// Re-add some triangles
1189
if (!triangle.empty()) {
1190
Base::Matrix4D mat(getTransform());
1192
for (auto& it : triangle) {
1195
this->_kernel.AddFacets(triangle);
1199
void MeshObject::trimByPlane(const Base::Vector3f& base, const Base::Vector3f& normal)
1201
MeshCore::MeshTrimByPlane trim(this->_kernel);
1202
std::vector<FacetIndex> trimFacets, removeFacets;
1203
std::vector<MeshCore::MeshGeomFacet> triangle;
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);
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);
1219
if (!triangle.empty()) {
1220
this->_kernel.AddFacets(triangle);
1224
MeshObject* MeshObject::unite(const MeshObject& mesh) const
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,
1234
MeshCore::SetOperations::Union,
1237
return new MeshObject(result);
1240
MeshObject* MeshObject::intersect(const MeshObject& mesh) const
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,
1250
MeshCore::SetOperations::Intersect,
1253
return new MeshObject(result);
1256
MeshObject* MeshObject::subtract(const MeshObject& mesh) const
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,
1266
MeshCore::SetOperations::Difference,
1269
return new MeshObject(result);
1272
MeshObject* MeshObject::inner(const MeshObject& mesh) const
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,
1282
MeshCore::SetOperations::Inner,
1285
return new MeshObject(result);
1288
MeshObject* MeshObject::outer(const MeshObject& mesh) const
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,
1298
MeshCore::SetOperations::Outer,
1301
return new MeshObject(result);
1304
std::vector<std::vector<Base::Vector3f>>
1305
MeshObject::section(const MeshObject& mesh, bool connectLines, float fMinDist) const
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;
1313
MeshCore::MeshIntersection sec(kernel1, kernel2, fMinDist);
1314
std::list<MeshCore::MeshIntersection::Tuple> tuple;
1315
sec.getIntersection(tuple);
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);
1326
std::list<std::list<MeshCore::MeshIntersection::Triple>> triple;
1327
sec.connectLines(false, tuple, triple);
1329
for (const auto& it : triple) {
1330
std::vector<Base::Vector3f> curve;
1331
curve.reserve(it.size());
1333
for (const auto& jt : it) {
1334
curve.push_back(jt.p);
1336
lines.push_back(curve);
1343
void MeshObject::refine()
1345
unsigned long cnt = _kernel.CountFacets();
1346
MeshCore::MeshFacetIterator cF(_kernel);
1347
MeshCore::MeshTopoAlgorithm topalg(_kernel);
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++) {
1352
if (!cF->IsDeformed(0.86f, -0.5f)) {
1353
topalg.InsertVertexAndSwapEdge(i, cF->GetGravityPoint(), 0.1f);
1357
// clear the segments because we don't know how the new
1358
// topology looks like
1359
this->_segments.clear();
1362
void MeshObject::removeNeedles(float length)
1364
unsigned long count = _kernel.CountFacets();
1365
MeshCore::MeshRemoveNeedles eval(_kernel, length);
1367
if (_kernel.CountFacets() < count) {
1368
this->_segments.clear();
1372
void MeshObject::validateCaps(float fMaxAngle, float fSplitFactor)
1374
MeshCore::MeshFixCaps eval(_kernel, fMaxAngle, fSplitFactor);
1378
void MeshObject::optimizeTopology(float fMaxAngle)
1380
MeshCore::MeshTopoAlgorithm topalg(_kernel);
1381
if (fMaxAngle > 0.0f) {
1382
topalg.OptimizeTopology(fMaxAngle);
1385
topalg.OptimizeTopology();
1388
// clear the segments because we don't know how the new
1389
// topology looks like
1390
this->_segments.clear();
1393
void MeshObject::optimizeEdges()
1395
MeshCore::MeshTopoAlgorithm topalg(_kernel);
1396
topalg.AdjustEdgesToCurvatureDirection();
1399
void MeshObject::splitEdges()
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();
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]);
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);
1427
// clear the segments because we don't know how the new
1428
// topology looks like
1429
this->_segments.clear();
1432
void MeshObject::splitEdge(FacetIndex facet, FacetIndex neighbour, const Base::Vector3f& v)
1434
MeshCore::MeshTopoAlgorithm topalg(_kernel);
1435
topalg.SplitEdge(facet, neighbour, v);
1438
void MeshObject::splitFacet(FacetIndex facet, const Base::Vector3f& v1, const Base::Vector3f& v2)
1440
MeshCore::MeshTopoAlgorithm topalg(_kernel);
1441
topalg.SplitFacet(facet, v1, v2);
1444
void MeshObject::swapEdge(FacetIndex facet, FacetIndex neighbour)
1446
MeshCore::MeshTopoAlgorithm topalg(_kernel);
1447
topalg.SwapEdge(facet, neighbour);
1450
void MeshObject::collapseEdge(FacetIndex facet, FacetIndex neighbour)
1452
MeshCore::MeshTopoAlgorithm topalg(_kernel);
1453
topalg.CollapseEdge(facet, neighbour);
1455
std::vector<FacetIndex> remFacets;
1456
remFacets.push_back(facet);
1457
remFacets.push_back(neighbour);
1458
deletedFacets(remFacets);
1461
void MeshObject::collapseFacet(FacetIndex facet)
1463
MeshCore::MeshTopoAlgorithm topalg(_kernel);
1464
topalg.CollapseFacet(facet);
1466
std::vector<FacetIndex> remFacets;
1467
remFacets.push_back(facet);
1468
deletedFacets(remFacets);
1471
void MeshObject::collapseFacets(const std::vector<FacetIndex>& facets)
1473
MeshCore::MeshTopoAlgorithm alg(_kernel);
1474
for (FacetIndex it : facets) {
1475
alg.CollapseFacet(it);
1478
deletedFacets(facets);
1481
void MeshObject::insertVertex(FacetIndex facet, const Base::Vector3f& v)
1483
MeshCore::MeshTopoAlgorithm topalg(_kernel);
1484
topalg.InsertVertex(facet, v);
1487
void MeshObject::snapVertex(FacetIndex facet, const Base::Vector3f& v)
1489
MeshCore::MeshTopoAlgorithm topalg(_kernel);
1490
topalg.SnapVertex(facet, v);
1493
unsigned long MeshObject::countNonUniformOrientedFacets() const
1495
MeshCore::MeshEvalOrientation cMeshEval(_kernel);
1496
std::vector<FacetIndex> inds = cMeshEval.GetIndices();
1500
void MeshObject::flipNormals()
1502
MeshCore::MeshTopoAlgorithm alg(_kernel);
1506
void MeshObject::harmonizeNormals()
1508
MeshCore::MeshTopoAlgorithm alg(_kernel);
1509
alg.HarmonizeNormals();
1512
bool MeshObject::hasNonManifolds() const
1514
MeshCore::MeshEvalTopology cMeshEval(_kernel);
1515
return !cMeshEval.Evaluate();
1518
void MeshObject::removeNonManifolds()
1520
MeshCore::MeshEvalTopology f_eval(_kernel);
1521
if (!f_eval.Evaluate()) {
1522
MeshCore::MeshFixTopology f_fix(_kernel, f_eval.GetFacets());
1524
deletedFacets(f_fix.GetDeletedFaces());
1528
void MeshObject::removeNonManifoldPoints()
1530
MeshCore::MeshEvalPointManifolds p_eval(_kernel);
1531
if (!p_eval.Evaluate()) {
1532
std::vector<FacetIndex> faces;
1533
p_eval.GetFacetIndices(faces);
1534
deleteFacets(faces);
1538
bool MeshObject::hasSelfIntersections() const
1540
MeshCore::MeshEvalSelfIntersection cMeshEval(_kernel);
1541
return !cMeshEval.Evaluate();
1544
MeshObject::TFacePairs MeshObject::getSelfIntersections() const
1546
MeshCore::MeshEvalSelfIntersection eval(getKernel());
1547
MeshObject::TFacePairs pairs;
1548
eval.GetIntersections(pairs);
1552
std::vector<Base::Line3d>
1553
MeshObject::getSelfIntersections(const MeshObject::TFacePairs& facets) const
1555
MeshCore::MeshEvalSelfIntersection eval(getKernel());
1556
using Section = std::pair<Base::Vector3f, Base::Vector3f>;
1557
std::vector<Section> selfPoints;
1558
eval.GetIntersections(facets, selfPoints);
1560
std::vector<Base::Line3d> lines;
1561
lines.reserve(selfPoints.size());
1563
Base::Matrix4D mat(getTransform());
1564
std::transform(selfPoints.begin(),
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));
1574
void MeshObject::removeSelfIntersections()
1576
std::vector<std::pair<FacetIndex, FacetIndex>> selfIntersections;
1577
MeshCore::MeshEvalSelfIntersection cMeshEval(_kernel);
1578
cMeshEval.GetIntersections(selfIntersections);
1580
if (!selfIntersections.empty()) {
1581
MeshCore::MeshFixSelfIntersection cMeshFix(_kernel, selfIntersections);
1582
deleteFacets(cMeshFix.GetFacets());
1586
void MeshObject::removeSelfIntersections(const std::vector<FacetIndex>& indices)
1588
// make sure that the number of indices is even and are in range
1589
if (indices.size() % 2 != 0) {
1592
unsigned long cntfacets = _kernel.CountFacets();
1593
if (std::find_if(indices.begin(),
1595
[cntfacets](FacetIndex v) {
1596
return v >= cntfacets;
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;
1606
FacetIndex id2 = *it;
1608
selfIntersections.emplace_back(id1, id2);
1611
if (!selfIntersections.empty()) {
1612
MeshCore::MeshFixSelfIntersection cMeshFix(_kernel, selfIntersections);
1614
this->_segments.clear();
1618
void MeshObject::removeFoldsOnSurface()
1620
std::vector<FacetIndex> indices;
1621
MeshCore::MeshEvalFoldsOnSurface s_eval(_kernel);
1622
MeshCore::MeshEvalFoldOversOnSurface f_eval(_kernel);
1625
std::vector<FacetIndex> inds = f_eval.GetIndices();
1628
std::vector<FacetIndex> inds1 = s_eval.GetIndices();
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());
1635
if (!inds.empty()) {
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()) {
1645
inds = b_eval.GetIndices();
1646
if (!inds.empty()) {
1652
void MeshObject::removeFullBoundaryFacets()
1654
std::vector<FacetIndex> facets;
1655
if (!MeshCore::MeshEvalBorderFacet(_kernel, facets).Evaluate()) {
1656
deleteFacets(facets);
1660
bool MeshObject::hasInvalidPoints() const
1662
MeshCore::MeshEvalNaNPoints nan(_kernel);
1663
return !nan.GetIndices().empty();
1666
void MeshObject::removeInvalidPoints()
1668
MeshCore::MeshEvalNaNPoints nan(_kernel);
1669
deletePoints(nan.GetIndices());
1672
bool MeshObject::hasPointsOnEdge() const
1674
MeshCore::MeshEvalPointOnEdge nan(_kernel);
1675
return !nan.Evaluate();
1678
void MeshObject::removePointsOnEdge(bool fillBoundary)
1680
MeshCore::MeshFixPointOnEdge nan(_kernel, fillBoundary);
1684
void MeshObject::mergeFacets()
1686
unsigned long count = _kernel.CountFacets();
1687
MeshCore::MeshFixMergeFacets merge(_kernel);
1689
if (_kernel.CountFacets() < count) {
1690
this->_segments.clear();
1694
void MeshObject::validateIndices()
1696
unsigned long count = _kernel.CountFacets();
1698
// for invalid neighbour indices we don't need to check first
1699
// but start directly with the validation
1700
MeshCore::MeshFixNeighbourhood fix(_kernel);
1703
MeshCore::MeshEvalRangeFacet rf(_kernel);
1704
if (!rf.Evaluate()) {
1705
MeshCore::MeshFixRangeFacet fix(_kernel);
1709
MeshCore::MeshEvalRangePoint rp(_kernel);
1710
if (!rp.Evaluate()) {
1711
MeshCore::MeshFixRangePoint fix(_kernel);
1715
MeshCore::MeshEvalCorruptedFacets cf(_kernel);
1716
if (!cf.Evaluate()) {
1717
MeshCore::MeshFixCorruptedFacets fix(_kernel);
1721
if (_kernel.CountFacets() < count) {
1722
this->_segments.clear();
1726
bool MeshObject::hasInvalidNeighbourhood() const
1728
MeshCore::MeshEvalNeighbourhood eval(_kernel);
1729
return !eval.Evaluate();
1732
bool MeshObject::hasPointsOutOfRange() const
1734
MeshCore::MeshEvalRangePoint eval(_kernel);
1735
return !eval.Evaluate();
1738
bool MeshObject::hasFacetsOutOfRange() const
1740
MeshCore::MeshEvalRangeFacet eval(_kernel);
1741
return !eval.Evaluate();
1744
bool MeshObject::hasCorruptedFacets() const
1746
MeshCore::MeshEvalCorruptedFacets eval(_kernel);
1747
return !eval.Evaluate();
1750
void MeshObject::validateDeformations(float fMaxAngle, float fEps)
1752
unsigned long count = _kernel.CountFacets();
1753
MeshCore::MeshFixDeformedFacets eval(_kernel,
1754
Base::toRadians(15.0f),
1755
Base::toRadians(150.0f),
1759
if (_kernel.CountFacets() < count) {
1760
this->_segments.clear();
1764
void MeshObject::validateDegenerations(float fEps)
1766
unsigned long count = _kernel.CountFacets();
1767
MeshCore::MeshFixDegeneratedFacets eval(_kernel, fEps);
1769
if (_kernel.CountFacets() < count) {
1770
this->_segments.clear();
1774
void MeshObject::removeDuplicatedPoints()
1776
unsigned long count = _kernel.CountFacets();
1777
MeshCore::MeshFixDuplicatePoints eval(_kernel);
1779
if (_kernel.CountFacets() < count) {
1780
this->_segments.clear();
1784
void MeshObject::removeDuplicatedFacets()
1786
unsigned long count = _kernel.CountFacets();
1787
MeshCore::MeshFixDuplicateFacets eval(_kernel);
1789
if (_kernel.CountFacets() < count) {
1790
this->_segments.clear();
1794
MeshObject* MeshObject::createMeshFromList(Py::List& list)
1796
std::vector<MeshCore::MeshGeomFacet> facets;
1797
MeshCore::MeshGeomFacet facet;
1799
for (Py::List::iterator it = list.begin(); it != list.end(); ++it) {
1801
for (int j = 0; j < 3; j++) {
1802
Py::Float value(item[j]);
1803
facet._aclPoints[i][j] = (float)value;
1808
facets.push_back(facet);
1812
Base::EmptySequencer seq;
1813
std::unique_ptr<MeshObject> mesh(new MeshObject);
1814
// mesh->addFacets(facets);
1815
mesh->getKernel() = facets;
1816
return mesh.release();
1819
MeshObject* MeshObject::createSphere(float radius, int sampling)
1821
// load the 'BuildRegularGeoms' module
1822
Base::PyGILStateLocker lock;
1824
Py::Module module(PyImport_ImportModule("BuildRegularGeoms"), true);
1825
if (module.isNull()) {
1828
Py::Dict dict = module.getDict();
1829
Py::Callable call(dict.getItem("Sphere"));
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);
1836
catch (Py::Exception& e) {
1843
MeshObject* MeshObject::createEllipsoid(float radius1, float radius2, int sampling)
1845
// load the 'BuildRegularGeoms' module
1846
Base::PyGILStateLocker lock;
1848
Py::Module module(PyImport_ImportModule("BuildRegularGeoms"), true);
1849
if (module.isNull()) {
1852
Py::Dict dict = module.getDict();
1853
Py::Callable call(dict.getItem("Ellipsoid"));
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);
1861
catch (Py::Exception& e) {
1869
MeshObject::createCylinder(float radius, float length, int closed, float edgelen, int sampling)
1871
// load the 'BuildRegularGeoms' module
1872
Base::PyGILStateLocker lock;
1874
Py::Module module(PyImport_ImportModule("BuildRegularGeoms"), true);
1875
if (module.isNull()) {
1878
Py::Dict dict = module.getDict();
1879
Py::Callable call(dict.getItem("Cylinder"));
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);
1889
catch (Py::Exception& e) {
1896
MeshObject* MeshObject::createCone(float radius1,
1903
// load the 'BuildRegularGeoms' module
1904
Base::PyGILStateLocker lock;
1906
Py::Module module(PyImport_ImportModule("BuildRegularGeoms"), true);
1907
if (module.isNull()) {
1910
Py::Dict dict = module.getDict();
1911
Py::Callable call(dict.getItem("Cone"));
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);
1922
catch (Py::Exception& e) {
1929
MeshObject* MeshObject::createTorus(float radius1, float radius2, int sampling)
1931
// load the 'BuildRegularGeoms' module
1932
Base::PyGILStateLocker lock;
1934
Py::Module module(PyImport_ImportModule("BuildRegularGeoms"), true);
1935
if (module.isNull()) {
1938
Py::Dict dict = module.getDict();
1939
Py::Callable call(dict.getItem("Toroid"));
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);
1947
catch (Py::Exception& e) {
1954
MeshObject* MeshObject::createCube(float length, float width, float height)
1956
// load the 'BuildRegularGeoms' module
1957
Base::PyGILStateLocker lock;
1959
Py::Module module(PyImport_ImportModule("BuildRegularGeoms"), true);
1960
if (module.isNull()) {
1963
Py::Dict dict = module.getDict();
1964
Py::Callable call(dict.getItem("Cube"));
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);
1972
catch (Py::Exception& e) {
1979
MeshObject* MeshObject::createCube(float length, float width, float height, float edgelen)
1981
// load the 'BuildRegularGeoms' module
1982
Base::PyGILStateLocker lock;
1984
Py::Module module(PyImport_ImportModule("BuildRegularGeoms"), true);
1985
if (module.isNull()) {
1988
Py::Dict dict = module.getDict();
1989
Py::Callable call(dict.getItem("FineCube"));
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);
1998
catch (Py::Exception& e) {
2005
MeshObject* MeshObject::createCube(const Base::BoundBox3d& bbox)
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));
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));
2031
Base::EmptySequencer seq;
2032
std::unique_ptr<MeshObject> mesh(new MeshObject);
2033
mesh->getKernel() = facets;
2034
return mesh.release();
2037
void MeshObject::addSegment(const Segment& s)
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;
2046
void MeshObject::addSegment(const std::vector<FacetIndex>& inds)
2048
unsigned long maxIndex = _kernel.CountFacets();
2049
for (FacetIndex it : inds) {
2050
if (it >= maxIndex) {
2051
throw Base::IndexError("Index out of range");
2055
this->_segments.emplace_back(this, inds, true);
2058
const Segment& MeshObject::getSegment(unsigned long index) const
2060
return this->_segments[index];
2063
Segment& MeshObject::getSegment(unsigned long index)
2065
return this->_segments[index];
2068
MeshObject* MeshObject::meshFromSegment(const std::vector<FacetIndex>& indices) const
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]);
2078
MeshCore::MeshKernel kernel;
2079
kernel.Merge(kernel_p, facets);
2081
return new MeshObject(kernel, _Mtrx);
2084
std::vector<Segment> MeshObject::getSegmentsOfType(MeshObject::GeometryType type,
2086
unsigned long minFacets) const
2088
std::vector<Segment> segm;
2089
if (this->_kernel.CountFacets() == 0) {
2093
MeshCore::MeshSegmentAlgorithm finder(this->_kernel);
2094
std::shared_ptr<MeshCore::MeshDistanceSurfaceSegment> surf;
2098
new MeshCore::MeshDistanceGenericSurfaceFitSegment(new MeshCore::PlaneSurfaceFit,
2105
new MeshCore::MeshDistanceGenericSurfaceFitSegment(new MeshCore::CylinderSurfaceFit,
2112
new MeshCore::MeshDistanceGenericSurfaceFitSegment(new MeshCore::SphereSurfaceFit,
2122
std::vector<MeshCore::MeshSurfaceSegmentPtr> surfaces;
2123
surfaces.push_back(surf);
2124
finder.FindSegments(surfaces);
2126
const std::vector<MeshCore::MeshSegment>& data = surf->GetSegments();
2127
for (const auto& it : data) {
2128
segm.emplace_back(this, it, false);
2135
// ----------------------------------------------------------------------------
2137
MeshObject::const_point_iterator::const_point_iterator(const MeshObject* mesh, PointIndex index)
2139
, _p_it(mesh->getKernel())
2141
this->_p_it.Set(index);
2142
this->_p_it.Transform(_mesh->_Mtrx);
2143
this->_point.Mesh = _mesh;
2146
MeshObject::const_point_iterator::const_point_iterator(const MeshObject::const_point_iterator& fi) =
2149
MeshObject::const_point_iterator::const_point_iterator(MeshObject::const_point_iterator&& fi) =
2152
MeshObject::const_point_iterator::~const_point_iterator() = default;
2154
MeshObject::const_point_iterator&
2155
MeshObject::const_point_iterator::operator=(const MeshObject::const_point_iterator& pi) = default;
2157
MeshObject::const_point_iterator&
2158
MeshObject::const_point_iterator::operator=(MeshObject::const_point_iterator&& pi) = default;
2160
void MeshObject::const_point_iterator::dereference()
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();
2168
const MeshPoint& MeshObject::const_point_iterator::operator*()
2171
return this->_point;
2174
const MeshPoint* MeshObject::const_point_iterator::operator->()
2177
return &(this->_point);
2180
bool MeshObject::const_point_iterator::operator==(const MeshObject::const_point_iterator& pi) const
2182
return (this->_mesh == pi._mesh) && (this->_p_it == pi._p_it);
2185
bool MeshObject::const_point_iterator::operator!=(const MeshObject::const_point_iterator& pi) const
2187
return !operator==(pi);
2190
MeshObject::const_point_iterator& MeshObject::const_point_iterator::operator++()
2196
MeshObject::const_point_iterator& MeshObject::const_point_iterator::operator--()
2202
// ----------------------------------------------------------------------------
2204
MeshObject::const_facet_iterator::const_facet_iterator(const MeshObject* mesh, FacetIndex index)
2206
, _f_it(mesh->getKernel())
2208
this->_f_it.Set(index);
2209
this->_f_it.Transform(_mesh->_Mtrx);
2210
this->_facet.Mesh = _mesh;
2213
MeshObject::const_facet_iterator::const_facet_iterator(const MeshObject::const_facet_iterator& fi) =
2216
MeshObject::const_facet_iterator::const_facet_iterator(MeshObject::const_facet_iterator&& fi) =
2219
MeshObject::const_facet_iterator::~const_facet_iterator() = default;
2221
MeshObject::const_facet_iterator&
2222
MeshObject::const_facet_iterator::operator=(const MeshObject::const_facet_iterator& fi) = default;
2224
MeshObject::const_facet_iterator&
2225
MeshObject::const_facet_iterator::operator=(MeshObject::const_facet_iterator&& fi) = default;
2227
void MeshObject::const_facet_iterator::dereference()
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];
2238
Facet& MeshObject::const_facet_iterator::operator*()
2241
return this->_facet;
2244
Facet* MeshObject::const_facet_iterator::operator->()
2247
return &(this->_facet);
2250
bool MeshObject::const_facet_iterator::operator==(const MeshObject::const_facet_iterator& fi) const
2252
return (this->_mesh == fi._mesh) && (this->_f_it == fi._f_it);
2255
bool MeshObject::const_facet_iterator::operator!=(const MeshObject::const_facet_iterator& fi) const
2257
return !operator==(fi);
2260
MeshObject::const_facet_iterator& MeshObject::const_facet_iterator::operator++()
2266
MeshObject::const_facet_iterator& MeshObject::const_facet_iterator::operator--()