/*************************************************************************** * Copyright (c) 2007 Joachim Zettler * * Copyright (c) 2007 Werner Mayer * * * * This file is part of the FreeCAD CAx development system. * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of the GNU Library General Public * * License as published by the Free Software Foundation; either * * version 2 of the License, or (at your option) any later version. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU Library General Public License for more details. * * * * You should have received a copy of the GNU Library General Public * * License along with this library; see the file COPYING.LIB. If not, * * write to the Free Software Foundation, Inc., 59 Temple Place, * * Suite 330, Boston, MA 02111-1307, USA * * * ***************************************************************************/ #include "PreCompiled.h" #include "Cutting.h" #include //Only for Testing #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace CamGui; Cutting::Cutting(QWidget* parent,Qt::WFlags fl) :QDialog(parent,fl),m_Process(NULL), m_PathSimulate(NULL),m_CuttingAlgo(NULL), m_BestFit(NULL),m_MergeData(NULL),m_Deviation(NULL) { this->setupUi(this); m_timer= false; } Cutting::~Cutting() { delete m_CuttingAlgo; delete m_PathSimulate; delete m_Process; delete m_BestFit; delete m_Deviation; delete m_MergeData; } bool Cutting::getProcessOutput() { QByteArray result = m_Process->readAll(); if (result.contains("Error")) { m_Process->kill(); QMessageBox::critical(this, tr("FreeCAD CamWorkbench"), tr("Error in generation\n"), QMessageBox::Ok, QMessageBox::NoButton); } else if (result.contains("N o r m a l t e r m i n a t i o n")) { QMessageBox::information(this, tr("FreeCAD CamWorkbench"), tr("Dyna-Job finished well\n"), QMessageBox::Ok, QMessageBox::NoButton); } return true; } void Cutting::on_adaptdynainput_clicked() { //First we have to select the LS-Dyna Masterfile and the current working dir QString filename, path, program; QStringList arguments; QString strcheck("dyna.str"); filename = QFileDialog::getOpenFileName( this, "Open Dyna.Str or Master-Key File",filename,"Ls-Dyna Keywords (*.k) (*.str)" ); if (filename.isNull()) return; QFileInfo aFileInfo(filename); path = aFileInfo.absolutePath(); QDir::setCurrent(path); program = "c:/Program Files/lsdyna/ls971d"; //As the new Versions already account for a proper curve file we no longer have to adapt the input //if we already have a str File we will not step into the next if-case //if(!aFileInfo.fileName().contains("dyna.str")) //{ // arguments << " i="<< aFileInfo.fileName(); // m_Process = new QProcess(this); // m_Process->start(program, arguments); // //Now we check if the output is written correctly // m_Process->waitForFinished(50000); // aFileInfo.setFile("dyna.str"); // if (aFileInfo.size() == 0) //the file does not exist // { // QMessageBox::critical(this, tr("FreeCAD CamWorkbench"), // tr("Error when creating the Struct file\n"), // QMessageBox::Ok, QMessageBox::NoButton); // return; // } // else // { // QMessageBox::information(this, tr("FreeCAD CamWorkbench"), // tr("Structured Dyna generated well\n"), // QMessageBox::Ok, QMessageBox::NoButton); // } //} //ChangeDyna aFileChanger; //if (aFileChanger.Read("dyna.str")) // start_simulation->show(); //else{ // QMessageBox::critical(this, tr("FreeCAD CamWorkbench"), // tr("Error while parsing the str File\n"), // QMessageBox::Ok, QMessageBox::NoButton); // return; //} } void Cutting::on_start_simulation_clicked() { //check if the initial process is already killed m_Process->kill(); QString program; QStringList arguments; program = "c:/Program Files/lsdyna/ls971d"; arguments << " i=dyna2.str"; connect(m_Process,SIGNAL(readyReadStandardError()),this,SLOT(getProcessOutput())); connect(m_Process,SIGNAL(readyReadStandardOutput()),this,SLOT(getProcessOutput())); m_Process->start(program, arguments); } void Cutting::on_Deviation_button_clicked() { m_Deviation = new Deviation(); deviation_geometry1_button->setEnabled(true); deviation_geometry2_button->setEnabled(true); deviation_go_button->setEnabled(true); } void Cutting::on_deviation_geometry1_button_clicked() { selectShape(); } void Cutting::on_deviation_geometry2_button_clicked() { selectMesh(); } void Cutting::on_deviation_go_button_clicked() { QString current_filename = QFileDialog::getSaveFileName(this,"Select Deviation Files","","*.txt"); m_Deviation->ImportGeometry(m_Shape, m_Mesh); m_Deviation->Compute(); m_Deviation->WriteOutput(current_filename); } void Cutting::on_error_accumulation_select_files_button_clicked() { m_MergeData = new MergeData(); QStringList m_dateinamen = QFileDialog::getOpenFileNames( this, "Select one or more files to open", "c:", "Deviation Files (*.txt)"); if (!m_dateinamen.isEmpty()) { if (!m_MergeData->Einlesen(m_dateinamen)) { QMessageBox::information(this, tr("FreeCAD CamWorkbench"), tr("Everything OK. Output can be generated\n"), QMessageBox::Ok, QMessageBox::NoButton); } } error_accumulation_go_button->setEnabled(true); } void Cutting::on_error_accumulation_go_button_clicked() { QString current_filename = QFileDialog::getSaveFileName(this,"Select Output File","","*.txt"); m_MergeData->WriteOutput(current_filename); } void Cutting::selectShape() { if (!m_timer) { int check_box1=0,check_box2=0; if (!m_Shape.IsNull()) { check_box1 = QMessageBox::question(this, tr("FreeCAD CamWorkbench"), tr("You have already selected a CAD-Shape.\n" "Do you want to make a new Selection?"), QMessageBox::Yes, QMessageBox::No); } else { check_box2 = QMessageBox::information(this, tr("FreeCAD CamWorkbench"), tr("You have to select a CAD-Shape.\n"), QMessageBox::Ok, QMessageBox::Cancel); } if ((check_box1 == QMessageBox::Yes) || (check_box2 == QMessageBox::Ok)) { //First, remove the old selection from the Gui, so that we do not directly have the same CAD once again. Gui::Selection().clearCompleteSelection(); //to make a Selection more easy, hide the dialog this->hide(); QTimer::singleShot(100,this,SLOT(selectShape())); m_timer = true; } } else { std::vector fea = Gui::Selection().getObjectsOfType(Part::Feature::getClassTypeId()); if ( fea.size() == 1) { m_Shape = static_cast(fea.front())->Shape.getValue(); //std::vector aSelection = Gui::Selection().getSelection(); this->show(); CalculateZLevel->setEnabled(true); CalculateFeatureBased->setEnabled(true); CalculateSpiralBased->setEnabled(true); m_timer = false; } else { QTimer::singleShot(100,this,SLOT(selectShape())); m_timer = true; } } } void Cutting::selectMesh() { if (!m_timer) { int check_box1=0,check_box2=0; if (m_Mesh.CountPoints() > 0) { check_box1 = QMessageBox::question(this, tr("FreeCAD CamWorkbench"), tr("You have already selected a Mesh.\n" "Do you want to make a new Selection?"), QMessageBox::Yes, QMessageBox::No); } else { check_box2 = QMessageBox::information(this, tr("FreeCAD CamWorkbench"), tr("You have to select a Mesh.\n"), QMessageBox::Ok, QMessageBox::Cancel); } if ((check_box1 == QMessageBox::Yes) || (check_box2 == QMessageBox::Ok)) { //First, remove the old selection from the Gui, so that we do not directly have the same CAD once again. Gui::Selection().clearCompleteSelection(); //to make a Selection more easy, hide the dialog this->hide(); QTimer::singleShot(100,this,SLOT(selectMesh())); m_timer = true; } } else { std::vector fea = Gui::Selection().getObjectsOfType(Mesh::Feature::getClassTypeId()); if ( fea.size() == 1) { m_Mesh = static_cast(fea.front())->Mesh.getValue().getKernel(); //std::vector aSelection = Gui::Selection().getSelection(); this->show(); m_timer = false; } else { QTimer::singleShot(100,this,SLOT(selectMesh())); m_timer = true; } } } void Cutting::setFace(const TopoDS_Shape& aShape, const float x, const float y, const float z) { //check if a Shape is selected std::vector fea = Gui::Selection().getObjectsOfType(Part::Feature::getClassTypeId()); if ( fea.size() == 1) { int test = aShape.ShapeType(); //get Hash Code of Selected Face inside the selected Shape and also the Coordinates of the click if (aShape.ShapeType() != TopAbs_FACE) { QMessageBox::information(this, tr("FreeCAD CamWorkbench"), tr("You have to select a Face!!\n")); return; } TopoDS_Face tempFace = TopoDS::Face(aShape); //Now search for the Hash-Code in the m_Shape TopExp_Explorer anExplorer; TopoDS_Face aselectedFace; //pickPoint.Set(x,y,z); for (anExplorer.Init(m_Shape,TopAbs_FACE);anExplorer.More();anExplorer.Next()) { if (tempFace.HashCode(IntegerLast()) == anExplorer.Current().HashCode(IntegerLast())) { if (m_selection == Springback) (m_Spring->m_FixFaces).push_back(TopoDS::Face(anExplorer.Current())); else if (m_selection == BestFit) (m_BestFit->m_LowFaces).push_back(TopoDS::Face(anExplorer.Current())); else if (m_selection == ToolpathCalculation) m_CuttingAlgo->SetMachiningOrder(TopoDS::Face(anExplorer.Current()),x,y,z); break; } } } } void Cutting::on_CalculateZLevel_clicked() { // Instantiating Cutting class if (m_CuttingAlgo == NULL) m_CuttingAlgo = new cutting_tools(m_Shape); else { delete m_CuttingAlgo; m_CuttingAlgo = new cutting_tools(m_Shape); } m_Mode = 1; CalculateFeatureBased->setEnabled(false); CalculateSpiralBased->setEnabled(false); toolpath_calculation_highest_level_button->setEnabled(true); m_selection = ToolpathCalculation; } void Cutting::on_CalculateFeatureBased_clicked() { if (m_CuttingAlgo == NULL) m_CuttingAlgo = new cutting_tools(m_Shape); else { delete m_CuttingAlgo; m_CuttingAlgo = new cutting_tools(m_Shape); } m_Mode = 2; toolpath_calculation_highest_level_button->setEnabled(true); m_selection = ToolpathCalculation; CalculateZLevel->setEnabled(false); CalculateSpiralBased->setEnabled(false); } void Cutting::on_CalculateSpiralBased_clicked() { if (m_CuttingAlgo == NULL) m_CuttingAlgo = new cutting_tools(m_Shape); else { delete m_CuttingAlgo; m_CuttingAlgo = new cutting_tools(m_Shape); } m_Mode = 3;// toolpath_calculation_highest_level_button->setEnabled(true); m_selection = ToolpathCalculation; CalculateZLevel->setEnabled(false); CalculateFeatureBased->setEnabled(false); } void Cutting::on_select_shape_z_level_button_clicked() { selectShape(); } void Cutting::on_select_shape_feature_based_button_clicked() { selectShape(); } void Cutting::on_select_shape_spiral_based_button_clicked() { selectShape(); } void Cutting::on_toolpath_calculation_highest_level_button_clicked() { Gui::Document* doc = Gui::Application::Instance->activeDocument(); Gui::View3DInventor* view = static_cast(doc->getActiveView()); if (view) { Gui::View3DInventorViewer* viewer = view->getViewer(); viewer->setEditing(true); viewer->addEventCallback(SoMouseButtonEvent::getClassTypeId(), zLevelCallback, this); QMessageBox::information(this, tr("FreeCAD CamWorkbench"), tr("You have to pick a point.\n")); this->hide(); } toolpath_calculation_middle_level_button->setEnabled(true); toolpath_calculation_lowest_level_button->setEnabled(true); } void Cutting::on_toolpath_calculation_middle_level_button_clicked() { Gui::Document* doc = Gui::Application::Instance->activeDocument(); Gui::View3DInventor* view = static_cast(doc->getActiveView()); if (view) { Gui::View3DInventorViewer* viewer = view->getViewer(); viewer->setEditing(true); viewer->addEventCallback(SoMouseButtonEvent::getClassTypeId(), zLevelCallback, this); QMessageBox::information(this, tr("FreeCAD CamWorkbench"), tr("You have to pick a point.\n")); this->hide(); } } void Cutting::on_toolpath_calculation_lowest_level_button_clicked() { Gui::Document* doc = Gui::Application::Instance->activeDocument(); Gui::View3DInventor* view = static_cast(doc->getActiveView()); if (view) { Gui::View3DInventorViewer* viewer = view->getViewer(); viewer->setEditing(true); viewer->addEventCallback(SoMouseButtonEvent::getClassTypeId(), zLevelCallback, this); QMessageBox::information(this, tr("FreeCAD CamWorkbench"), tr("You have to pick a point.\n")); this->hide(); } toolpath_calculation_go_button->setEnabled(true); } void Cutting::on_toolpath_calculation_go_button_clicked() { //Do the actual Cut //First transfer the settings to the Cutting_tools class m_CuttingAlgo->m_UserSettings = getSettings(); if (!m_CuttingAlgo->arrangecuts_ZLEVEL()) { std::cout << "Couldn't cut properly" << std::endl; } bool ok = true; try { switch (m_Mode) { case 1: ok = m_CuttingAlgo->OffsetWires_Standard(); break; case 2: ok = m_CuttingAlgo->OffsetWires_FeatureBased(); break; case 3: ok = m_CuttingAlgo->OffsetWires_Spiral(); break; } } catch (...) { std::cout<<"Error"<setEnabled(true); GenSimOut->setEnabled(true); } void Cutting::on_GenSimOut_clicked() { QString dir = QFileDialog::getExistingDirectory(this, tr("Select Simulation-Path Output-Directory"),"d:/", QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks); if (dir.isNull()) return; QDir::setCurrent(dir); if (m_PathSimulate != NULL) delete m_PathSimulate;//If it exists already m_PathSimulate = new path_simulate(*(m_CuttingAlgo->getOutputhigh()),*(m_CuttingAlgo->getOutputlow()),m_CuttingAlgo->m_UserSettings); switch (m_Mode) { case 1: if (m_PathSimulate->MakePathSimulate()) adaptdynainput->setEnabled(true); break; case 2: if (m_PathSimulate->MakePathSimulate_Feat(m_CuttingAlgo->getFlatAreas(),0)) adaptdynainput->setEnabled(true); break; case 3: if (m_PathSimulate->MakePathSimulate_Feat(m_CuttingAlgo->getFlatAreas(),1)) adaptdynainput->setEnabled(true); break; } } void Cutting::on_GenRobotOut_clicked() { QString dir = QFileDialog::getExistingDirectory(this, tr("Select File Output-Directory"),"d:/", QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks); QDir::setCurrent(dir); if (m_PathSimulate != NULL) delete m_PathSimulate; m_PathSimulate = new path_simulate(*(m_CuttingAlgo->getOutputhigh()),*(m_CuttingAlgo->getOutputlow()),m_CuttingAlgo->m_UserSettings); switch (m_Mode) { case 1: m_PathSimulate->MakePathRobot(); break; case 2: m_PathSimulate->MakePathRobot_Feat(m_CuttingAlgo->getFlatAreas()); break; } } const CuttingToolsSettings& Cutting::getSettings() { //First transfer the settings to the Cutting_tools class m_Settings.cad_radius = cad_radius_box->value(); m_Settings.correction_factor = correction_factor_box->value(); m_Settings.level_distance = level_distance_box->value(); m_Settings.limit_angle = limit_angle_box->value(); m_Settings.sheet_thickness = sheet_thickness_box->value(); m_Settings.slave_radius = slave_radius_box->value(); m_Settings.master_radius = master_radius_box->value(); m_Settings.max_Vel = max_vel->value(); m_Settings.max_Acc = max_acc->value(); m_Settings.spring_pretension = spring_pretension->value(); m_Settings.x_offset_robot = xoffset_box->value(); m_Settings.y_offset_robot = yoffset_box->value(); m_Settings.clockwise = clockwise_checkbox->isChecked(); m_Settings.error_tolerance = error_tolerance->value(); return m_Settings; } void Cutting::on_BestFitButton_clicked() { m_selection = BestFit; m_BestFit = new best_fit(); // Best-Fit based on Point-Clouds m_BestFit->Initialize_Mesh_Geometrie_1(); m_BestFit->Initialize_Mesh_Geometrie_2(); m_BestFit->Perform_PointCloud(); m_BestFit->output_best_fit_mesh(); best_fit_cad_button->setEnabled(true); } void Cutting::on_SpringbackButton_clicked() { m_Spring = new SpringbackCorrection(); m_selection = Springback; best_fit_cad_button->setEnabled(true); } void Cutting::on_Approximate_button_clicked() { m_selection = Approx; best_fit_mesh_button->setEnabled(true); } void Cutting::on_best_fit_cad_button_clicked() { selectShape(); best_fit_mesh_button->setEnabled(true); } void Cutting::on_best_fit_mesh_button_clicked() { if(m_selection == Springback) { best_fit_mesh2_button->setEnabled(true); m_Spring->Load(m_Shape); } selectMesh(); best_fit_go_button->setEnabled(true); SelectFace_button->setEnabled(true); if(m_selection == Springback) best_fit_mesh2_button->setEnabled(true); } void Cutting::on_best_fit_mesh2_button_clicked() { m_Spring->Load(m_Mesh); selectMesh(); } void Cutting::on_SelectFace_button_clicked() { Gui::Document* doc = Gui::Application::Instance->activeDocument(); Gui::View3DInventor* view = static_cast(doc->getActiveView()); if (view) { Gui::View3DInventorViewer* viewer = view->getViewer(); viewer->setEditing(true); viewer->addEventCallback(SoMouseButtonEvent::getClassTypeId(), zLevelCallback, this); QMessageBox::information(this, tr("FreeCAD CamWorkbench"), tr("You have to pick a face.\n")); this->hide(); } } void Cutting::on_best_fit_go_button_clicked() { bool out = 1; //specifies whether ONLY the error vectors should be output in the case of springback getSettings(); //First transfer the settings to the Cutting_tools class (-> m_Settings) switch (m_selection) { case BestFit: m_BestFit->Load(m_Mesh,m_Shape); m_BestFit->Perform(); best_fit_cad_button ->setEnabled(false); best_fit_mesh_button->setEnabled(false); best_fit_go_button ->setEnabled(false); m_MeshOut = m_BestFit->m_MeshWork; m_MeshCad = m_BestFit->m_CadMesh; DisplayMeshOutput(m_MeshOut); //DisplayMeshOutput(m_MeshCad); break; case Springback: m_Spring->Load(m_Mesh); m_Spring->Init_Setting(m_Settings); m_Spring->Init(); m_Spring->Perform(m_Settings.limit_angle,out); m_MeshCad = m_Spring->m_CadMesh; best_fit_cad_button ->setEnabled(false); best_fit_mesh_button->setEnabled(false); best_fit_go_button ->setEnabled(false); if(out==0) { DisplayMeshOutput(m_MeshCad); DisplayMeshOutput(m_Spring->m_Mesh_vis); DisplayMeshOutput(m_Spring->m_Mesh_vis2); } best_fit_mesh2_button->setEnabled(true); break; case Approx: // The file "Kleines.stl" has a point above the level ... not compatible with this Algo /*MeshCore::MeshPointArray pnts = m_Mesh.GetPoints(); MeshCore::MeshFacetArray facets = m_Mesh.GetFacets(); for(int i=0; i0.0) pnts[i].z *= -1; } m_Mesh.Assign(pnts,facets);*/ std::vector CtrlPnts, U_knot, V_knot; int degU,degV; m_App = new Approximate(m_Mesh,CtrlPnts,U_knot,V_knot,degU,degV,m_Settings.error_tolerance); //m_Approx = new UniGridApprox(m_Mesh, 1); //m_Approx->Perform(0.1); BRepBuilderAPI_MakeFace Face(m_App->aAdaptorSurface.Surface()); m_Shape = Face.Face(); ofstream anOutputFile; anOutputFile.open("c:/approx_log.txt"); anOutputFile << "face assigned" << endl; DisplayMeshOutput(m_App->MeshParam); DisplayShapeOutput(); break; } } void Cutting::DisplayMeshOutput(const MeshCore::MeshKernel &mesh) { App::Document* doc = App::GetApplication().getActiveDocument(); App::DocumentObject* obj = doc->addObject("Mesh::Feature","Best_Fit-Mesh"); Mesh::Feature* part1 = static_cast(obj); part1->Mesh.setValue(mesh); //doc->recompute(); } void Cutting::DisplayShapeOutput() { App::Document* doc = App::GetApplication().getActiveDocument(); App::DocumentObject* obj = doc->addObject("Part::Feature","Output-Shape"); Part::Feature* part1 = static_cast(obj); part1->Shape.setValue(m_Shape); //doc->recompute(); } void Cutting::DisplayCAMOutput() { BRep_Builder BB; TopoDS_Compound aCompound1,aCompound2; BB.MakeCompound(aCompound1); BB.MakeCompound(aCompound2); TopoDS_Edge anEdge; const std::vector* topCurves; const std::vector* botCurves; std::vector::const_iterator an_it1; topCurves = m_CuttingAlgo->getOutputhigh(); botCurves = m_CuttingAlgo->getOutputlow(); for (an_it1 = topCurves->begin();an_it1!=topCurves->end();an_it1++) { BB.MakeEdge(anEdge,*an_it1,0.01); BB.Add(aCompound1,anEdge); } for (an_it1 = botCurves->begin();an_it1!=botCurves->end();an_it1++) { BB.MakeEdge(anEdge,*an_it1,0.01); BB.Add(aCompound2,anEdge); } App::Document* doc = App::GetApplication().getActiveDocument(); App::DocumentObject* obj = doc->addObject("Part::Feature","Master-Tool"); App::DocumentObject* obj1 = doc->addObject("Part::Feature","Slave-Tool"); Part::Feature* part1 = static_cast(obj); Part::Feature* part2 = static_cast(obj1); part1->Shape.setValue(aCompound1); part2->Shape.setValue(aCompound2); // // for (unsigned int i=0;i topCurves; //std::vector botCurves; //std::vector::iterator an_it; //topCurves = *(anewCuttingEnv.getOutputhigh()); //botCurves = *(anewCuttingEnv.getOutputlow()); ofstream anoutput; ofstream anoutput2; anoutput.open("c:/topCurves.txt"); anoutput2.open("c:/botCurves.txt"); for (an_it1 = topCurves->begin();an_it1!=topCurves->end();an_it1++) { GeomAdaptor_Curve aCurveAdaptor(*an_it1); GCPnts_QuasiUniformDeflection aPointGenerator(aCurveAdaptor,0.1); for (int t=1;t<=aPointGenerator.NbPoints();++t) { anoutput << (aPointGenerator.Value(t)).X() <<","<< (aPointGenerator.Value(t)).Y() <<","<<(aPointGenerator.Value(t)).Z()<begin();an_it1!=botCurves->end();an_it1++) { GeomAdaptor_Curve aCurveAdaptor(*an_it1); GCPnts_QuasiUniformDeflection aPointGenerator(aCurveAdaptor,0.1); for (int t=1;t<=aPointGenerator.NbPoints();++t) { anoutput2 << (aPointGenerator.Value(t)).X() <<","<< (aPointGenerator.Value(t)).Y() <<","<<(aPointGenerator.Value(t)).Z()<getEvent(); Gui::View3DInventorViewer* view = reinterpret_cast(n->getUserData()); Cutting* that = reinterpret_cast(ud); // Mark all incoming mouse button events as handled, especially, to deactivate the selection node n->getAction()->setHandled(); if (mbe->getButton() == SoMouseButtonEvent::BUTTON2 && mbe->getState() == SoButtonEvent::UP) { n->setHandled(); view->setEditing(false); view->removeEventCallback(SoMouseButtonEvent::getClassTypeId(), zLevelCallback, that); that->show(); } else if (mbe->getButton() == SoMouseButtonEvent::BUTTON1 && mbe->getState() == SoButtonEvent::DOWN) { const SoPickedPoint * point = n->getPickedPoint(); if (point == NULL) { QMessageBox::warning(Gui::getMainWindow(),"z level", "No shape picked!"); return; } n->setHandled(); // By specifying the indexed mesh node 'pcFaceSet' we make sure that the picked point is // really from the mesh we render and not from any other geometry Gui::ViewProvider* vp = static_cast(view->getViewProviderByPath(point->getPath())); if (!vp || !vp->getTypeId().isDerivedFrom(PartGui::ViewProviderPart::getClassTypeId())) return; PartGui::ViewProviderPart* vpp = static_cast(vp); std::string element = vpp->getElement(point->getDetail()); TopoDS_Shape sh = static_cast(vpp->getObject())-> Shape.getShape().getSubShape(element.c_str()); if (!sh.IsNull()) { // ok a shape was picked n->setHandled(); view->setEditing(false); view->removeEventCallback(SoMouseButtonEvent::getClassTypeId(), zLevelCallback, that); that->show(); SbVec3f pt = point->getPoint(); that->setFace(sh, pt[0],pt[1],pt[2]); } } } #include "moc_Cutting.cpp"