| | |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| |
|
| | #include <sstream> |
| |
|
| | #include <BRepBuilderAPI_MakePolygon.hxx> |
| | #include <BRep_Builder.hxx> |
| | #include <GeomAPI_ProjectPointOnSurf.hxx> |
| | #include <Geom_Plane.hxx> |
| | #include <Standard_Failure.hxx> |
| | #include <TopoDS_Compound.hxx> |
| | #include <TopoDS_Wire.hxx> |
| |
|
| | #include <App/Application.h> |
| | #include <App/Document.h> |
| | #include <App/DocumentObjectGroup.h> |
| | #include <Base/Console.h> |
| | #include <Gui/WaitCursor.h> |
| | #include <Mod/Mesh/App/Core/Algorithm.h> |
| | #include <Mod/Mesh/App/Core/Approximation.h> |
| | #include <Mod/Mesh/App/Core/Curvature.h> |
| | #include <Mod/Mesh/App/Core/Segmentation.h> |
| | #include <Mod/Mesh/App/Core/Smoothing.h> |
| | #include <Mod/Mesh/App/MeshFeature.h> |
| | #include <Mod/Part/App/FaceMakerCheese.h> |
| | #include <Mod/Part/App/PartFeature.h> |
| |
|
| | #include "Segmentation.h" |
| | #include "ui_Segmentation.h" |
| |
|
| |
|
| | using namespace ReverseEngineeringGui; |
| |
|
| | Segmentation::Segmentation(Mesh::Feature* mesh, QWidget* parent, Qt::WindowFlags fl) |
| | : QWidget(parent, fl) |
| | , ui(new Ui_Segmentation) |
| | , myMesh(mesh) |
| | { |
| | ui->setupUi(this); |
| | ui->numPln->setRange(1, std::numeric_limits<int>::max()); |
| | ui->numPln->setValue(100); |
| |
|
| | ui->checkBoxSmooth->setChecked(false); |
| | } |
| |
|
| | Segmentation::~Segmentation() = default; |
| |
|
| | void Segmentation::accept() |
| | { |
| | if (myMesh.expired()) { |
| | return; |
| | } |
| |
|
| | Gui::WaitCursor wc; |
| | bool createUnused = ui->createUnused->isChecked(); |
| | bool createCompound = ui->createCompound->isChecked(); |
| | BRep_Builder builder; |
| | TopoDS_Compound compound; |
| | builder.MakeCompound(compound); |
| |
|
| | const Mesh::MeshObject* mesh = myMesh.get<Mesh::Feature>()->Mesh.getValuePtr(); |
| | |
| | MeshCore::MeshKernel kernel = mesh->getKernel(); |
| | MeshCore::MeshAlgorithm algo(kernel); |
| |
|
| | if (ui->checkBoxSmooth->isChecked()) { |
| | MeshCore::LaplaceSmoothing smoother(kernel); |
| | smoother.Smooth(ui->smoothSteps->value()); |
| | } |
| |
|
| | MeshCore::MeshSegmentAlgorithm finder(kernel); |
| | MeshCore::MeshCurvature meshCurv(kernel); |
| | meshCurv.ComputePerVertex(); |
| |
|
| | |
| | std::vector<MeshCore::MeshSurfaceSegmentPtr> segm; |
| | if (ui->groupBoxPln->isChecked()) { |
| | segm.emplace_back( |
| | std::make_shared<MeshCore::MeshCurvaturePlanarSegment>( |
| | meshCurv.GetCurvature(), |
| | ui->numPln->value(), |
| | ui->curvTolPln->value() |
| | ) |
| | ); |
| | } |
| | finder.FindSegments(segm); |
| |
|
| | std::vector<MeshCore::MeshSurfaceSegmentPtr> segmSurf; |
| | for (const auto& it : segm) { |
| | const std::vector<MeshCore::MeshSegment>& data = it->GetSegments(); |
| |
|
| | |
| | |
| | if (strcmp(it->GetType(), "Plane") == 0) { |
| | for (const auto& jt : data) { |
| | std::vector<MeshCore::PointIndex> indexes = kernel.GetFacetPoints(jt); |
| | MeshCore::PlaneFit fit; |
| | fit.AddPoints(kernel.GetPoints(indexes)); |
| | if (fit.Fit() < std::numeric_limits<float>::max()) { |
| | Base::Vector3f base = fit.GetBase(); |
| | Base::Vector3f axis = fit.GetNormal(); |
| | MeshCore::AbstractSurfaceFit* fitter = new MeshCore::PlaneSurfaceFit(base, axis); |
| | segmSurf.emplace_back( |
| | std::make_shared<MeshCore::MeshDistanceGenericSurfaceFitSegment>( |
| | fitter, |
| | kernel, |
| | ui->numPln->value(), |
| | ui->distToPln->value() |
| | ) |
| | ); |
| | } |
| | } |
| | } |
| | } |
| | finder.FindSegments(segmSurf); |
| |
|
| | App::Document* document = App::GetApplication().getActiveDocument(); |
| | document->openTransaction("Segmentation"); |
| |
|
| | std::string internalname = "Segments_"; |
| | internalname += myMesh->getNameInDocument(); |
| |
|
| | auto* group = document->addObject<App::DocumentObjectGroup>(internalname.c_str()); |
| | std::string labelname = "Segments "; |
| | labelname += myMesh->Label.getValue(); |
| | group->Label.setValue(labelname); |
| |
|
| | std::vector<App::DocumentObject*> failures; |
| | algo.SetFacetFlag(MeshCore::MeshFacet::TMP0); |
| |
|
| | for (const auto& it : segmSurf) { |
| | const std::vector<MeshCore::MeshSegment>& data = it->GetSegments(); |
| | std::shared_ptr<MeshCore::MeshDistanceGenericSurfaceFitSegment> genSegm |
| | = std::dynamic_pointer_cast<MeshCore::MeshDistanceGenericSurfaceFitSegment>(it); |
| |
|
| | bool isPlanar = (strcmp(genSegm->GetType(), "Plane") == 0); |
| | for (const auto& jt : data) { |
| | |
| | algo.ResetFacetsFlag(jt, MeshCore::MeshFacet::TMP0); |
| |
|
| | Mesh::MeshObject* segment = mesh->meshFromSegment(jt); |
| | Mesh::Feature* feaSegm = static_cast<Mesh::Feature*>( |
| | group->addObject("Mesh::Feature", "Segment") |
| | ); |
| | Mesh::MeshObject* feaMesh = feaSegm->Mesh.startEditing(); |
| | feaMesh->swap(*segment); |
| | feaSegm->Mesh.finishEditing(); |
| | delete segment; |
| |
|
| | std::stringstream label; |
| | label << feaSegm->Label.getValue() << " (" << it->GetType() << ")"; |
| | feaSegm->Label.setValue(label.str()); |
| |
|
| | if (createCompound) { |
| | std::list<std::vector<Base::Vector3f>> bounds; |
| | algo.GetFacetBorders(jt, bounds); |
| |
|
| | |
| | if (isPlanar) { |
| | std::vector<float> par = genSegm->Parameters(); |
| | gp_Pnt loc(par.at(0), par.at(1), par.at(2)); |
| | gp_Dir dir(par.at(3), par.at(4), par.at(5)); |
| |
|
| | Handle(Geom_Plane) hPlane(new Geom_Plane(loc, dir)); |
| |
|
| | std::vector<TopoDS_Wire> wires; |
| | for (const auto& bound : bounds) { |
| | |
| | std::vector<gp_Pnt> polygon; |
| | std::transform( |
| | bound.begin(), |
| | bound.end(), |
| | std::back_inserter(polygon), |
| | [&hPlane](const Base::Vector3f& v) { |
| | gp_Pnt p(v.x, v.y, v.z); |
| | return GeomAPI_ProjectPointOnSurf(p, hPlane).NearestPoint(); |
| | } |
| | ); |
| |
|
| | BRepBuilderAPI_MakePolygon mkPoly; |
| | for (std::vector<gp_Pnt>::reverse_iterator it = polygon.rbegin(); |
| | it != polygon.rend(); |
| | ++it) { |
| | mkPoly.Add(*it); |
| | } |
| | if (mkPoly.IsDone()) { |
| | wires.push_back(mkPoly.Wire()); |
| | } |
| | } |
| |
|
| | try { |
| | TopoDS_Shape shape = Part::FaceMakerCheese::makeFace(wires); |
| | if (!shape.IsNull()) { |
| | builder.Add(compound, shape); |
| | } |
| | else { |
| | failures.push_back(feaSegm); |
| | Base::Console().warning( |
| | "Failed to create face from %s\n", |
| | feaSegm->Label.getValue() |
| | ); |
| | } |
| | } |
| | catch (Standard_Failure&) { |
| | failures.push_back(feaSegm); |
| | Base::Console().error( |
| | "Fatal failure to create face from %s\n", |
| | feaSegm->Label.getValue() |
| | ); |
| | } |
| | } |
| | } |
| | } |
| | } |
| |
|
| | if (createUnused) { |
| | |
| | std::vector<MeshCore::FacetIndex> unusedFacets; |
| | algo.GetFacetsFlag(unusedFacets, MeshCore::MeshFacet::TMP0); |
| |
|
| | if (!unusedFacets.empty()) { |
| | std::unique_ptr<Mesh::MeshObject> segment(mesh->meshFromSegment(unusedFacets)); |
| | Mesh::Feature* feaSegm = static_cast<Mesh::Feature*>( |
| | group->addObject("Mesh::Feature", "Unused") |
| | ); |
| | Mesh::MeshObject* feaMesh = feaSegm->Mesh.startEditing(); |
| | feaMesh->swap(*segment); |
| | feaSegm->Mesh.finishEditing(); |
| | } |
| | } |
| | if (createCompound) { |
| | Part::Feature* shapeFea = static_cast<Part::Feature*>( |
| | group->addObject("Part::Feature", "Compound") |
| | ); |
| | shapeFea->Shape.setValue(compound); |
| |
|
| | |
| | if (!failures.empty()) { |
| | App::DocumentObjectGroup* subgroup = static_cast<App::DocumentObjectGroup*>( |
| | group->addObject("App::DocumentObjectGroup", "Failed") |
| | ); |
| | failures = group->removeObjects(failures); |
| | subgroup->Group.setValues(failures); |
| | } |
| | } |
| |
|
| | document->commitTransaction(); |
| | } |
| |
|
| | void Segmentation::changeEvent(QEvent* e) |
| | { |
| | if (e->type() == QEvent::LanguageChange) { |
| | ui->retranslateUi(this); |
| | } |
| | QWidget::changeEvent(e); |
| | } |
| |
|
| | |
| |
|
| | |
| |
|
| | TaskSegmentation::TaskSegmentation(Mesh::Feature* mesh) |
| | { |
| | widget = new Segmentation(mesh); |
| | addTaskBox(widget, false); |
| | } |
| |
|
| | bool TaskSegmentation::accept() |
| | { |
| | widget->accept(); |
| | return true; |
| | } |
| |
|
| | #include "moc_Segmentation.cpp" |
| |
|