/*************************************************************************** * Copyright (c) 2007 * * Joachim Zettler * * * * 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" //Mesh Stuff #include #include #include #include #include #include #include //FreeCAD Stuff #include //OCC Stuff #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 //Own Stuff #include "cutting_tools.h" #include "best_fit.h" #include "edgesort.h" #include "WireExplorer.h" #include "BRepAdaptor_CompCurve2.h" //#include "MeshInterface.h" cutting_tools::cutting_tools(TopoDS_Shape aShape, float pitch) : m_Shape(aShape), m_aMeshAlgo(NULL), m_CAD_Mesh_Grid(NULL), m_pitch(pitch) { m_ordered_cuts.clear(); m_all_offset_cuts_high.clear(); m_all_offset_cuts_low.clear(); m_face_bboxes.clear(); m_cad = false; m_CAD_Mesh.Clear(); m_FaceWireMap.clear(); m_MachiningOrder.clear(); getShapeBB(); fillFaceBBoxes(); classifyShape(); //checkFlatLevel(); initializeMeshStuff(); //BRepBuilderAPI_Sewing aSewer; //aSewer.Add(m_Shape); //aSewer. //Everything should be initialised now } cutting_tools::cutting_tools(TopoDS_Shape aShape) :m_Shape(aShape),m_aMeshAlgo(NULL),m_CAD_Mesh_Grid(NULL),m_cad(false),m_pitch(0.0) { m_ordered_cuts.clear(); m_all_offset_cuts_high.clear(); m_all_offset_cuts_low.clear(); m_face_bboxes.clear(); m_CAD_Mesh.Clear(); m_FaceWireMap.clear(); m_MachiningOrder.clear(); getShapeBB(); fillFaceBBoxes(); classifyShape(); //checkFlatLevel(); initializeMeshStuff(); } cutting_tools::~cutting_tools() { delete m_aMeshAlgo; delete m_CAD_Mesh_Grid; } bool cutting_tools::SetMachiningOrder(const TopoDS_Face &aFace, float x,float y,float z) { std::pair aTempPair; Base::Vector3f aPoint(x,y,z); aTempPair.first = aPoint; aTempPair.second = aFace; m_MachiningOrder.push_back(aTempPair); return true; } bool cutting_tools::fillFaceWireMap() { std::vector >::iterator MOrderIt; for (MOrderIt = m_MachiningOrder.begin();MOrderIt != m_MachiningOrder.end(); ++MOrderIt) { //Here we take the flat areas and put them in a map where we can easily search for the biggest, smallest Wire std::pair >aTempPair; aTempPair.second.clear(); std::pair aTempBBoxPair; aTempPair.first = MOrderIt->second; //Jetzt durch das Face gehen und die Wires rausfiltern TopExp_Explorer Explore_Face; Explore_Face.Init(MOrderIt->second,TopAbs_WIRE); //If there is no Wire -> return if (!Explore_Face.More()) return false; //Jetzt alle Wires in die map schieben for (Explore_Face.ReInit();Explore_Face.More();Explore_Face.Next()) { aTempBBoxPair.first = getWireBBox(TopoDS::Wire(Explore_Face.Current())); aTempBBoxPair.second = TopoDS::Wire(Explore_Face.Current()); aTempPair.second.insert(aTempBBoxPair); } m_FaceWireMap.insert(aTempPair); } return true; } bool cutting_tools::getShapeBB() { //Die Cascade-Bounding Box funktioniert nicht richtig //Es wird dort wohl ne BoundingBox um dasKontrollnetz gelegt //Deshalb wird jetzt kurz das Shape tesseliert und dann die Bounding Box direkt ausgelesen best_fit::Tesselate_Shape(m_Shape,m_CAD_Mesh,float(0.1)); Base::BoundBox3f aBoundBox = m_CAD_Mesh.GetBoundBox(); m_maxlevel = aBoundBox.MaxZ; m_minlevel = aBoundBox.MinZ; // //Hier testen wir noch ein paar OpenMesh Funktionen // typedef OpenMesh::DefaultTraits MyTraits; // typedef OpenMesh::TriMesh_ArrayKernelT MyMesh; //////// Mesh::Interface erbt von MyMesh , so dass das Objekt 'mesh' direkt in den OpenMesh-Funktionen genutzt werden kann // Mesh::Interface mesh(m_CAD_Mesh); ////// proceed with mesh, e.g. refining // MyMesh::EdgeIter e_it,e_end(mesh.edges_end()); // MyMesh::EdgeHandle eh; // MyMesh::Scalar dist; // MyMesh::Point startPoint,midPoint,endPoint; // for ( e_it = mesh.edges_begin() ; e_it != e_end ; ++e_it ) // { // eh = e_it.handle(); // dist = mesh.calc_edge_length(eh); //get the length of the current edge // if(dist>2.6) //Split the Edge now // { // // //Get the Start and EndPoints of the Edge // // } // } ////// throw away all tagged edges ////mesh.garbage_collection(); //Function from OpenMesh //mesh.release(m_CAD_Mesh); //Function from MeshInterface to convert the Input Kernel back /* Hier ist die alte OCC BoundingBox Funktion Bnd_Box currentBBox; Standard_Real XMin, YMin, ZMin, XMax, YMax, ZMax; BRepBndLib::Add(m_shape, currentBBox ); currentBBox.SetGap(1000.0); currentBBox.Get(XMin, YMin, ZMin, XMax, YMax, ZMax); */ return true; } //bool cutting_tools::fillFaceMeshMap() //{ // if(m_CAD_Mesh.size()> bool cutting_tools::fillFaceBBoxes() { TopoDS_Face atopo_surface; TopExp_Explorer Explorer; MeshCore::MeshKernel aFaceMesh; Base::BoundBox3f aBoundBox; Explorer.Init(m_Shape,TopAbs_FACE); for (;Explorer.More();Explorer.Next()) { aFaceMesh.Clear(); aBoundBox.Flush(); atopo_surface = TopoDS::Face (Explorer.Current()); best_fit::Tesselate_Face(atopo_surface,aFaceMesh,float(0.1)); aBoundBox = aFaceMesh.GetBoundBox(); aBoundBox.Enlarge(2.0); std::pair tempPair; tempPair.first = atopo_surface; tempPair.second = aBoundBox; m_face_bboxes.push_back(tempPair); } return true; } //Hier ist die alte Version um die Bounding Box zu bestimmen // aAdaptor_Surface.Initialize(atopo_surface); // Standard_Real FirstUParameter, LastUParameter,FirstVParameter,LastVParameter; // gp_Pnt aSurfacePoint; // FirstUParameter = aAdaptor_Surface.FirstUParameter(); // LastUParameter = aAdaptor_Surface.LastUParameter(); // FirstVParameter = aAdaptor_Surface.FirstVParameter(); // LastVParameter = aAdaptor_Surface.LastVParameter(); //float urange = LastUParameter - FirstUParameter; //float vrange = LastVParameter - FirstVParameter; ////Jetzt ein 10x10 Grid pro Face machen und so die BBox bestimmen ////Zunächst mal die BoundingBox auf Null setzen //Bnd_Box currentBBox; // //for(int i=0;i<10;++i) //{ // for(int j=0;j<10;++j) // { // aAdaptor_Surface.D0(FirstUParameter+((urange/10)*i),FirstVParameter+((vrange/10)*j),aSurfacePoint); // currentBBox.Update(aSurfacePoint.X(),aSurfacePoint.Y(),aSurfacePoint.Z()); // } //} ////Jetzt noch nen Rand drumherum bauen //currentBBox.SetGap(0.5); ////Jetzt die aktuelle BoundingBox mit dem aktuellen Face in einen vector pushen //std::pair tempPair; //tempPair.first = atopo_surface; //tempPair.second = currentBBox; //m_face_bboxes.push_back(tempPair); ////aVertex = BRepBuilderAPI_MakeVertex(aSurfacePoint); ////BRepBndLib::Add(aVertex, currentBBox ); //currentBBox.SetVoid(); bool cutting_tools::checkPointinFaceBB(const gp_Pnt &aPnt,const Base::BoundBox3f &aBndBox) { if ((aPnt.X()>aBndBox.MinX) && (aPnt.X()aBndBox.MinY) && (aPnt.Y()aBndBox.MinZ) && (aPnt.Z() tempPair; tempPair.first = z_level_corrected; tempPair.second = aCutShape; m_ordered_cuts.push_back(tempPair); } return true; } //Wenn wir mehrere Faces haben oder eine CAD-Geometrie vorhanden ist else { //Über die MachiningOrder wird jetzt die Cutting-Folge festgelegt std::vector >::iterator MOrderIt; if (m_MachiningOrder.size()<2) return false; //Did not select at least two Levels //Now take two levels and perform the Cutting Stuff for (MOrderIt = m_MachiningOrder.begin();MOrderIt != m_MachiningOrder.end(); ++MOrderIt) { float temp_max = MOrderIt->first.z; //the check if MOrderIt+1 != end is performend at the bottom of the function float temp_min = (MOrderIt+1)->first.z; //set the direction flags if (temp_max> temp_min) m_direction = true; else m_direction = false; //Now we cut from temp_max to temp_min, without the flat areas at the top and bottom int cutnumber = (int)fabs((temp_max-temp_min)/m_UserSettings.level_distance); //m_pitch correction to really reach temp_min m_UserSettings.level_distance = fabs(temp_max-temp_min)/cutnumber; float z_level,z_level_corrected; TopoDS_Shape aCutShape; //Now lets cut and push the highest and lowest level also into the results vector std::pair tempPair; //Highest Level push_back (only the proper Wire) tempPair.first = MOrderIt->first.z; //get the Wire with the smallest Bounding Box if we go from top to bottom for the highest area tempPair.second = m_FaceWireMap.find(MOrderIt->second)->second.begin()->second; m_ordered_cuts.push_back(tempPair); for (int i=1;ifirst.z; tempPair.second = m_FaceWireMap.find((MOrderIt+1)->second)->second.rbegin()->second; m_ordered_cuts.push_back(tempPair); break; //No more combination to find } else { tempPair.first = (MOrderIt+1)->first.z; tempPair.second = m_FaceWireMap.find((MOrderIt+1)->second)->second.rbegin()->second; m_ordered_cuts.push_back(tempPair); } } } return true; } //} // std::map >::iterator zl_wire_it; // //Wir holen uns jetzt den nächsten Z-Level raus. Wir müssen was kleineres // //wie den höchsten Wert nehmen sonst gibt er immer den höchsten Wert aus // zl_wire_it = m_zl_wire_combination.upper_bound(temp_max-0.1); // if (zl_wire_it->first == temp_max) // { // cout << "Tja, es gibt wohl nur eine flache Area"; // temp_min = m_minlevel; // } // //Wenn es mehrere flache Bereiche gibt muss ich nochmal weitermachen // else // { // temp_min = zl_wire_it->first; // cout << "Mehrere Areas erkannt"; // } // //Jetzt schnippeln von temp_max bis temp_min // int cutnumber = (int)fabs((temp_max-temp_min)/m_pitch); // //m_pitch leicht korrigieren um wirklich auf die letzte Ebene zu kommen // m_pitch = fabs(temp_max-temp_min)/cutnumber; // //Jetzt die Schnitte machen. Die höchste Ebene fällt weg, da hier noch kein Blech gedrückt wird // float z_level,z_level_corrected; // TopoDS_Shape aCutShape; // //Jetzt schneiden (die oberste Ebene auslassen) // for (int i=1;i<=20;++i) // { // z_level = temp_max-(i*m_pitch); // z_level_corrected = z_level; // //cut_Mesh(z_level,m_minlevel,result,z_level_corrected); // //Jetzt die resultierenden Points in den vector schieben // //std::pair > > tempPair; // //tempPair.first = z_level_corrected; // //tempPair.second = result; // //m_ordered_cuts.push_back(tempPair); // cut(z_level,temp_min, aCutShape,z_level_corrected); // //Jetzt die gefüllte Wire in den vector schieben // std::pair tempPair; // tempPair.first = z_level_corrected; // tempPair.second = aCutShape; // m_ordered_cuts.push_back(tempPair); // } // return true; // } // return false; //} //bool cutting_tools::checkFlatLevel() //{ // //Falls keine CAD-Geometrie da ist, gleich wieder rausspringen // // if (m_cad==false) return false; // // TopoDS_Face atopo_surface; // BRepAdaptor_Surface aAdaptor_Surface; // TopExp_Explorer Explorer; // // // for (Explorer.Init(m_Shape,TopAbs_FACE);Explorer.More();Explorer.Next()) // { // atopo_surface = TopoDS::Face (Explorer.Current()); // aAdaptor_Surface.Initialize(atopo_surface); // Standard_Real FirstUParameter, LastUParameter,FirstVParameter,LastVParameter; // gp_Pnt first,second,third; // gp_Vec first_u,first_v,second_u,second_v,third_u,third_v, Norm_first,Norm_second,Norm_third,Norm_average; // double u_middle,v_middle; // /* // Generate three random point on the surface to get the surface normal and decide wether its a // planar face or not // */ // FirstUParameter = aAdaptor_Surface.FirstUParameter(); // LastUParameter = aAdaptor_Surface.LastUParameter(); // FirstVParameter = aAdaptor_Surface.FirstVParameter(); // LastVParameter = aAdaptor_Surface.LastVParameter(); // u_middle = sqrt((FirstUParameter - LastUParameter)*(FirstUParameter - LastUParameter))/2; // v_middle = sqrt((FirstVParameter - LastVParameter)*(FirstVParameter - LastVParameter))/2; // aAdaptor_Surface.D1(sqrt((FirstUParameter-u_middle)*(FirstUParameter-u_middle))/2,sqrt((FirstVParameter-v_middle)*(FirstVParameter-v_middle))/2,first,first_u,first_v); // aAdaptor_Surface.D1(sqrt((u_middle)*(u_middle))/2,sqrt((v_middle)*(v_middle))/2,second,second_u,second_v); // aAdaptor_Surface.D1(sqrt((FirstUParameter+u_middle)*(FirstUParameter+u_middle))/2,sqrt((FirstVParameter+v_middle)*(FirstVParameter+v_middle))/2,third,third_u,third_v); // //Get Surface normal as Cross-Product between two Vectors // Norm_first = first_u.Crossed(first_v); // Norm_first.Normalize(); // Norm_second = second_u.Crossed(second_v); // Norm_second.Normalize(); // Norm_third = third_u.Crossed(third_v); // Norm_third.Normalize(); // //Evaluate average normal vector // Norm_average.SetX((Norm_first.X()+Norm_second.X()+Norm_third.X())/3); // Norm_average.SetY((Norm_first.Y()+Norm_second.Y()+Norm_third.Y())/3); // Norm_average.SetZ((Norm_first.Z()+Norm_second.Z()+Norm_third.Z())/3); // Norm_average.Normalize(); // gp_Vec z_normal(0,0,1); // gp_Vec z_normal_opposite(0,0,-1); // if (Norm_average.IsEqual(z_normal,0.01,0.01) || Norm_average.IsEqual(z_normal_opposite,0.01,0.01)) // { // cout << "Einen flachen Bereich gefunden"; // std::pair >aTempPair; // aTempPair.second.clear(); // std::pair aTempBBoxPair; // // //Z-Wert vom flachen Bereich in ein temporäres pair pushen // aTempPair.first = ((first.Z()+second.Z()+third.Z())/3); // //Jetzt durch das Face gehen und die Wires rausfiltern // TopExp_Explorer Explore_Face; // Explore_Face.Init(atopo_surface,TopAbs_WIRE); // //If there is no Wire -> return // if (!Explore_Face.More()) return false; // // //Jetzt alle Wires in die map schieben // for (Explore_Face.ReInit();Explore_Face.More();Explore_Face.Next()) // { // aTempBBoxPair.first = getWireBBox(TopoDS::Wire(Explore_Face.Current())); // aTempBBoxPair.second = TopoDS::Wire(Explore_Face.Current()); // aTempPair.second.insert(aTempBBoxPair); // //aTempPair.first ist ja noch auf dem gleichen Z-Wert wie vorher, deswegen muss da nichts abgepasst werden // } // m_zl_wire_combination.insert(aTempPair); // } // } // // return true; //} //bool cutting_tools::projectWireToSurface(const TopoDS_Wire &aWire,const TopoDS_Shape &aShape,std::vector &aContainer); //{ // //make your wire looks like a curve to other algorithm and generate Points to offset the curve // aContainer.clear(); // BRepAdaptor_CompCurve2 wireAdaptor(aWire); // GCPnts_QuasiUniformDeflection aProp(wireAdaptor,0.01); // int numberofpoints = aProp.NbPoints(); // Standard_Real Umin,Vmin,lowestdistance; // TopoDS_Face atopo_surface,atopo_surface_shortest; // Handle_Geom_Surface geom_surface; // // //Now project the points to the surface and get surface normal. // for (int i=1;i<=numberofpoints;++i) // { // lowestdistance=200; // //Aktuellen Punkt holen // gp_Pnt currentPoint = aProp.Value(i); // projectPointContainer aTempContainer; // //checken auf welches Face wir projezieren könnnen // for(m_face_bb_it = m_face_bboxes.begin();m_face_bb_it!=m_face_bboxes.end();++m_face_bb_it) // { // //Wenn der aktuelle Punkt in der BBox enthalten ist, dann machen wir mit der Projection weiter // if(checkPointinFaceBB(aProp.Value(i),m_face_bb_it->second)) // { // atopo_surface = m_face_bb_it->first; // geom_surface = BRep_Tool::Surface(atopo_surface); // GeomAPI_ProjectPointOnSurf aPPS(currentPoint,geom_surface,0.001); // //Wenn nichts projeziert werden kann, gehts gleich weiter zum nächsten Face bzw. der nächsten BBox // if (aPPS.NbPoints() == 0) continue; // //Jetzt muss das aktuelle Face gespeichert werden, da es eventuell das face ist, welches am nächsten ist // double length = aPPS.LowerDistance(); // if(lowestdistance>length) // { // lowestdistance=length; // atopo_surface_shortest = atopo_surface; // aPPS.LowerDistanceParameters (Umin,Vmin); // } // } // } // gp_Vec Uvec,Vvec,normalVec; // geom_surface = BRep_Tool::Surface(atopo_surface_shortest); // //Das Face welches am nächsten ist in der temp-struct speichern // aTempContainer.face = atopo_surface_shortest; // geom_surface->D1(Umin,Vmin,aTempContainer.point,Uvec,Vvec); // //Jetzt den Normalenvector auf die Fläche ausrechnen // normalVec = Uvec; // normalVec.Cross(Vvec); // normalVec.Normalize(); // //Jetzt ist die Normale berechnet und auch normalisiert // //Jetzt noch checken ob die Normale auch wirklich wie alle anderen auf die gleiche Seite zeigt. // //dazu nur checken ob der Z-Wert der Normale größer Null ist (dann im 1.und 2. Quadranten) // if(normalVec.Z()<0) normalVec.Multiply(-1.0); // //Mal kurz den Winkel zur Grund-Ebene ausrechnen // aTempContainer.normalvector = normalVec; // aContainer.push_back(aTempContainer); // // } // return true; //} TopoDS_Wire cutting_tools::ordercutShape(const TopoDS_Shape &aShape) { //Bisher funktioniert das Ganze nur für Schnitte welche nur einmal rundherum laufen und noch nicht für Inseln TopExp_Explorer exploreShape; exploreShape.Init(aShape,TopAbs_EDGE); int k=0; for (; exploreShape.More(); exploreShape.Next()) //erstmal schauen wieviele Edges wir haben { k++; } //Jetzt die Edges alle in eine Wire packen (mit Add) und schauen ob ein Fehler kommt. //Wenn ja, dann die nächste Edge. Solange bis alle Edges drin sind. if (k<1) { exploreShape.ReInit(); BRepBuilderAPI_MakeWire mkWire(TopoDS::Edge(exploreShape.Current())); return mkWire.Wire(); } else //Nur wenn mehr als eine Edge vorhanden ist { BRepBuilderAPI_MakeWire mkWire; //WireContainer aufbauen std::vector listofedge_tmp,listofedge; std::vector::iterator it_edge; edge_container a_edge_container; //Definiert in der stuff.h listofedge.clear(); listofedge_tmp.clear(); exploreShape.ReInit(); //Edge-Liste füllen for (; exploreShape.More(); exploreShape.Next()) { a_edge_container.edge = TopoDS::Edge(exploreShape.Current()); TopoDS_Vertex V1,V2; TopExp::Vertices(a_edge_container.edge,V1,V2); a_edge_container.firstPoint = BRep_Tool::Pnt(V1);; a_edge_container.lastPoint = BRep_Tool::Pnt(V2); listofedge.push_back(a_edge_container); } gp_Pnt lastpointoflastedge,firstpointoflastedge; while (listofedge.empty() == false ) { listofedge_tmp.clear(); for (it_edge = listofedge.begin();it_edge!=listofedge.end();++it_edge) { mkWire.Add((*it_edge).edge); if (mkWire.IsDone()) { lastpointoflastedge = (*it_edge).lastPoint; firstpointoflastedge = (*it_edge).firstPoint; } else { //Abstände ausrechnen double abstand1=sqrt((*it_edge).firstPoint.SquareDistance(lastpointoflastedge)); double abstand2=sqrt((*it_edge).lastPoint.SquareDistance(lastpointoflastedge)); double abstand3=sqrt((*it_edge).firstPoint.SquareDistance(firstpointoflastedge)); double abstand4=sqrt((*it_edge).lastPoint.SquareDistance(firstpointoflastedge)); if (abstand1<0.5) { //Neue Edge erzeugen welche vom letzten Endpunkt zum aktuellen Startpunkt geht BRepBuilderAPI_MakeEdge newedge(lastpointoflastedge,(*it_edge).firstPoint); mkWire.Add(newedge); mkWire.Add((*it_edge).edge); lastpointoflastedge = (*it_edge).lastPoint; firstpointoflastedge = (*it_edge).firstPoint; } else if (abstand2<0.5) { //Neue Edge erzeugen welche vom letzten Endpunkt zum aktuellen Startpunkt geht BRepBuilderAPI_MakeEdge newedge(lastpointoflastedge,(*it_edge).lastPoint); mkWire.Add(newedge); mkWire.Add((*it_edge).edge); lastpointoflastedge = (*it_edge).lastPoint; firstpointoflastedge = (*it_edge).firstPoint; } else if (abstand3<0.5) { //Neue Edge erzeugen welche vom letzten Endpunkt zum aktuellen Startpunkt geht BRepBuilderAPI_MakeEdge newedge(firstpointoflastedge,(*it_edge).firstPoint); mkWire.Add(newedge); mkWire.Add((*it_edge).edge); lastpointoflastedge = (*it_edge).lastPoint; firstpointoflastedge = (*it_edge).firstPoint; } else if (abstand4<0.5) { //Neue Edge erzeugen welche vom letzten Endpunkt zum aktuellen Startpunkt geht BRepBuilderAPI_MakeEdge newedge(firstpointoflastedge,(*it_edge).lastPoint); mkWire.Add(newedge); mkWire.Add((*it_edge).edge); lastpointoflastedge = (*it_edge).lastPoint; firstpointoflastedge = (*it_edge).firstPoint; } else { listofedge_tmp.push_back(*it_edge); } } } listofedge = listofedge_tmp; } return mkWire.Wire(); } } //bool cutting_tools::OffsetWires_Standard(float radius) //Version wo nur in X,Y-Ebene verschoben wird //{ // Base::Builder3D build; // std::ofstream outfile; // outfile.open("c:/atest.out"); // // // //Die ordered_cuts sind ein Vector wo für jede Ebene ein Pair existiert // for(m_ordered_cuts_it = m_ordered_cuts.begin();m_ordered_cuts_it!=m_ordered_cuts.end();++m_ordered_cuts_it) // { // float current_z_level = m_ordered_cuts_it->first; // std::vector finalPoints; // finalPoints.clear(); // Standard_Real Umin,Vmin,lowestdistance; // TopoDS_Face atopo_surface,atopo_surface_shortest; // Handle_Geom_Surface geom_surface; // int i=0; // for (;avector_it!=aPolyline_it->end();++avector_it) // { // i++; // lowestdistance=200; // //Aktuellen Punkt holen // gp_Pnt currentPoint(avector_it->x,avector_it->y,avector_it->z); // gp_Pnt nearest_Point; // //checken auf welches Face wir projezieren könnnen // for(m_face_bb_it = m_face_bboxes.begin();m_face_bb_it!=m_face_bboxes.end();++m_face_bb_it) // { // //Wenn der aktuelle Punkt in der BBox enthalten ist, dann machen wir mit der Projection weiter // if(checkPointinFaceBB(currentPoint,m_face_bb_it->second)) // { // atopo_surface = m_face_bb_it->first; // geom_surface = BRep_Tool::Surface(atopo_surface); // GeomAPI_ProjectPointOnSurf aPPS(currentPoint,geom_surface,0.001); // //Wenn nichts projeziert werden kann, gehts gleich weiter zum nächsten Face bzw. der nächsten BBox // if (aPPS.NbPoints() == 0) continue; // //Jetzt muss das aktuelle Face gespeichert werden, da es eventuell das face ist, welches am nächsten ist // double length = aPPS.LowerDistance(); // if(lowestdistance>length) // { // lowestdistance=length; // atopo_surface_shortest = atopo_surface; // //aPPS.LowerDistanceParameters (Umin,Vmin); // nearest_Point = aPPS.NearestPoint(); // } // } // } // //Für eine saubere Projection auf der aktuellen Ebene wird jetzt der Richtungsvector // //aus dem projezierten Punkt und dem Ursprungspunkt gebildet // //und dieser dann hergenommen um damit nochmal in dessen Richtung zu projezieren // gp_Vec aVec(currentPoint,nearest_Point); // aVec.Normalize(); // aVec.SetZ(0.0); // gp_Dir aDir(aVec); // gp_Lin aLine(currentPoint,aDir); // IntCurvesFace_ShapeIntersector aFaceIntSect; // aFaceIntSect.Load(m_Shape, 0.001); // aFaceIntSect.PerformNearest(aLine,-RealLast(), +RealLast()); // //Jetzt holen wir uns auf der Fläche den U und V Wert um dann D1 und D2 bestimmen zu können // gp_Pnt projectedPoint,OffsetPoint; // gp_Pnt testpoint,testpoint2; // float abstand,abstand_old; // int number = aFaceIntSect.NbPnt(); // abstand_old = 100; // for(int k=0;kD1(Umin,Vmin,projectedPoint,Uvec,Vvec); // normalVec = Uvec; // normalVec.Cross(Vvec); // normalVec.Normalize(); // //Jetzt ist die Surface-Normale berechnet und auch normalisiert // //Jetzt noch checken ob die Normale auch wirklich wie alle anderen auf die gleiche Seite zeigt. // //dazu nur checken ob der Z-Wert der Normale größer Null ist (dann im 1.und 2. Quadranten) // if(normalVec.Z()<0) normalVec.Multiply(-1.0); // //Jetzt die Normale auf die Radiuslänge verlängern // normalVec.Multiply(radius); // //Jetzt die Z-Komponente auf 0 setzen // normalVec.SetZ(0.0); // //float abstand = currentPoint.Distance(projectedPoint); // //if(abstand>0.2) // //{cout<<"error"< finalPointscorrected; // finalPointscorrected.clear(); // checkPointDistance(finalPoints,finalPointscorrected); // Handle(TColgp_HArray1OfPnt) finalOffsetPoints = new TColgp_HArray1OfPnt(1, finalPointscorrected.size()); // for(int t=0;tSetValue(t+1,finalPointscorrected[t]); // } // GeomAPI_Interpolate aNoPeriodInterpolate(finalOffsetPoints, Standard_False, Precision::Confusion()); // aNoPeriodInterpolate.Perform(); // Handle_Geom_BSplineCurve aCurve(aNoPeriodInterpolate.Curve()); // //check results // if (!aNoPeriodInterpolate.IsDone()) return false; // m_all_offset_cuts_high.push_back(aCurve); // } // // // // // // build.saveToFile("c:/output.iv"); // outfile.close(); // // // // // //return true; // //} //bool cutting_tools::checkPointDistance(std::vector &finalPoints,std::vector &output) //{ // std::vector::iterator aPntIt,atempit; // output.clear(); // double square_precision = Precision::Confusion()*Precision::Confusion(); // int i; // for(aPntIt=finalPoints.begin();aPntIt!=finalPoints.end();++aPntIt) // { // atempit=aPntIt; // output.push_back(*aPntIt); // i=1; // while(((*(aPntIt+i)).SquareDistance(*aPntIt))< square_precision && (aPntIt+i)!=finalPoints.end()) // { // i++; // atempit++; // } // aPntIt = atempit; // // // // } // // return true; //} //bool cutting_tools::checkPointIntersection(std::vector &finalPoints) //{ // //Hier wird gecheckt ob die Punkte wirklich alle in der richtigen Reihenfolge vorliegen // std::vector::iterator aPntIt; // double distance,distance_old; // projectPointContainer nearestPointStruct; // int k; // for(unsigned int j=0;j=finalPoints.size()) break; // // distance = (finalPoints[j+i].point).SquareDistance(finalPoints[j].point); // if(distanceLength()); //for (int j=1;j<=TangentFlags->Length();++j) // TangentFlags->SetValue(j,true); GeomAPI_Interpolate aBSplineInterpolation(InterpolationPoints, Standard_False, Precision::Confusion()); //aBSplineInterpolation.Load(Tangents,TangentFlags); aBSplineInterpolation.Perform(); Handle_Geom_BSplineCurve aBSplineCurve(aBSplineInterpolation.Curve()); //check results //if (!aBSplineInterpolation.IsDone()) cout << "error" << endl; return aBSplineCurve; } bool cutting_tools::CheckEdgeTangency(const TopoDS_Edge& edge1, const TopoDS_Edge& edge2) { //Get the vertex which is equal to both edges TopoDS_Vertex CommonVertex; TopExp::CommonVertex(edge1,edge2,CommonVertex); if (CommonVertex.IsNull()) { cout << "Not possible to calculate Tangency" << endl; return false; } gp_Pnt CommonPoint = BRep_Tool::Pnt(CommonVertex); BRepAdaptor_Curve aCurve1(edge1); BRepAdaptor_Curve aCurve2(edge2); gp_Vec Tangent1,Tangent2; gp_Pnt P; if (aCurve1.Value(aCurve1.FirstParameter()).IsEqual(CommonPoint,0.1)) aCurve1.D1(aCurve1.FirstParameter(),P,Tangent1); else if (aCurve1.Value(aCurve1.LastParameter()).IsEqual(CommonPoint,0.1)) aCurve1.D1(aCurve1.LastParameter(),P,Tangent1); if (aCurve2.Value(aCurve2.FirstParameter()).IsEqual(CommonPoint,0.1)) aCurve2.D1(aCurve1.FirstParameter(),P,Tangent2); else if (aCurve2.Value(aCurve2.LastParameter()).IsEqual(CommonPoint,0.1)) aCurve2.D1(aCurve1.LastParameter(),P,Tangent2); //Now we calculate the angle between the two Tangents and if the angle is below 10° then we say its continuous double angle = Tangent1.Angle(Tangent2); //Angle must be between +/-5° if (angle<(5.0/180.0*D_PI) || angle>(175.0/180.0*D_PI)) return true; else return false; } bool cutting_tools::CheckforLastPoint(const gp_Pnt& lastPoint, int &start_index,int &start_array,const std::vector > >& MasterPointsStorage) { float dist,distold = FLT_MAX; for (unsigned int t=0;t >& SlavePointsStorage) { float dist,distold = FLT_MAX; for (unsigned int t=0;t > >& MasterPointsStorage, const std::vector >& SlavePointsStorage ) { float dist,distold = FLT_MAX; for (unsigned int t=0;t >::iterator current_flat_level; gp_Pnt lastPoint(0.0,0.0,0.0); //Initialize the first Point to the Origin current_flat_level = m_ordered_cuts.begin(); bool slave_is_wire= false; //Necessary if the slave is a wire while the master is not... //Nicht beim höchsten Anfangen, da wir den nicht mit dem Master fahren wollen for (m_ordered_cuts_it = m_ordered_cuts.begin()+1;m_ordered_cuts_it!=m_ordered_cuts.end();++m_ordered_cuts_it) { std::vector > MasterPointContainer; std::vector > > MasterPointsStorage; std::vector SlavePointContainer; std::vector > SlavePointsStorage; std::vector >::iterator anIterator1; std::vector > >::iterator anIterator2; MasterPointsStorage.clear(); SlavePointsStorage.clear(); MasterPointContainer.clear(); SlavePointContainer.clear(); //Now we have to select which strategy to choose //if the current levels is bigger,the same, or less then the previous one if (m_ordered_cuts_it->first<(m_ordered_cuts_it-1)->first) { //Master is calculated as Usual, Slave follows the Master //Check if current Level has got a Wire if (m_ordered_cuts_it->second.ShapeType() == TopAbs_WIRE) { WireExplorer aWireExplorer(TopoDS::Wire(m_ordered_cuts_it->second)); for (aWireExplorer.Init();aWireExplorer.More();aWireExplorer.Next()) { BRepAdaptor_Curve curveAdaptor(aWireExplorer.Current()); GCPnts_QuasiUniformAbscissa aProp(curveAdaptor,100); for (int i=1;i<=aProp.NbPoints();++i) { std::pair aTempPair; //Check the direction if (aWireExplorer.Current().Orientation() != TopAbs_REVERSED) curveAdaptor.D0(aProp.Parameter(i),aTempPair.first); else curveAdaptor.D0(aProp.Parameter(aProp.NbPoints()-i+1),aTempPair.first); //aTempPair.first.SetZ(aTempPair.first.Z() + m_UserSettings.master_radius); aTempPair.first.SetZ(aTempPair.first.Z() ); aTempPair.second = 0.0; //Initialize of Angle //checken ob der neue Punkt zu nahe am alten ist. Wenn ja, dann kein push_back if (MasterPointContainer.size()>0 && (MasterPointContainer.rbegin()->first.SquareDistance(aTempPair.first)>(Precision::Confusion()*Precision::Confusion()))) { MasterPointContainer.push_back(aTempPair); anoutput1 << aTempPair.first.X() <<","<< aTempPair.first.Y() <<","<< aTempPair.first.Z()<size();i++) { //We skip the Endpoint as it may be the same point as the start point if (i+1 == MasterPointsStorage.begin()->size()) { i=-1; first = false; continue; } MasterPointContainer.push_back(MasterPointsStorage[0][i]); SlavePointContainer.push_back(SlavePointsStorage[0][i]); if (!first && i == start_index) break; } //Now lets interpolate the Point Cloud Handle(TColgp_HArray1OfPnt) InterpolationPointsMaster = new TColgp_HArray1OfPnt(1, MasterPointContainer.size()); Handle(TColgp_HArray1OfPnt) InterpolationPointsSlave = new TColgp_HArray1OfPnt(1, SlavePointContainer.size()); for (unsigned int t=0;tSetValue(t+1,MasterPointContainer[t].first); InterpolationPointsSlave->SetValue(t+1,SlavePointContainer[t]); } m_all_offset_cuts_high.push_back(InterpolateOrderedPoints(InterpolationPointsMaster,true)); m_all_offset_cuts_low.push_back(InterpolateOrderedPoints(InterpolationPointsSlave,true)); //Store the last point lastPoint = MasterPointContainer.rbegin()->first; } else { anIterator1 = SlavePointsStorage.begin(); anIterator2 = MasterPointsStorage.begin(); MasterPointContainer.clear(); SlavePointContainer.clear(); for (int i=0;i<=start_index;i++) { MasterPointContainer.push_back(MasterPointsStorage[start_array][i]); SlavePointContainer.push_back(SlavePointsStorage[start_array][i]); } MasterPointsStorage.insert((anIterator2+start_array+1),MasterPointContainer); SlavePointsStorage.insert((anIterator1+start_array+1),SlavePointContainer); MasterPointContainer.clear(); SlavePointContainer.clear(); //Reinitialize the Iterators anIterator1 = SlavePointsStorage.begin(); anIterator2 = MasterPointsStorage.begin(); for (unsigned int i=start_index;iSetValue(t+1,MasterPointsStorage[j][t].first); InterpolationPointsSlave->SetValue(t+1,SlavePointsStorage[j][t]); } m_all_offset_cuts_high.push_back(InterpolateOrderedPoints(InterpolationPointsMaster,true)); m_all_offset_cuts_low.push_back(InterpolateOrderedPoints(InterpolationPointsSlave,true)); if (j+1==MasterPointsStorage.size()) { j=-1; continue; } if (j+1==start_array+1) break; } lastPoint = MasterPointsStorage[start_array].rbegin()->first; } } else //If the current Curve is no Wire (Mode <) { Edgesort aCutShapeSorter(m_ordered_cuts_it->second); for (aCutShapeSorter.Init();aCutShapeSorter.More();aCutShapeSorter.Next()) { //Get the PCurve and the GeomSurface Handle_Geom2d_Curve a2DCurve; Handle_Geom_Surface aSurface; TopLoc_Location aLoc; TopoDS_Edge anEdge; double first2,last2; bool reversed = false; BRep_Tool::CurveOnSurface(aCutShapeSorter.Current(),a2DCurve,aSurface,aLoc,first2,last2); //Jetzt noch die resultierende Surface und die Curve sauber drehen //(vielleicht wurde ja das TopoDS_Face irgendwie gedreht oder die TopoDS_Edge) if (aCutShapeSorter.Current().Orientation() == TopAbs_REVERSED) reversed = true; BRepAdaptor_Curve aCurveAdaptor(aCutShapeSorter.Current()); GCPnts_QuasiUniformAbscissa aPointGenerator(aCurveAdaptor,200); int PointSize = aPointGenerator.NbPoints(); //Now get the surface normal to the generated points for (int i=1;i<=PointSize;++i) { std::pair PointContactPair; gp_Pnt2d a2dParaPoint; gp_Pnt aSurfacePoint; TopoDS_Face aFace; gp_Vec Uvec,Vvec,normalVec; //If the curve is reversed we also have to reverse the point direction if (reversed) a2DCurve->D0(aPointGenerator.Parameter(PointSize-i+1),a2dParaPoint); else a2DCurve->D0(aPointGenerator.Parameter(i),a2dParaPoint); GeomAdaptor_Surface aGeom_Adaptor(aSurface); int t = aGeom_Adaptor.GetType(); aGeom_Adaptor.D1(a2dParaPoint.X(),a2dParaPoint.Y(),aSurfacePoint,Uvec,Vvec); //Jetzt den Normalenvector auf die Fläche ausrechnen normalVec = Uvec; normalVec.Cross(Vvec); normalVec.Normalize(); //Jetzt ist die Normale berechnet und auch normalisiert //Jetzt noch checken ob die Normale auch wirklich auf die saubere Seite zeigt //dazu nur checken ob der Z-Wert der Normale größer Null ist (dann im 1.und 2. Quadranten) if (normalVec.Z()<0) normalVec.Multiply(-1.0); //Mal kurz den Winkel zur Grund-Ebene ausrechnen gp_Vec planeVec(normalVec.X(),normalVec.Y(),0.0); //Den Winkel PointContactPair.second = normalVec.Angle(planeVec); gp_Vec NormalVecSlave = normalVec; gp_Pnt SlavePoint; //Jetzt die Z-Komponente auf 0 setzen //normalVec.SetZ(0.0); normalVec.Normalize(); //Jetzt die Normale mit folgender Formel multiplizieren für den Master //double multiply = m_UserSettings.master_radius*(1-sin(PointContactPair.second))/cos(PointContactPair.second); double multiply = m_UserSettings.master_radius; normalVec.Multiply(multiply); //und hier für den Slave NormalVecSlave.Normalize(); multiply = m_UserSettings.sheet_thickness+m_UserSettings.slave_radius; NormalVecSlave.Multiply(multiply); //Jetzt die Richtung umdrehen NormalVecSlave.Multiply(-1.0); //Jetzt den OffsetPunkt berechnen PointContactPair.first.SetXYZ(aSurfacePoint.XYZ()); //PointContactPair.first.SetXYZ(aSurfacePoint.XYZ() + normalVec.XYZ()); SlavePoint.SetXYZ(aSurfacePoint.XYZ() + NormalVecSlave.XYZ()); //PointContactPair.first.SetZ(PointContactPair.first.Z() + m_UserSettings.master_radius); //Damit wir keine Punkte bekommen die zu nahe beieinander liegen //Den letzten hinzugefügten Punkt suchen if (MasterPointContainer.size()>0 && (MasterPointContainer.rbegin()->first.SquareDistance(PointContactPair.first)>0.001)) { MasterPointContainer.push_back(PointContactPair); SlavePointContainer.push_back(SlavePoint); anoutput1 << PointContactPair.first.X() <<","<< PointContactPair.first.Y() <<","<< PointContactPair.first.Z()<(current_flat_level->first-m_UserSettings.sheet_thickness)) { slave_is_wire = true; TopoDS_Wire aWire = TopoDS::Wire(current_flat_level->second); BRepAdaptor_CompCurve2 wireAdaptor(aWire); GCPnts_QuasiUniformAbscissa aProp(wireAdaptor,1000); SlavePointContainer.clear(); for (int i=1;i<=aProp.NbPoints();++i) { gp_Pnt SlaveOffsetPoint; wireAdaptor.D0(aProp.Parameter(i),SlaveOffsetPoint); SlaveOffsetPoint.SetZ(SlaveOffsetPoint.Z() - m_UserSettings.slave_radius - m_UserSettings.sheet_thickness); //checken ob der neue Punkt zu nahe am alten ist. Wenn ja, dann kein push_back if (SlavePointContainer.size()>0 && (SlavePointContainer.rbegin()->SquareDistance(SlaveOffsetPoint)>(0.001))) { SlavePointContainer.push_back(SlaveOffsetPoint); anoutput2 << SlaveOffsetPoint.X() <<","<< SlaveOffsetPoint.Y() <<","<< SlaveOffsetPoint.Z()<size();i++) { //We skip the Endpoint as it may be the same point as the start point if (i+1 == MasterPointsStorage.begin()->size()) { first = false; i=-1; continue; } MasterPointContainer.push_back(MasterPointsStorage[0][i]); SlavePointContainer.push_back(SlavePointsStorage[0][i]); if (!first && i==start_index_master) break; } } else //if slave is a wire { //Reset the flag slave_is_wire = false; //Now check the point-cloud with the shortest distance to "lastPoint" //As the Master and the slave have different number of points we have to do it two times now //First we have to divide the first PointCloud as it is for sure that we start //Somewhere in the middle of it. We will then insert the points at the current start MasterPointContainer.clear(); SlavePointContainer.clear(); bool first = true; for (unsigned int i=start_index_master;isize();i++) { //We skip the Endpoint as it may be the same point as the start point if (i+1 == MasterPointsStorage.begin()->size()) { first = false; i=-1; continue; } MasterPointContainer.push_back(MasterPointsStorage[0][i]); if (!first && i== start_index_master) break; } first = true; for (unsigned int i=start_index_slave;isize();i++) { //We skip the Endpoint as it may be the same point as the start point if (i+1 == SlavePointsStorage.begin()->size()) { first = false; i=-1; continue; } SlavePointContainer.push_back(SlavePointsStorage[0][i]); if (!first && i== start_index_slave) break; } } //Now lets interpolate the Point Cloud Handle(TColgp_HArray1OfPnt) InterpolationPointsMaster = new TColgp_HArray1OfPnt(1, MasterPointContainer.size()); Handle(TColgp_HArray1OfPnt) InterpolationPointsSlave = new TColgp_HArray1OfPnt(1, SlavePointContainer.size()); for (unsigned int t=0;tSetValue(t+1,MasterPointContainer[t].first); } for (unsigned int t=0;tSetValue(t+1,SlavePointContainer[t]); } /*CheckPoints(InterpolationPointsMaster);*/ /*CheckPoints(InterpolationPointsSlave);*/ m_all_offset_cuts_high.push_back(InterpolateOrderedPoints(InterpolationPointsMaster,true)); m_all_offset_cuts_low.push_back(InterpolateOrderedPoints(InterpolationPointsSlave,true)); //Store the last point lastPoint = MasterPointContainer.rbegin()->first; //SlaveTool Path finished }//Current Curve < last curve is finished here } if (fabs(m_ordered_cuts_it->first-(m_ordered_cuts_it-1)->first)<=0.01) { //we only set the new flat level wire here //no Toolpath is calculated current_flat_level = m_ordered_cuts_it; }//end of current == last if (m_ordered_cuts_it->first>(m_ordered_cuts_it-1)->first) { //The Slave Tool is now the Master Tool and therefore we only have to exchange < case //Check if current Level has got a Wire if (m_ordered_cuts_it->second.ShapeType() == TopAbs_WIRE) { WireExplorer aWireExplorer(TopoDS::Wire(m_ordered_cuts_it->second)); for (aWireExplorer.Init();aWireExplorer.More();aWireExplorer.Next()) { BRepAdaptor_Curve curveAdaptor(aWireExplorer.Current()); GCPnts_QuasiUniformAbscissa aProp(curveAdaptor,100); for (int i=1;i<=aProp.NbPoints();++i) { std::pair aTempPair; //Check the direction if (aWireExplorer.Current().Orientation() != TopAbs_REVERSED) curveAdaptor.D0(aProp.Parameter(i),aTempPair.first); else curveAdaptor.D0(aProp.Parameter(aProp.NbPoints()-i+1),aTempPair.first); aTempPair.first.SetZ(aTempPair.first.Z() -m_UserSettings.slave_radius -m_UserSettings.sheet_thickness); aTempPair.second = 0.0; //Initialize of Angle //checken ob der neue Punkt zu nahe am alten ist. Wenn ja, dann kein push_back if (MasterPointContainer.size()>0 && (MasterPointContainer.rbegin()->first.SquareDistance(aTempPair.first)>(Precision::Confusion()*Precision::Confusion()))) { MasterPointContainer.push_back(aTempPair); anoutput1 << aTempPair.first.X() <<","<< aTempPair.first.Y() <<","<< aTempPair.first.Z()<size();i++) { //We skip the Endpoint as it may be the same point as the start point if (i+1 == MasterPointsStorage.begin()->size()) { i=-1; first = false; continue; } MasterPointContainer.push_back(MasterPointsStorage[0][i]); SlavePointContainer.push_back(SlavePointsStorage[0][i]); if (!first && i == start_index) break; } //Now lets interpolate the Point Cloud Handle(TColgp_HArray1OfPnt) InterpolationPointsMaster = new TColgp_HArray1OfPnt(1, MasterPointContainer.size()); Handle(TColgp_HArray1OfPnt) InterpolationPointsSlave = new TColgp_HArray1OfPnt(1, SlavePointContainer.size()); for (unsigned int t=0;tSetValue(t+1,MasterPointContainer[t].first); InterpolationPointsSlave->SetValue(t+1,SlavePointContainer[t]); } m_all_offset_cuts_low.push_back(InterpolateOrderedPoints(InterpolationPointsMaster,true)); m_all_offset_cuts_high.push_back(InterpolateOrderedPoints(InterpolationPointsSlave,true)); //Store the last point lastPoint = MasterPointContainer.rbegin()->first; } else { anIterator1 = SlavePointsStorage.begin(); anIterator2 = MasterPointsStorage.begin(); MasterPointContainer.clear(); SlavePointContainer.clear(); for (int i=0;i<=start_index;i++) { MasterPointContainer.push_back(MasterPointsStorage[start_array][i]); SlavePointContainer.push_back(SlavePointsStorage[start_array][i]); } MasterPointsStorage.insert((anIterator2+start_array+1),MasterPointContainer); SlavePointsStorage.insert((anIterator1+start_array+1),SlavePointContainer); MasterPointContainer.clear(); SlavePointContainer.clear(); //Reinitialize the Iterators anIterator1 = SlavePointsStorage.begin(); anIterator2 = MasterPointsStorage.begin(); for (unsigned int i=start_index;iSetValue(t+1,MasterPointsStorage[j][t].first); InterpolationPointsSlave->SetValue(t+1,SlavePointsStorage[j][t]); } m_all_offset_cuts_low.push_back(InterpolateOrderedPoints(InterpolationPointsMaster,true)); m_all_offset_cuts_high.push_back(InterpolateOrderedPoints(InterpolationPointsSlave,true)); if (j+1==MasterPointsStorage.size()) { j=-1; continue; } if (j+1==start_array+1) break; } lastPoint = MasterPointsStorage[start_array].rbegin()->first; } } else //If the current Curve is no Wire (Mode >) { Edgesort aCutShapeSorter(m_ordered_cuts_it->second); for (aCutShapeSorter.Init();aCutShapeSorter.More();aCutShapeSorter.Next()) { //Get the PCurve and the GeomSurface Handle_Geom2d_Curve a2DCurve; Handle_Geom_Surface aSurface; TopLoc_Location aLoc; TopoDS_Edge anEdge; double first2,last2; bool reversed = false; BRep_Tool::CurveOnSurface(aCutShapeSorter.Current(),a2DCurve,aSurface,aLoc,first2,last2); //Jetzt noch die resultierende Surface und die Curve sauber drehen //(vielleicht wurde ja das TopoDS_Face irgendwie gedreht oder die TopoDS_Edge) if (aCutShapeSorter.Current().Orientation() == TopAbs_REVERSED) reversed = true; BRepAdaptor_Curve aCurveAdaptor(aCutShapeSorter.Current()); GCPnts_QuasiUniformAbscissa aPointGenerator(aCurveAdaptor,200); int PointSize = aPointGenerator.NbPoints(); //Now get the surface normal to the generated points for (int i=1;i<=PointSize;++i) { std::pair PointContactPair; gp_Pnt2d a2dParaPoint; gp_Pnt aSurfacePoint; TopoDS_Face aFace; gp_Vec Uvec,Vvec,normalVec; //If the curve is reversed we also have to reverse the point direction if (reversed) a2DCurve->D0(aPointGenerator.Parameter(PointSize-i+1),a2dParaPoint); else a2DCurve->D0(aPointGenerator.Parameter(i),a2dParaPoint); GeomAdaptor_Surface aGeom_Adaptor(aSurface); int t = aGeom_Adaptor.GetType(); aGeom_Adaptor.D1(a2dParaPoint.X(),a2dParaPoint.Y(),aSurfacePoint,Uvec,Vvec); //Jetzt den Normalenvector auf die Fläche ausrechnen normalVec = Uvec; normalVec.Cross(Vvec); normalVec.Normalize(); //Jetzt ist die Normale berechnet und auch normalisiert //Jetzt noch checken ob die Normale auch wirklich auf die saubere Seite zeigt //dazu nur checken ob der Z-Wert der Normale größer Null ist (dann im 1.und 2. Quadranten) if (normalVec.Z()<0) normalVec.Multiply(-1.0); //Mal kurz den Winkel zur Grund-Ebene ausrechnen gp_Vec planeVec(normalVec.X(),normalVec.Y(),0.0); //Den Winkel PointContactPair.second = normalVec.Angle(planeVec); gp_Vec NormalVecSlave = normalVec; gp_Pnt SlavePoint; //Jetzt die Z-Komponente auf 0 setzen //normalVec.SetZ(0.0); normalVec.Normalize(); //Jetzt die Normale mit folgender Formel multiplizieren für den Master //double multiply = (m_UserSettings.slave_radius*(1-sin(PointContactPair.second))/cos(PointContactPair.second))+m_UserSettings.sheet_thickness; double multiply = m_UserSettings.slave_radius + m_UserSettings.sheet_thickness; //As the Master is now the Slave we have to multiply it also by -1.0 normalVec.Multiply(-multiply); //und hier für den Slave NormalVecSlave.Normalize(); multiply = m_UserSettings.master_radius; NormalVecSlave.Multiply(multiply); //Jetzt den OffsetPunkt berechnen PointContactPair.first.SetXYZ(aSurfacePoint.XYZ() + normalVec.XYZ()); SlavePoint.SetXYZ(aSurfacePoint.XYZ() + NormalVecSlave.XYZ()); //PointContactPair.first.SetZ(PointContactPair.first.Z() - m_UserSettings.slave_radius); //Damit wir keine Punkte bekommen die zu nahe beieinander liegen //Den letzten hinzugefügten Punkt suchen if (MasterPointContainer.size()>0 && (MasterPointContainer.rbegin()->first.SquareDistance(PointContactPair.first)>(Precision::Confusion()*Precision::Confusion()))) { MasterPointContainer.push_back(PointContactPair); SlavePointContainer.push_back(SlavePoint); anoutput1 << PointContactPair.first.X() <<","<< PointContactPair.first.Y() <<","<< PointContactPair.first.Z()<first)) { slave_is_wire = true; TopoDS_Wire aWire = TopoDS::Wire(current_flat_level->second); BRepAdaptor_CompCurve2 wireAdaptor(aWire); GCPnts_QuasiUniformAbscissa aProp(wireAdaptor,1000); SlavePointContainer.clear(); for (int i=1;i<=aProp.NbPoints();++i) { gp_Pnt SlaveOffsetPoint; wireAdaptor.D0(aProp.Parameter(i),SlaveOffsetPoint); SlaveOffsetPoint.SetZ(SlaveOffsetPoint.Z() + m_UserSettings.master_radius); //checken ob der neue Punkt zu nahe am alten ist. Wenn ja, dann kein push_back if (SlavePointContainer.size()>0 && (SlavePointContainer.rbegin()->SquareDistance(SlaveOffsetPoint)>(0.001))) { SlavePointContainer.push_back(SlaveOffsetPoint); anoutput2 << SlaveOffsetPoint.X() <<","<< SlaveOffsetPoint.Y() <<","<< SlaveOffsetPoint.Z()<size();i++) { if (i+1 == MasterPointsStorage.begin()->size()) { i=-1; first = false; continue; } MasterPointContainer.push_back(MasterPointsStorage[0][i]); SlavePointContainer.push_back(SlavePointsStorage[0][i]); if (!first && i == start_index_master) break; } } else //if slave is a wire { //Now check the point-cloud with the shortest distance to "lastPoint" //As the Master and the slave have different number of points we have to do it two times now //First we have to divide the first PointCloud as it is for sure that we start //Somewhere in the middle of it. We will then insert the points at the current start MasterPointContainer.clear(); SlavePointContainer.clear(); bool first = true; for (unsigned int i=start_index_master;isize();i++) { //We skip the Endpoint as it may be the same point as the start point if (i+1 == MasterPointsStorage.begin()->size()) { i=-1; first = false; continue; } MasterPointContainer.push_back(MasterPointsStorage[0][i]); if (!first && i== start_index_master) break; } for (unsigned int i=start_index_slave;isize();i++) { //We skip the Endpoint as it may be the same point as the start point if (i+1 == SlavePointsStorage.begin()->size()) { i=-1; first = false; continue; } SlavePointContainer.push_back(SlavePointsStorage[0][i]); if (!first && i == start_index_slave) break; } } //Now lets interpolate the Point Cloud Handle(TColgp_HArray1OfPnt) InterpolationPointsMaster = new TColgp_HArray1OfPnt(1, MasterPointContainer.size()); Handle(TColgp_HArray1OfPnt) InterpolationPointsSlave = new TColgp_HArray1OfPnt(1, SlavePointContainer.size()); for (unsigned int t=0;tSetValue(t+1,MasterPointContainer[t].first); } for (unsigned int t=0;tSetValue(t+1,SlavePointContainer[t]); } /*CheckPoints(InterpolationPointsMaster);*/ /*CheckPoints(InterpolationPointsSlave);*/ m_all_offset_cuts_low.push_back(InterpolateOrderedPoints(InterpolationPointsMaster,true)); m_all_offset_cuts_high.push_back(InterpolateOrderedPoints(InterpolationPointsSlave,true)); //Store the last point lastPoint = MasterPointContainer.rbegin()->first; }//Current Curve > last curve is finished here } } return true; } bool cutting_tools::CheckPoints(Handle(TColgp_HArray1OfPnt) PointArray) { Standard_Integer ii ; Standard_Real tolerance_squared = Precision::Confusion() * Precision::Confusion(), distance_squared ; Standard_Boolean result = Standard_True ; for (ii = PointArray->Lower() ; result && ii < PointArray->Upper() ; ii++) { distance_squared = PointArray->Value(ii).SquareDistance(PointArray->Value(ii+1)) ; if (distance_squared < tolerance_squared) { return false; } } return true; } Base::BoundBox3f cutting_tools::getWireBBox(TopoDS_Wire aWire) { //Fill Bounding Boxes with Wires //Therefore we have to evaluate some points on our wire and feed the BBox Algorithm Base::BoundBox3f currentBox; BRepAdaptor_CompCurve2 wireAdaptor(aWire); GCPnts_QuasiUniformDeflection aProp(wireAdaptor,0.1); Base::Vector3f aPoint; currentBox.Flush(); for (int j=1;j<=aProp.NbPoints();++j) { aPoint.x = float(aProp.Value(j).X()); aPoint.y = float(aProp.Value(j).Y()); aPoint.z = float(aProp.Value(j).Z()); currentBox.Add(aPoint); } return currentBox; } TopoDS_Shape cutting_tools::getProperCut(TopoDS_Shape& aShape) { //A cutting Shape is coming as aShape //check direction to decide which Topology to hold and which to delete if (m_direction)//From top to bottom { } TopoDS_Shape aReturnShape; return aReturnShape; } bool cutting_tools::calculateAccurateSlaveZLevel(std::vector >& OffsetPoints, double current_z_level, double &slave_z_level, double &average_sheet_thickness, double &average_angle, bool &cutpos) { //Mittelwert von allen Normalenwinkeln und damit dann den Mittelwert der Blechdicke bilden bool direction,area; //Zunächst checken in welchem Bereich vom Teil wir uns aufhalten if (current_z_level < m_MachiningOrder[0].first.z && current_z_level > m_MachiningOrder[1].first.z) { //Wir sind von oben nach unten im ersten Teil direction = true; area = true; } else if (m_MachiningOrder.size() > 2 && current_z_level < m_MachiningOrder[1].first.z) { //Wir sind von oben nach unten im zweiten Teil direction = true; area = false; } else if (m_MachiningOrder.size() > 2 && current_z_level < m_MachiningOrder[2].first.z && current_z_level > m_MachiningOrder[1].first.z) { //Wir sind von unten nach oben im 2. Teil direction = false; area = false; } else { cout << "Konnte keine Zuordnung finden" << endl; } average_angle = 0.0; double slave_z_leveltop,slave_z_levelbottom; for (unsigned int i=0;i (m_MachiningOrder[0].first.z-m_UserSettings.sheet_thickness)) { if ((slave_z_levelbottom + m_UserSettings.slave_radius) < (m_MachiningOrder[0].first.z - m_UserSettings.sheet_thickness)) { slave_z_level = slave_z_levelbottom; cutpos = false; return true; } else { slave_z_level = m_MachiningOrder[0].first.z; return true; } } //Die oberste Ebene ist hier abgehakt if (direction && !area && slave_z_leveltop < (m_MachiningOrder[1].first.z - m_UserSettings.sheet_thickness)) { slave_z_level = slave_z_leveltop; cutpos = true; return true; } else if (direction && !area && slave_z_leveltop > (m_MachiningOrder[1].first.z-m_UserSettings.sheet_thickness)) { if ((slave_z_levelbottom + m_UserSettings.slave_radius) < (m_MachiningOrder[1].first.z - m_UserSettings.sheet_thickness)) { slave_z_level = slave_z_levelbottom; cutpos = false; return true; } else { slave_z_level = m_MachiningOrder[1].first.z; return true; } } //Jetzt noch die Geschichte wo wir wieder nach oben fahren if (!direction && !area && slave_z_leveltop < (m_MachiningOrder[1].first.z - m_UserSettings.sheet_thickness)) { slave_z_level = slave_z_leveltop; cutpos = true; return true; } else if (direction && !area && slave_z_leveltop > (m_MachiningOrder[2].first.z-m_UserSettings.sheet_thickness)) { if ((slave_z_levelbottom + m_UserSettings.slave_radius) < (m_MachiningOrder[2].first.z - m_UserSettings.sheet_thickness)) { slave_z_level = slave_z_levelbottom; cutpos = false; return true; } else { slave_z_level = m_MachiningOrder[2].first.z; return true; } } return true; } //bool cutting_tools::OffsetWires() //Hier ist die alte Version //{ // for(m_it = m_all_cuts.begin();m_itD1(Umin,Vmin,projectedPoint,Uvec,Vvec); // normalVec = Uvec; // normalVec.Cross(Vvec); // normalVec.Normalize(); //Jetzt ist die Normale berechnet und auch normalisiert // //zeroPoint.SetCoord(0.0,0.0,0.0); // // projPointVec.SetXYZ(projectedPoint.XYZ()); // OffsetPoint.SetXYZ((projPointVec + (normalVec*(-21))).XYZ()); // finalOffsetPoints->SetValue(i,OffsetPoint); //Aktuellen OffsetPoint setzen // } // Standard_Boolean isPeriodic = Standard_False; // GeomAPI_Interpolate aNoPeriodInterpolate(finalOffsetPoints, isPeriodic, Precision::Confusion()); // aNoPeriodInterpolate.Perform(); // Handle_Geom_BSplineCurve aCurve(aNoPeriodInterpolate.Curve()); // // // check results // if (!aNoPeriodInterpolate.IsDone()) return false; // m_all_offset_cuts_high.push_back(aCurve); // } //} gp_Dir cutting_tools::getPerpendicularVec(gp_Vec& anInput) { double x,y; gp_Dir Output; x = anInput.X(); y = anInput.Y(); if (x != 0.0 && y != 0.0) { Output.SetCoord(1.0,(-x/y),0.0); } else if (x == 0 && y == 0) { Output.SetCoord(1.0,1.0,0.0); } else if (x == 0 && y != 0) { Output.SetCoord(1.0,0.0,0.0); } else if (x != 0 && y == 0) { Output.SetCoord(0.0,1.0,0.0); } return Output; } bool cutting_tools::OffsetWires_Spiral() { std::ofstream anoutput1; anoutput1.open("c:/spiral.txt"); Base::Builder3D log; std::vector >::iterator current_flat_level; current_flat_level = m_ordered_cuts.begin(); SpiralHelper lastPoint; lastPoint.SurfacePoint.SetCoord(0.0,0.0,0.0); bool slave_done= false; //Necessary if the slave is already output bool just_started = true; // gp_Vec direction_vector(0.0,0.0,1.0),last_direction_vector(0.0,0.0,1.0);//Just to initialize them bool direction = true; //for the Robot, this tells the algo that we have to switch the direction //Nicht beim höchsten Anfangen, da wir den nicht mit dem Master fahren wollen for (m_ordered_cuts_it = m_ordered_cuts.begin()+1;m_ordered_cuts_it!=m_ordered_cuts.end();++m_ordered_cuts_it) { std::vector OffsetSpiralPoints,TempSpiralPoints; std::vector SlavePointContainer; OffsetSpiralPoints.clear(); TempSpiralPoints.clear(); //Now we have to select which strategy to choose //if the current levels is bigger,the same, or less then the previous one if (m_ordered_cuts_it->first<(m_ordered_cuts_it-1)->first) { //Master is calculated as Usual, Slave stays at the currently highest level //Check if Last Level has got a Wire as we go from the last to the current with our Spiral SpiralHelper aSpiralStruct; double CurveLength = 0.0; if ((m_ordered_cuts_it-1)->second.ShapeType() == TopAbs_WIRE) { WireExplorer aWireExplorer(TopoDS::Wire((m_ordered_cuts_it-1)->second)); for (aWireExplorer.Init();aWireExplorer.More();aWireExplorer.Next()) { CurveLength = CurveLength + GetEdgeLength(aWireExplorer.Current()); BRepAdaptor_Curve curveAdaptor(aWireExplorer.Current()); //Adjust the point amount based on the curve length make every 0.3mm a point //GCPnts_QuasiUniformAbscissa aProp(curveAdaptor,int(GetEdgeLength(aWireExplorer.Current())/0.4)); GCPnts_QuasiUniformAbscissa aProp(curveAdaptor,1000); for (int i=1;i<=aProp.NbPoints();++i) { //Check the direction if (aWireExplorer.Current().Orientation() != TopAbs_REVERSED) curveAdaptor.D1(aProp.Parameter(i),aSpiralStruct.SurfacePoint,aSpiralStruct.LineD1); else curveAdaptor.D1(aProp.Parameter(aProp.NbPoints()-i+1),aSpiralStruct.SurfacePoint,aSpiralStruct.LineD1); aSpiralStruct.SurfaceNormal.SetCoord(0.0,0.0,1.0); TempSpiralPoints.push_back(aSpiralStruct); } } } else { CurveLength = 0.0; Edgesort aCutShapeSorter((m_ordered_cuts_it-1)->second); for (aCutShapeSorter.Init();aCutShapeSorter.More();aCutShapeSorter.Next()) { CurveLength = CurveLength + GetEdgeLength(aCutShapeSorter.Current()); //Get the PCurve and the GeomSurface Handle_Geom2d_Curve a2DCurve; Handle_Geom_Surface aSurface; TopLoc_Location aLoc; double first2,last2; bool reversed = false; BRep_Tool::CurveOnSurface(aCutShapeSorter.Current(),a2DCurve,aSurface,aLoc,first2,last2); //Jetzt noch die resultierende Surface und die Curve sauber drehen //(vielleicht wurde ja das TopoDS_Face irgendwie gedreht oder die TopoDS_Edge) if (aCutShapeSorter.Current().Orientation() == TopAbs_REVERSED) reversed = true; BRepAdaptor_Curve aCurveAdaptor(aCutShapeSorter.Current()); GCPnts_QuasiUniformAbscissa aPointGenerator(aCurveAdaptor,1000); int PointSize = aPointGenerator.NbPoints(); //Now get the surface normal to the generated points for (int i=1;i<=PointSize;++i) { gp_Pnt2d a2dParaPoint; gp_Pnt aSurfacePoint; TopoDS_Face aFace; gp_Vec Uvec,Vvec,normalVec; //If the curve is reversed we also have to reverse the point direction if (reversed) { a2DCurve->D0(aPointGenerator.Parameter(PointSize-i+1),a2dParaPoint); aCurveAdaptor.D1(aPointGenerator.Parameter(PointSize-i+1),aSurfacePoint,aSpiralStruct.LineD1); } else { a2DCurve->D0(aPointGenerator.Parameter(i),a2dParaPoint); aCurveAdaptor.D1(aPointGenerator.Parameter(i),aSurfacePoint,aSpiralStruct.LineD1); } GeomAdaptor_Surface aGeom_Adaptor(aSurface); aGeom_Adaptor.D1(a2dParaPoint.X(),a2dParaPoint.Y(),aSurfacePoint,Uvec,Vvec); //Jetzt den Normalenvector auf die Fläche ausrechnen normalVec = Uvec; normalVec.Cross(Vvec); normalVec.Normalize(); //Jetzt ist die Normale berechnet und auch normalisiert //Jetzt noch checken ob die Normale auch wirklich auf die saubere Seite zeigt //dazu nur checken ob der Z-Wert der Normale größer Null ist (dann im 1.und 2. Quadranten) if (normalVec.Z()<0) normalVec.Multiply(-1.0); //Mal kurz den Winkel zur Grund-Ebene ausrechnen gp_Vec planeVec(normalVec.X(),normalVec.Y(),0.0); //Den Winkel speichern float angle = float(normalVec.Angle(planeVec)); aSpiralStruct.SurfaceNormal = normalVec; aSpiralStruct.SurfacePoint = aSurfacePoint; TempSpiralPoints.push_back(aSpiralStruct); } } } //Now we have to find the shortest distance to the lastPoint of the previous spiral. //At the beginning the lastPoint is the Origin //This represents our startPoint. If we just started, then we skip this point unsigned int start_index = 0,adapted_start_index=0; float dist,distold = FLT_MAX; for (unsigned int t=0;tsecond); BRepAdaptor_CompCurve2 wireAdaptor(aWire); GCPnts_QuasiUniformAbscissa aProp(wireAdaptor,1000); SlavePointContainer.clear(); gp_Pnt SlaveOffsetPoint; for (int i=1;i<=aProp.NbPoints();++i) { wireAdaptor.D0(aProp.Parameter(i),SlaveOffsetPoint); SlaveOffsetPoint.SetZ(SlaveOffsetPoint.Z() - m_UserSettings.sheet_thickness - m_UserSettings.slave_radius); //checken ob der neue Punkt zu nahe am alten ist. Wenn ja, dann kein push_back if (SlavePointContainer.size()>0 && (SlavePointContainer.rbegin()->SquareDistance(SlaveOffsetPoint)>(Precision::Confusion()*Precision::Confusion()))) SlavePointContainer.push_back(SlaveOffsetPoint); else if (SlavePointContainer.empty()) SlavePointContainer.push_back(SlaveOffsetPoint); } //Now Interpolate the Slave with reordered points based on the last point int index = 0; distold = FLT_MAX; for (unsigned int t=0;tSetValue(t+1,SlavePointContainer[t]); if (t==index) break; if (t+1==SlavePointContainer.size()) t=-1; } m_all_offset_cuts_low.push_back(InterpolateOrderedPoints(InterpolationPoints,true)); slave_done = true; } //Slave done gp_Pnt PreviousPoint = TempSpiralPoints[start_index].SurfacePoint; //check the current direction we would go gp_Vec help_Vec(TempSpiralPoints[start_index].SurfacePoint.Coord()); if (!start_index+1>=TempSpiralPoints.size()) direction_vector = TempSpiralPoints[start_index+1].SurfacePoint.Coord(); else direction_vector = TempSpiralPoints[1].SurfacePoint.Coord();//As Start and End-Point are the same direction_vector.Subtract(help_Vec); //direction_vector.SetZ(0.0); direction_vector.Normalize(); direction_vector.Multiply(1.0); //Zum testen bauen wir keinen Offset ein //switch the Spiral-direction if the clockwise flag is checked and the //angle between the last and current round is more then 90° double angle = direction_vector.Angle(last_direction_vector); if (m_UserSettings.clockwise && angle<(D_PI*0.5)) direction = true; //We are already in the wright direction else if (m_UserSettings.clockwise && angle >(D_PI*0.5)) direction = false; //we have to switch the direction else if (!m_UserSettings.clockwise && angle<(D_PI*0.5)) direction = false; else if (!m_UserSettings.clockwise && angle>(D_PI*0.5)) direction = true; IntCurvesFace_ShapeIntersector anIntersector; anIntersector.Load(m_Shape,0.01); //Insert the first point into the TempSpiralPoints if we have just started std::vector TempSpiralPointsFinal; TempSpiralPointsFinal.clear(); if (!just_started) TempSpiralPointsFinal.push_back(lastPoint); else just_started = false;//The first point is now done if (direction && ((start_index+1)=TempSpiralPoints.size())) adapted_start_index = 1;//Not 0 because the last one is already added else { if (start_index==0) adapted_start_index = TempSpiralPoints.size()-2; //Skip the last Point as its equal to the first one else adapted_start_index = start_index-1; } std::cout<<"Angle ="<< angle<< " Direction = "<< direction << "Start_Index: "<< adapted_start_index <<","<0) { float shortestDistance, shortestDistanceOld = FLT_MAX; for (int g=1;g<=points;g++) { const gp_Pnt& TestPoint = anIntersector.Pnt(g); shortestDistance = float(TestPoint.SquareDistance(TempSpiralPoints[j].SurfacePoint)); if (shortestDistance156)//The point is more then 14mm away (square distance) continue; TempSpiralPoints[j].SurfacePoint = anIntersector.Pnt(current_index); } else //We have to try a mesh intersection as the Nurb Intersection does not seem to work { cout << "Big Probleme"; continue; } //Now get the Proper Normal at this point BRepAdaptor_Surface aFaceAdaptor(anIntersector.Face(current_index)); gp_Pnt P; gp_Vec U_Vec,V_Vec; aFaceAdaptor.D1(anIntersector.UParameter(current_index),anIntersector.VParameter(current_index),P,U_Vec,V_Vec); U_Vec.Cross(V_Vec); U_Vec.Normalize(); if (U_Vec.Z() < 0) U_Vec.Multiply(-1.0); TempSpiralPoints[j].SurfaceNormal = U_Vec; TempSpiralPointsFinal.push_back(TempSpiralPoints[j]); //If we reached the end before we processed all points, then we start at the beginning. if (direction) { if (j==start_index) break; //Now we have completed all Points else if (j+1==TempSpiralPoints.size()) { j=-1; //-1 because at the for we ++ the variable directly continue; } } else { if (j==start_index) break; //Now we have completed all Points else if (j-1<0) { j=TempSpiralPoints.size()-3; continue; } //We switch to the end and skip the last point //as its the same as the point at j=0; j=j-2;//As the for puts +1 for each step } } //Offset for Master and Slave OffsetSpiralPoints = OffsetSpiral(TempSpiralPointsFinal); //Now store the lastPoint of the currentSpiral as we need it for the next one lastPoint = *(TempSpiralPointsFinal.rbegin()); gp_Vec temp_vector((OffsetSpiralPoints.rbegin()+5)->SurfacePoint.Coord()); last_direction_vector = OffsetSpiralPoints.rbegin()->SurfacePoint.Coord(); last_direction_vector.Subtract(temp_vector); //last_direction_vector.SetZ(0.0); last_direction_vector.Normalize(); last_direction_vector.Multiply(10.0); Handle(TColgp_HArray1OfPnt) InterpolationPoints = new TColgp_HArray1OfPnt(1,OffsetSpiralPoints.size()); TColgp_Array1OfVec Tangents(1,OffsetSpiralPoints.size()); for (unsigned int t=0;tSetValue(t+1,OffsetSpiralPoints[t].SurfacePoint); } bool check = CheckPoints(InterpolationPoints); //Here we interpolate. If direction == true this means that the rotation is like the initial rotation m_all_offset_cuts_high.push_back(InterpolateOrderedPoints(InterpolationPoints,true)); } if (m_ordered_cuts_it->first==(m_ordered_cuts_it-1)->first) { //we only set the new flat level wire here //no Toolpath is calculated current_flat_level = m_ordered_cuts_it; slave_done = false; //This is to generate the next flat level for the slave just_started = true; //We start a new section }//end of current == last //Now lets take the case when we move up again if (m_ordered_cuts_it->first>(m_ordered_cuts_it-1)->first) { //Slave is calculated as Usual, Master stays at the currently highest level //Check if Last Level has got a Wire as we go from the last to the current with our Spiral SpiralHelper aSpiralStruct; double CurveLength = 0.0; if ((m_ordered_cuts_it-1)->second.ShapeType() == TopAbs_WIRE) { WireExplorer aWireExplorer(TopoDS::Wire((m_ordered_cuts_it-1)->second)); for (aWireExplorer.Init();aWireExplorer.More();aWireExplorer.Next()) { CurveLength = CurveLength + GetEdgeLength(aWireExplorer.Current()); BRepAdaptor_Curve curveAdaptor(aWireExplorer.Current()); //Adjust the point amount based on the curve length make every 0.3mm a point //GCPnts_QuasiUniformAbscissa aProp(curveAdaptor,int(GetEdgeLength(aWireExplorer.Current())/0.4)); GCPnts_QuasiUniformAbscissa aProp(curveAdaptor,1000); for (int i=1;i<=aProp.NbPoints();++i) { //Check the direction if (aWireExplorer.Current().Orientation() != TopAbs_REVERSED) curveAdaptor.D1(aProp.Parameter(i),aSpiralStruct.SurfacePoint,aSpiralStruct.LineD1); else curveAdaptor.D1(aProp.Parameter(aProp.NbPoints()-i+1),aSpiralStruct.SurfacePoint,aSpiralStruct.LineD1); aSpiralStruct.SurfaceNormal.SetCoord(0.0,0.0,1.0); TempSpiralPoints.push_back(aSpiralStruct); } } } else { CurveLength = 0.0; Edgesort aCutShapeSorter((m_ordered_cuts_it-1)->second); for (aCutShapeSorter.Init();aCutShapeSorter.More();aCutShapeSorter.Next()) { CurveLength = CurveLength + GetEdgeLength(aCutShapeSorter.Current()); //Get the PCurve and the GeomSurface Handle_Geom2d_Curve a2DCurve; Handle_Geom_Surface aSurface; TopLoc_Location aLoc; double first2,last2; bool reversed = false; BRep_Tool::CurveOnSurface(aCutShapeSorter.Current(),a2DCurve,aSurface,aLoc,first2,last2); //Jetzt noch die resultierende Surface und die Curve sauber drehen //(vielleicht wurde ja das TopoDS_Face irgendwie gedreht oder die TopoDS_Edge) if (aCutShapeSorter.Current().Orientation() == TopAbs_REVERSED) reversed = true; BRepAdaptor_Curve aCurveAdaptor(aCutShapeSorter.Current()); GCPnts_QuasiUniformAbscissa aPointGenerator(aCurveAdaptor,1000); int PointSize = aPointGenerator.NbPoints(); //Now get the surface normal to the generated points for (int i=1;i<=PointSize;++i) { gp_Pnt2d a2dParaPoint; gp_Pnt aSurfacePoint; TopoDS_Face aFace; gp_Vec Uvec,Vvec,normalVec; //If the curve is reversed we also have to reverse the point direction if (reversed) { a2DCurve->D0(aPointGenerator.Parameter(PointSize-i+1),a2dParaPoint); aCurveAdaptor.D1(aPointGenerator.Parameter(PointSize-i+1),aSurfacePoint,aSpiralStruct.LineD1); } else { a2DCurve->D0(aPointGenerator.Parameter(i),a2dParaPoint); aCurveAdaptor.D1(aPointGenerator.Parameter(i),aSurfacePoint,aSpiralStruct.LineD1); } GeomAdaptor_Surface aGeom_Adaptor(aSurface); aGeom_Adaptor.D1(a2dParaPoint.X(),a2dParaPoint.Y(),aSurfacePoint,Uvec,Vvec); //Jetzt den Normalenvector auf die Fläche ausrechnen normalVec = Uvec; normalVec.Cross(Vvec); normalVec.Normalize(); //Jetzt ist die Normale berechnet und auch normalisiert //Jetzt noch checken ob die Normale auch wirklich auf die saubere Seite zeigt //dazu nur checken ob der Z-Wert der Normale größer Null ist (dann im 1.und 2. Quadranten) if (normalVec.Z()<0) normalVec.Multiply(-1.0); //Mal kurz den Winkel zur Grund-Ebene ausrechnen gp_Vec planeVec(normalVec.X(),normalVec.Y(),0.0); //Den Winkel speichern float angle = float(normalVec.Angle(planeVec)); aSpiralStruct.SurfaceNormal = normalVec; aSpiralStruct.SurfacePoint = aSurfacePoint; TempSpiralPoints.push_back(aSpiralStruct); } } } //Now we have to find the shortest distance to the lastPoint of the previous spiral. //At the beginning the lastPoint is the Origin //This represents our startPoint. If we just started, then we skip this point int start_index = 0,adapted_start_index=0; float dist,distold = FLT_MAX; for (unsigned int t=0;tsecond); BRepAdaptor_CompCurve2 wireAdaptor(aWire); GCPnts_QuasiUniformAbscissa aProp(wireAdaptor,1000); SlavePointContainer.clear(); gp_Pnt SlaveOffsetPoint; for (int i=1;i<=aProp.NbPoints();++i) { wireAdaptor.D0(aProp.Parameter(i),SlaveOffsetPoint); SlaveOffsetPoint.SetZ(SlaveOffsetPoint.Z() + m_UserSettings.master_radius); //checken ob der neue Punkt zu nahe am alten ist. Wenn ja, dann kein push_back if (SlavePointContainer.size()>0 && (SlavePointContainer.rbegin()->SquareDistance(SlaveOffsetPoint)>(Precision::Confusion()*Precision::Confusion()))) SlavePointContainer.push_back(SlaveOffsetPoint); else if (SlavePointContainer.empty()) SlavePointContainer.push_back(SlaveOffsetPoint); } //Now Interpolate the Slave with reordered points based on the last point Handle(TColgp_HArray1OfPnt) InterpolationPoints = new TColgp_HArray1OfPnt(1, SlavePointContainer.size()); adapted_start_index = start_index+1; for (int t=adapted_start_index;tSetValue(t+1,SlavePointContainer[t]); if (t==start_index) break; if (t+1==SlavePointContainer.size()) t=-1; } m_all_offset_cuts_high.push_back(InterpolateOrderedPoints(InterpolationPoints,true)); slave_done = true; } //Slave done gp_Pnt PreviousPoint = TempSpiralPoints[start_index].SurfacePoint; //check the current direction we would go gp_Vec help_Vec(TempSpiralPoints[start_index].SurfacePoint.Coord()); direction_vector = TempSpiralPoints[start_index+1].SurfacePoint.Coord(); direction_vector.Subtract(help_Vec); //direction_vector.SetZ(0.0); direction_vector.Normalize(); direction_vector.Multiply(10.0); //switch the Spiral-direction if the clockwise flag is checked and the //angle between the last and current round is more then 90° double angle = direction_vector.Angle(last_direction_vector); if (m_UserSettings.clockwise && angle<(D_PI*0.5)) direction = true; //We are already in the wright direction else if (m_UserSettings.clockwise && angle >(D_PI*0.5)) direction = false; //we have to switch the direction else if (!m_UserSettings.clockwise && angle<(D_PI*0.5)) direction = false; else if (!m_UserSettings.clockwise && angle>(D_PI*0.5)) direction = true; IntCurvesFace_ShapeIntersector anIntersector; anIntersector.Load(m_Shape,0.01); //Insert the first point into the TempSpiralPoints if we have just started std::vector TempSpiralPointsFinal; TempSpiralPointsFinal.clear(); gp_Pnt origin(0.0,0.0,0.0); if (!just_started) TempSpiralPointsFinal.push_back(lastPoint); else just_started=false; if (direction) adapted_start_index = start_index+1; else { if (start_index==0) adapted_start_index = TempSpiralPoints.size()-2; //Skip the last Point as its equal to the first one else adapted_start_index = start_index-1; } std::cout<<"Angle ="<< angle<< " Direction = "<< direction << "Start_Index: "<< adapted_start_index <<","<0) { float shortestDistance, shortestDistanceOld = FLT_MAX; for (int g=1;g<=points;g++) { const gp_Pnt& TestPoint = anIntersector.Pnt(g); shortestDistance = float(TestPoint.SquareDistance(TempSpiralPoints[j].SurfacePoint)); if (shortestDistance50 ) continue; TempSpiralPoints[j].SurfacePoint = anIntersector.Pnt(current_index); } else //We have to try a mesh intersection as the Nurb Intersection does not seem to work { cout << "Big Probleme"; continue; } //Now get the Proper Normal at this point BRepAdaptor_Surface aFaceAdaptor(anIntersector.Face(current_index)); gp_Pnt P; gp_Vec U_Vec,V_Vec; aFaceAdaptor.D1(anIntersector.UParameter(current_index),anIntersector.VParameter(current_index),P,U_Vec,V_Vec); U_Vec.Cross(V_Vec); U_Vec.Normalize(); if (U_Vec.Z() < 0) U_Vec.Multiply(-1.0); TempSpiralPoints[j].SurfaceNormal = U_Vec; TempSpiralPointsFinal.push_back(TempSpiralPoints[j]); //If we reached the end before we processed all points, then we start at the beginning. if (direction) { if (j==start_index) break; //Now we have completed all Points else if (j+1==TempSpiralPoints.size()) { j=-1; //-1 because at the for we ++ the variable directly continue; } } else { if (j==start_index) break; //Now we have completed all Points else if (j-1<0) { j=TempSpiralPoints.size()-3; continue; } //We switch to the end and skip the last point //as its the same as the point at j=0; j=j-2;//As the for puts +1 for each step } } //Offset for the slave OffsetSpiralPoints = OffsetSpiral(TempSpiralPointsFinal,false); //Now store the lastPoint of the currentSpiral as we need it for the next one lastPoint = *(TempSpiralPointsFinal.rbegin()); gp_Vec temp_vector((OffsetSpiralPoints.rbegin()+5)->SurfacePoint.Coord()); last_direction_vector = OffsetSpiralPoints.rbegin()->SurfacePoint.Coord(); last_direction_vector.Subtract(temp_vector); //last_direction_vector.SetZ(0.0); last_direction_vector.Normalize(); last_direction_vector.Multiply(10.0); Handle(TColgp_HArray1OfPnt) InterpolationPoints = new TColgp_HArray1OfPnt(1,OffsetSpiralPoints.size()); TColgp_Array1OfVec Tangents(1,OffsetSpiralPoints.size()); for (unsigned int t=0;tSetValue(t+1,OffsetSpiralPoints[t].SurfacePoint); } bool check = CheckPoints(InterpolationPoints); //Here we interpolate. If direction == true this means that the rotation is like the initial rotation m_all_offset_cuts_low.push_back(InterpolateOrderedPoints(InterpolationPoints,true)); } } anoutput1.close(); log.saveToFile("C:/normals.iv"); return true; } std::vector cutting_tools::OffsetSpiral(const std::vector& SpiralPoints,bool master_or_slave) { std::vector OffsetPoints; SpiralHelper OffsetPoint; OffsetPoints.clear(); //Offset the Points now for (unsigned int i=0;i0 && (OffsetPoints.rbegin()->SurfacePoint.SquareDistance(OffsetPoint.SurfacePoint)>(Precision::Confusion()*Precision::Confusion())) && (fabs(OffsetPoints.rbegin()->SurfacePoint.Z()-OffsetPoint.SurfacePoint.Z())< (m_UserSettings.level_distance/10.0))) { OffsetPoints.push_back(OffsetPoint); } else if (OffsetPoints.empty()) { OffsetPoints.push_back(OffsetPoint); } else if ((i+1==SpiralPoints.size()) && (OffsetPoints.rbegin()->SurfacePoint.SquareDistance(OffsetPoint.SurfacePoint)<(Precision::Confusion()*Precision::Confusion()))) { //This part is necessary as the last point of the current spiral would otherwise not be offsetted OffsetPoints.pop_back();//Delete the two currently last points OffsetPoints.pop_back(); OffsetPoints.push_back(OffsetPoint);//Add the last point } } return OffsetPoints; } std::vector cutting_tools::getFlatAreas() { std::vector FlatAreas; FlatAreas.clear(); for (unsigned int i=0;i >::iterator current_flat_level; gp_Pnt lastPoint(0.0,0.0,0.0); //Initialize the first Point to the Origin current_flat_level = m_ordered_cuts.begin(); bool slave_done= false; //Necessary if the slave is already put out //Nicht beim höchsten Anfangen, da wir den nicht mit dem Master fahren wollen for (m_ordered_cuts_it = m_ordered_cuts.begin()+1;m_ordered_cuts_it!=m_ordered_cuts.end();++m_ordered_cuts_it) { std::vector > MasterPointContainer; std::vector > > MasterPointsStorage; std::vector SlavePointContainer; std::vector > SlavePointsStorage; std::vector >::iterator anIterator1; std::vector > >::iterator anIterator2; MasterPointsStorage.clear(); SlavePointsStorage.clear(); MasterPointContainer.clear(); SlavePointContainer.clear(); //Now we have to select which strategy to choose //if the current levels is bigger,the same, or less then the previous one if (m_ordered_cuts_it->first<(m_ordered_cuts_it-1)->first) { //Master is calculated as Usual, Slave stays at the currently highest level //Check if current Level has got a Wire if (m_ordered_cuts_it->second.ShapeType() == TopAbs_WIRE) { WireExplorer aWireExplorer(TopoDS::Wire(m_ordered_cuts_it->second)); for (aWireExplorer.Init();aWireExplorer.More();aWireExplorer.Next()) { BRepAdaptor_Curve curveAdaptor(aWireExplorer.Current()); GCPnts_QuasiUniformAbscissa aProp(curveAdaptor,100); for (int i=1;i<=aProp.NbPoints();++i) { std::pair aTempPair; //Check the direction if (aWireExplorer.Current().Orientation() != TopAbs_REVERSED) curveAdaptor.D0(aProp.Parameter(i),aTempPair.first); else curveAdaptor.D0(aProp.Parameter(aProp.NbPoints()-i+1),aTempPair.first); aTempPair.first.SetZ(aTempPair.first.Z() + m_UserSettings.master_radius); aTempPair.second = 0.0; //Initialize of Angle //checken ob der neue Punkt zu nahe am alten ist. Wenn ja, dann kein push_back if (MasterPointContainer.size()>0 && (MasterPointContainer.rbegin()->first.SquareDistance(aTempPair.first)>(Precision::Confusion()*Precision::Confusion()))) { MasterPointContainer.push_back(aTempPair); } else if (MasterPointContainer.empty()) { MasterPointContainer.push_back(aTempPair); } } //Now Interpolate the Points only if we have a non-continuous edge or if we are finished //with all edges bool tangency = true; //If there are more Edges in the wire if (aWireExplorer.MoreEdge()) { tangency = CheckEdgeTangency(aWireExplorer.Current(),aWireExplorer.NextEdge()); if (!tangency) { //Store all the PointClouds in a StorageVector to arrange the Robot-Movement afterwards MasterPointsStorage.push_back(MasterPointContainer); MasterPointContainer.clear(); } else continue; } else { MasterPointsStorage.push_back(MasterPointContainer); MasterPointContainer.clear(); } } //Now check the point-cloud with the shortest distance to "lastPoint" int start_index = 0,start_array=0; CheckforLastPoint(lastPoint,start_index,start_array,MasterPointsStorage); //Now Interpolate the PointClouds...Cloud by Cloud //First we have to divide the first PointCloud as it is for sure that we start //Somewhere in the middle of it. We will then insert the points at the current start if (MasterPointsStorage.size() == 1) //If we have only one PointCloud { MasterPointContainer.clear(); bool first = true; for (unsigned int i=start_index;isize();i++) { if (i+1 == MasterPointsStorage.begin()->size()) { first = false; i=-1; continue; } MasterPointContainer.push_back(MasterPointsStorage[0][i]); if (!first && i == start_index) break; } //Now lets interpolate the Point Cloud Handle(TColgp_HArray1OfPnt) InterpolationPointsMaster = new TColgp_HArray1OfPnt(1, MasterPointContainer.size()); for (unsigned int t=0;tSetValue(t+1,MasterPointContainer[t].first); } m_all_offset_cuts_high.push_back(InterpolateOrderedPoints(InterpolationPointsMaster,true)); //Store the last point lastPoint = MasterPointContainer.rbegin()->first; } else //If we have more than one PointCloud { anIterator2 = MasterPointsStorage.begin(); MasterPointContainer.clear(); for (int i=0;i<=start_index;i++) { MasterPointContainer.push_back(MasterPointsStorage[start_array][i]); } MasterPointsStorage.insert((anIterator2+start_array+1),MasterPointContainer); MasterPointContainer.clear(); //Reinitialize the Iterators anIterator2 = MasterPointsStorage.begin(); for (unsigned int i=start_index;iSetValue(t+1,MasterPointsStorage[j][t].first); } m_all_offset_cuts_high.push_back(InterpolateOrderedPoints(InterpolationPointsMaster,true)); if (j+1==MasterPointsStorage.size()) { j=-1; continue; } if (j+1==start_array+1) break; } lastPoint = MasterPointsStorage[start_array].rbegin()->first; } } else //If the current Curve is no Wire { Edgesort aCutShapeSorter(m_ordered_cuts_it->second); for (aCutShapeSorter.Init();aCutShapeSorter.More();aCutShapeSorter.Next()) { //Get the PCurve and the GeomSurface Handle_Geom2d_Curve a2DCurve; Handle_Geom_Surface aSurface; TopLoc_Location aLoc; TopoDS_Edge anEdge; double first2,last2; bool reversed = false; BRep_Tool::CurveOnSurface(aCutShapeSorter.Current(),a2DCurve,aSurface,aLoc,first2,last2); //Jetzt noch die resultierende Surface und die Curve sauber drehen //(vielleicht wurde ja das TopoDS_Face irgendwie gedreht oder die TopoDS_Edge) if (aCutShapeSorter.Current().Orientation() == TopAbs_REVERSED) reversed = true; BRepAdaptor_Curve aCurveAdaptor(aCutShapeSorter.Current()); GCPnts_QuasiUniformAbscissa aPointGenerator(aCurveAdaptor,200); int PointSize = aPointGenerator.NbPoints(); //Now get the surface normal to the generated points for (int i=1;i<=PointSize;++i) { std::pair PointContactPair; gp_Pnt2d a2dParaPoint; gp_Pnt aSurfacePoint; TopoDS_Face aFace; gp_Vec Uvec,Vvec,normalVec; //If the curve is reversed we also have to reverse the point direction if (reversed) a2DCurve->D0(aPointGenerator.Parameter(PointSize-i+1),a2dParaPoint); else a2DCurve->D0(aPointGenerator.Parameter(i),a2dParaPoint); GeomAdaptor_Surface aGeom_Adaptor(aSurface); int t = aGeom_Adaptor.GetType(); aGeom_Adaptor.D1(a2dParaPoint.X(),a2dParaPoint.Y(),aSurfacePoint,Uvec,Vvec); //Jetzt den Normalenvector auf die Fläche ausrechnen normalVec = Uvec; normalVec.Cross(Vvec); normalVec.Normalize(); //Jetzt ist die Normale berechnet und auch normalisiert //Jetzt noch checken ob die Normale auch wirklich auf die saubere Seite zeigt //dazu nur checken ob der Z-Wert der Normale größer Null ist (dann im 1.und 2. Quadranten) if (normalVec.Z()<0) normalVec.Multiply(-1.0); //Mal kurz den Winkel zur Grund-Ebene ausrechnen gp_Vec planeVec(normalVec.X(),normalVec.Y(),0.0); //Den Winkel PointContactPair.second = normalVec.Angle(planeVec); gp_Vec NormalVecSlave = normalVec; //Jetzt die Z-Komponente auf 0 setzen //normalVec.SetZ(0.0); normalVec.Normalize(); //Jetzt die Normale mit folgender Formel multiplizieren für den Master //double multiply = m_UserSettings.master_radius*(1-sin(PointContactPair.second))/cos(PointContactPair.second); double multiply = m_UserSettings.master_radius; normalVec.Multiply(multiply); //Jetzt den OffsetPunkt berechnen PointContactPair.first.SetXYZ(aSurfacePoint.XYZ() + normalVec.XYZ()); //Damit wir keine Punkte bekommen die zu nahe beieinander liegen //Den letzten hinzugefügten Punkt suchen if (MasterPointContainer.size()>0 && (MasterPointContainer.rbegin()->first.SquareDistance(PointContactPair.first)>0.001)) { MasterPointContainer.push_back(PointContactPair); } else if (MasterPointContainer.empty()) { MasterPointContainer.push_back(PointContactPair); } } } MasterPointsStorage.push_back(MasterPointContainer); int start_index_master = 0,start_array_master=0; CheckforLastPoint(lastPoint,start_index_master,start_array_master,MasterPointsStorage); //First we have to divide the first PointCloud as it is for sure that we start //Somewhere in the middle of it. We will then insert the points at the current start MasterPointContainer.clear(); bool first = true; for (unsigned int i=start_index_master;isize();i++) { if (i+1 == MasterPointsStorage.begin()->size()) { first = false; i=-1; continue; } MasterPointContainer.push_back(MasterPointsStorage[0][i]); if (!first && i == start_index_master) break; } //Now lets interpolate the Point Cloud Handle(TColgp_HArray1OfPnt) InterpolationPointsMaster = new TColgp_HArray1OfPnt(1, MasterPointContainer.size()); for (unsigned int t=0;tSetValue(t+1,MasterPointContainer[t].first); m_all_offset_cuts_high.push_back(InterpolateOrderedPoints(InterpolationPointsMaster,true)); //Store the last point lastPoint = MasterPointContainer.rbegin()->first; //SlaveTool Path finished }//end calculation of the master if its not a wire //Calculate the Slave Toolpath if (!slave_done)//if we did not calculate the slave toolpath for the current flat area { TopoDS_Wire aWire = TopoDS::Wire(current_flat_level->second); BRepAdaptor_CompCurve2 wireAdaptor(aWire); GCPnts_QuasiUniformAbscissa aProp(wireAdaptor,1000); SlavePointContainer.clear(); SlavePointsStorage.clear(); for (int i=1;i<=aProp.NbPoints();++i) { gp_Pnt SlaveOffsetPoint; wireAdaptor.D0(aProp.Parameter(i),SlaveOffsetPoint); SlaveOffsetPoint.SetZ(SlaveOffsetPoint.Z() - m_UserSettings.sheet_thickness - m_UserSettings.slave_radius); //checken ob der neue Punkt zu nahe am alten ist. Wenn ja, dann kein push_back if (SlavePointContainer.size()>0 && (SlavePointContainer.rbegin()->SquareDistance(SlaveOffsetPoint)>(Precision::Confusion()*Precision::Confusion()))) SlavePointContainer.push_back(SlaveOffsetPoint); else if (SlavePointContainer.empty()) SlavePointContainer.push_back(SlaveOffsetPoint); } SlavePointsStorage.push_back(SlavePointContainer); int start_index_slave = 0,start_array_slave=0; CheckforLastPoint(lastPoint,start_index_slave,start_array_slave,SlavePointsStorage); //First we have to divide the first PointCloud as it is for sure that we start //Somewhere in the middle of it. We will then insert the points at the current start SlavePointContainer.clear(); bool first = true; for (unsigned int i=start_index_slave;isize();i++) { if (i+1 == SlavePointsStorage.begin()->size()) { first = false; i=-1; continue; } SlavePointContainer.push_back(SlavePointsStorage[0][i]); if (!first && i == start_index_slave) break; } //Now Interpolate the Slave, therefore we also have to take the curves normal directions Handle(TColgp_HArray1OfPnt) InterpolationPoints = new TColgp_HArray1OfPnt(1, SlavePointContainer.size()); for (unsigned int t=0;tSetValue(t+1,SlavePointContainer[t]); m_all_offset_cuts_low.push_back(InterpolateOrderedPoints(InterpolationPoints,true)); slave_done = true; } //Slave done }//Current Curve < last curve is finished here if (m_ordered_cuts_it->first==(m_ordered_cuts_it-1)->first) { //we only set the new flat level wire here //no Toolpath is calculated current_flat_level = m_ordered_cuts_it; slave_done = false; //This is to generate the next flat level for the slave }//end of current == last if (m_ordered_cuts_it->first>(m_ordered_cuts_it-1)->first) { //The Slave Tool is now the Master Tool and therefore we only have to exchange < case if (m_ordered_cuts_it->second.ShapeType() == TopAbs_WIRE) { WireExplorer aWireExplorer(TopoDS::Wire(m_ordered_cuts_it->second)); for (aWireExplorer.Init();aWireExplorer.More();aWireExplorer.Next()) { BRepAdaptor_Curve curveAdaptor(aWireExplorer.Current()); GCPnts_QuasiUniformAbscissa aProp(curveAdaptor,100); for (int i=1;i<=aProp.NbPoints();++i) { std::pair aTempPair; //Check the direction if (aWireExplorer.Current().Orientation() != TopAbs_REVERSED) curveAdaptor.D0(aProp.Parameter(i),aTempPair.first); else curveAdaptor.D0(aProp.Parameter(aProp.NbPoints()-i+1),aTempPair.first); aTempPair.first.SetZ(aTempPair.first.Z() - m_UserSettings.slave_radius - m_UserSettings.sheet_thickness); aTempPair.second = 0.0; //Initialize of Angle //checken ob der neue Punkt zu nahe am alten ist. Wenn ja, dann kein push_back if (MasterPointContainer.size()>0 && (MasterPointContainer.rbegin()->first.SquareDistance(aTempPair.first)>(Precision::Confusion()*Precision::Confusion()))) { MasterPointContainer.push_back(aTempPair); } else if (MasterPointContainer.empty()) { MasterPointContainer.push_back(aTempPair); } } //Now Interpolate the Points only if we have a non-continuous edge or if we are finished //with all edges bool tangency = true; //If there are more Edges in the wire if (aWireExplorer.MoreEdge()) { tangency = CheckEdgeTangency(aWireExplorer.Current(),aWireExplorer.NextEdge()); if (!tangency) { //Store all the PointClouds in a StorageVector to arrange the Robot-Movement afterwards MasterPointsStorage.push_back(MasterPointContainer); MasterPointContainer.clear(); } else continue; } else { MasterPointsStorage.push_back(MasterPointContainer); MasterPointContainer.clear(); } } //Now check the point-cloud with the shortest distance to "lastPoint" int start_index = 0,start_array=0; CheckforLastPoint(lastPoint,start_index,start_array,MasterPointsStorage); //Now Interpolate the PointClouds...Cloud by Cloud //First we have to divide the first PointCloud as it is for sure that we start //Somewhere in the middle of it. We will then insert the points at the current start if (MasterPointsStorage.size() == 1) //If we have only one PointCloud { MasterPointContainer.clear(); bool first = true; for (unsigned int i=start_index;isize();i++) { if (i+1 == MasterPointsStorage.begin()->size()) { first = false; i=-1; continue; } MasterPointContainer.push_back(MasterPointsStorage[0][i]); if (!first && i == start_index) break; } //Now lets interpolate the Point Cloud Handle(TColgp_HArray1OfPnt) InterpolationPointsMaster = new TColgp_HArray1OfPnt(1, MasterPointContainer.size()); for (unsigned int t=0;tSetValue(t+1,MasterPointContainer[t].first); } m_all_offset_cuts_low.push_back(InterpolateOrderedPoints(InterpolationPointsMaster,true)); //Store the last point lastPoint = MasterPointContainer.rbegin()->first; } else //If we have more than one PointCloud { anIterator2 = MasterPointsStorage.begin(); MasterPointContainer.clear(); for (int i=0;i<=start_index;i++) { MasterPointContainer.push_back(MasterPointsStorage[start_array][i]); } MasterPointsStorage.insert((anIterator2+start_array+1),MasterPointContainer); MasterPointContainer.clear(); //Reinitialize the Iterators anIterator2 = MasterPointsStorage.begin(); for (unsigned int i=start_index;iSetValue(t+1,MasterPointsStorage[j][t].first); } m_all_offset_cuts_low.push_back(InterpolateOrderedPoints(InterpolationPointsMaster,true)); if (j+1==MasterPointsStorage.size()) { j=-1; continue; } if (j+1==start_array+1) break; } lastPoint = MasterPointsStorage[start_array].rbegin()->first; } } else //If the current Curve is no Wire { Edgesort aCutShapeSorter(m_ordered_cuts_it->second); for (aCutShapeSorter.Init();aCutShapeSorter.More();aCutShapeSorter.Next()) { //Get the PCurve and the GeomSurface Handle_Geom2d_Curve a2DCurve; Handle_Geom_Surface aSurface; TopLoc_Location aLoc; TopoDS_Edge anEdge; double first2,last2; bool reversed = false; BRep_Tool::CurveOnSurface(aCutShapeSorter.Current(),a2DCurve,aSurface,aLoc,first2,last2); //Jetzt noch die resultierende Surface und die Curve sauber drehen //(vielleicht wurde ja das TopoDS_Face irgendwie gedreht oder die TopoDS_Edge) if (aCutShapeSorter.Current().Orientation() == TopAbs_REVERSED) reversed = true; BRepAdaptor_Curve aCurveAdaptor(aCutShapeSorter.Current()); GCPnts_QuasiUniformAbscissa aPointGenerator(aCurveAdaptor,200); int PointSize = aPointGenerator.NbPoints(); //Now get the surface normal to the generated points for (int i=1;i<=PointSize;++i) { std::pair PointContactPair; gp_Pnt2d a2dParaPoint; gp_Pnt aSurfacePoint; TopoDS_Face aFace; gp_Vec Uvec,Vvec,normalVec; //If the curve is reversed we also have to reverse the point direction if (reversed) a2DCurve->D0(aPointGenerator.Parameter(PointSize-i+1),a2dParaPoint); else a2DCurve->D0(aPointGenerator.Parameter(i),a2dParaPoint); GeomAdaptor_Surface aGeom_Adaptor(aSurface); int t = aGeom_Adaptor.GetType(); aGeom_Adaptor.D1(a2dParaPoint.X(),a2dParaPoint.Y(),aSurfacePoint,Uvec,Vvec); //Jetzt den Normalenvector auf die Fläche ausrechnen normalVec = Uvec; normalVec.Cross(Vvec); normalVec.Normalize(); //Jetzt ist die Normale berechnet und auch normalisiert //Jetzt noch checken ob die Normale auch wirklich auf die saubere Seite zeigt //dazu nur checken ob der Z-Wert der Normale größer Null ist (dann im 1.und 2. Quadranten) if (normalVec.Z()<0) normalVec.Multiply(-1.0); //Mal kurz den Winkel zur Grund-Ebene ausrechnen gp_Vec planeVec(normalVec.X(),normalVec.Y(),0.0); //Den Winkel PointContactPair.second = normalVec.Angle(planeVec); gp_Vec NormalVecSlave = normalVec; //Jetzt die Z-Komponente auf 0 setzen //normalVec.SetZ(0.0); normalVec.Normalize(); //Jetzt die Normale mit folgender Formel multiplizieren für den Master //double multiply = m_UserSettings.master_radius*(1-sin(PointContactPair.second))/cos(PointContactPair.second); double multiply = m_UserSettings.slave_radius + m_UserSettings.sheet_thickness; normalVec.Multiply(multiply); normalVec.Multiply(-1.0); //As the master is the slave //Jetzt den OffsetPunkt berechnen PointContactPair.first.SetXYZ(aSurfacePoint.XYZ() + normalVec.XYZ()); //Damit wir keine Punkte bekommen die zu nahe beieinander liegen //Den letzten hinzugefügten Punkt suchen if (MasterPointContainer.size()>0 && (MasterPointContainer.rbegin()->first.SquareDistance(PointContactPair.first)>0.001)) { MasterPointContainer.push_back(PointContactPair); } else if (MasterPointContainer.empty()) { MasterPointContainer.push_back(PointContactPair); } } } MasterPointsStorage.push_back(MasterPointContainer); int start_index_master = 0,start_array_master=0; CheckforLastPoint(lastPoint,start_index_master,start_array_master,MasterPointsStorage); //First we have to divide the first PointCloud as it is for sure that we start //Somewhere in the middle of it. We will then insert the points at the current start MasterPointContainer.clear(); bool first = true; for (unsigned int i=start_index_master;isize();i++) { if (i+1 == MasterPointsStorage.begin()->size()) { first = false; i=-1; continue; } MasterPointContainer.push_back(MasterPointsStorage[0][i]); if (!first && i == start_index_master) break; } //Now lets interpolate the Point Cloud Handle(TColgp_HArray1OfPnt) InterpolationPointsMaster = new TColgp_HArray1OfPnt(1, MasterPointContainer.size()); for (unsigned int t=0;tSetValue(t+1,MasterPointContainer[t].first); m_all_offset_cuts_low.push_back(InterpolateOrderedPoints(InterpolationPointsMaster,true)); //Store the last point lastPoint = MasterPointContainer.rbegin()->first; //SlaveTool Path finished }//end calculation of the master if its not a wire //Calculate the Slave Toolpath if (!slave_done)//if we did not calculate the slave toolpath for the current flat area { TopoDS_Wire aWire = TopoDS::Wire(current_flat_level->second); BRepAdaptor_CompCurve2 wireAdaptor(aWire); GCPnts_QuasiUniformAbscissa aProp(wireAdaptor,1000); SlavePointContainer.clear(); SlavePointsStorage.clear(); for (int i=1;i<=aProp.NbPoints();++i) { gp_Pnt SlaveOffsetPoint; wireAdaptor.D0(aProp.Parameter(i),SlaveOffsetPoint); SlaveOffsetPoint.SetZ(SlaveOffsetPoint.Z() + m_UserSettings.master_radius); //checken ob der neue Punkt zu nahe am alten ist. Wenn ja, dann kein push_back if (SlavePointContainer.size()>0 && (SlavePointContainer.rbegin()->SquareDistance(SlaveOffsetPoint)>(Precision::Confusion()*Precision::Confusion()))) { SlavePointContainer.push_back(SlaveOffsetPoint); } else if (SlavePointContainer.empty()) { SlavePointContainer.push_back(SlaveOffsetPoint); } } SlavePointsStorage.push_back(SlavePointContainer); int start_index_slave = 0,start_array_slave=0; CheckforLastPoint(lastPoint,start_index_slave,start_array_slave,SlavePointsStorage); //First we have to divide the first PointCloud as it is for sure that we start //Somewhere in the middle of it. We will then insert the points at the current start SlavePointContainer.clear(); bool first = true; for (unsigned int i=start_index_slave;isize();i++) { if (i+1 == SlavePointsStorage.begin()->size()) { first = false; i=-1; continue; } SlavePointContainer.push_back(SlavePointsStorage[0][i]); if (!first && i == start_index_slave) break; } //Now Interpolate the Slave, therefore we also have to take the curves normal directions Handle(TColgp_HArray1OfPnt) InterpolationPoints = new TColgp_HArray1OfPnt(1, SlavePointContainer.size()); for (unsigned int t=0;tSetValue(t+1,SlavePointContainer[t]); m_all_offset_cuts_high.push_back(InterpolateOrderedPoints(InterpolationPoints,true)); slave_done = true; } //Slave done }//Current Curve > Last Curve }//Main for Loop which goes through all the curves return true; } bool cutting_tools::cut_Mesh(float z_level, float min_level, std::list >&result, float &z_level_corrected) { //std::ofstream outfile; //outfile.open("c:/mesh_cut.out"); Base::Vector3f z_level_plane,normal; z_level_plane.z=z_level; normal.x=0; normal.y=0; normal.z=1.0; bool cutok; //Die Richtung für die Korrektur wird hier festgelegt bool direction=true; float factor = 0.0; do { cutok = true; m_aMeshAlgo->CutWithPlane(z_level_plane,normal,*m_CAD_Mesh_Grid,result); //std::list >::iterator it; //std::vector::iterator vector_it; //checken ob wirklich ein Schnitt zustande gekommen ist if (result.size()==0) { cutok = false; //Jedes Mal ein wenig mehr Abstand für die Korrektur einfügen factor = factor+float(0.05); if (factor>=1) factor = float(0.95); //Wenn wir das erste Mal eine Korrektur machen müssen gehts zunächst mal mit Minus rein if (direction) { z_level_plane.z = (z_level-(m_pitch*factor)); z_level_corrected = z_level_plane.z; direction=false; continue; } else { z_level_plane.z = (z_level+(m_pitch*factor)); z_level_corrected = z_level_plane.z; direction=true; continue; } } } while (cutok==false); //for(vector_it=(*(result.begin())).begin();vector_it<(*(result.begin())).end();++vector_it) //outfile << (*vector_it).x <<","<<(*vector_it).y <<","<<(*vector_it).z<< std::endl; //outfile.close(); return true; } bool cutting_tools::cut(float z_level, float min_level, TopoDS_Shape &aCutShape, float &z_level_corrected) { gp_Pnt aPlanePnt(0,0,z_level); gp_Dir aPlaneDir(0,0,1); bool cutok; //Die Richtung für die Korrektur wird hier festgelegt bool correction=true; float factor = 0.0; do { cutok = true; Handle_Geom_Plane aPlane = new Geom_Plane(aPlanePnt, aPlaneDir); BRepBuilderAPI_MakeFace Face(aPlane); BRepAlgo_Section mkCut(m_Shape, Face.Face(),Standard_False); mkCut.Approximation (Standard_True); mkCut.ComputePCurveOn1(Standard_True); mkCut.Build(); //Den neuen Algorithmus checken //Edgesort aSorter(mkCut.Shape()); //aSorter.Init(); //Jetzt checken ob auch wirlich edges vorhanden sind TopExp_Explorer exploreShape; exploreShape.Init(mkCut.Shape(),TopAbs_EDGE); //Wenn keine Edge vorhanden ist if (!exploreShape.More()) { cutok = false; //Jedes Mal ein wenig mehr Abstand für die Korrektur einfügen factor = factor+float(0.05); if (factor>=1) factor = float(0.95); //Wenn wir das erste Mal eine Korrektur machen müssen gehts zunächst mal mit Minus rein if (correction) { aPlanePnt.SetZ(z_level-(m_pitch*factor)); z_level_corrected = float(aPlanePnt.Z()); correction=false; continue; } else { aPlanePnt.SetZ(z_level+(m_pitch*factor)); z_level_corrected = float(aPlanePnt.Z()); correction=true; continue; } } //Das Shape, welches per Referenz übergeben wird jetzt mit dem geordneten Schnitt füllen aCutShape = mkCut.Shape(); } while (cutok==false); return true; } bool cutting_tools::classifyShape() { TopExp_Explorer Explorer; Explorer.Init(m_Shape,TopAbs_FACE); if (!Explorer.More()) return false; //checken wieviele verschiedene Faces wir haben int k=0; for (; Explorer.More(); Explorer.Next()) { k++; } std::cout <<"We have " << k << "Faces" << std::endl; //Wenn mehr als ein Face vorhanden, dann eine Membervariable setzen if (k>1) m_cad = true; return true; } /* Hier ging das alte cut los bool cutok=true; //Falls wir nur ein Face haben und keine flachen Bereiche if (m_all_cuts.empty()) { //Schnitte über die Bounding Box bestimmen Bnd_Box currentBBox; Standard_Real XMin, YMin, ZMin, XMax, YMax, ZMax; BRepBndLib::Add(m_Shape, currentBBox ); currentBBox.SetGap(0.0); currentBBox.Get(XMin, YMin, ZMin, XMax, YMax, ZMax); double maxlevel=Max(ZMax,ZMin); double minlevel=Min(ZMax,ZMin); int cutnumber = fabs((maxlevel-minlevel)/m_pitch);//Cast um die Nachkommastellen wegzuschneiden m_pitch = fabs(maxlevel-minlevel)/cutnumber;//m_pitch leicht korrigieren um wirklich auf die letzte Ebene zu kommen //Aktuell wird die letzte Ebene bei selbst approxmierten Flächen nicht als Bahnkurve betrachtet //Auch die erste Ebene fällt komplett weg, da unwichtig. Lediglich für die untere Maschine ist die Bahn sinnvoll falls überhaupt noch flache Bereiche vorhanden sind for (int i=0;i InitialPlaneLevels; std::vector > atemp_storage; atemp_storage.clear(); std::vector::iterator temp_it; for (m_it= m_all_cuts.begin();m_itX2Max && Y1Min < Y2Min && Y1Max>Y2Max) //1 ist größer { if(m_it == m_all_cuts.begin())//Wenn wir auf der obersten Ebene sind.... { atemp_storage.push_back(*(m_it+1)); m_it++;//Wir überspringen damit das nächste //Damit haben wir nur noch ein Problem falls wir mehr als zwei Wires auf einer ebene haben. } else { atemp_storage.push_back(*(m_it)); } } //Mal schauen ob der Wert schon in der Liste vorhanden ist temp_it = std::find(InitialPlaneLevels.begin(),InitialPlaneLevels.end(),(*m_it).first); if (temp_it == InitialPlaneLevels.end()) { InitialPlaneLevels.push_back((*m_it).first); } } //Jetzt die flachen Bereiche der Höhe nach sortieren std::sort(InitialPlaneLevels.begin(),InitialPlaneLevels.end(),FloatHuge); //Die Schnitte müssen jetzt zwischen die flachen Stücke einsortiert werden for (temp_it=InitialPlaneLevels.begin();temp_it