cutting_tools.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002  *   Copyright (c) 2007                                                    *
00003  *   Joachim Zettler <Joachim.Zettler@gmx.de>                              *
00004  *                                                                         *
00005  *   This file is part of the FreeCAD CAx development system.              *
00006  *                                                                         *
00007  *   This library is free software; you can redistribute it and/or         *
00008  *   modify it under the terms of the GNU Library General Public           *
00009  *   License as published by the Free Software Foundation; either          *
00010  *   version 2 of the License, or (at your option) any later version.      *
00011  *                                                                         *
00012  *   This library  is distributed in the hope that it will be useful,      *
00013  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00014  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
00015  *   GNU Library General Public License for more details.                  *
00016  *                                                                         *
00017  *   You should have received a copy of the GNU Library General Public     *
00018  *   License along with this library; see the file COPYING.LIB. If not,    *
00019  *   write to the Free Software Foundation, Inc., 59 Temple Place,         *
00020  *   Suite 330, Boston, MA  02111-1307, USA                                *
00021  *                                                                         *
00022  ***************************************************************************/
00023 
00024 
00025 #include "PreCompiled.h"
00026 
00027 //Mesh Stuff
00028 #include <Mod/Mesh/App/Core/MeshKernel.h>
00029 #include <Mod/Mesh/App/Core/TopoAlgorithm.h>
00030 #include <Mod/Mesh/App/Core/Iterator.h>
00031 #include <Mod/Mesh/App/MeshPy.h>
00032 #include <Mod/Mesh/App/Mesh.h>
00033 #include <Mod/Mesh/App/Core/Elements.h>
00034 #include <Mod/Mesh/App/Core/Grid.h>
00035 
00036 
00037 //FreeCAD Stuff
00038 #include <Base/Builder3D.h>
00039 
00040 //OCC Stuff
00041 #include <BRepBuilderAPI_MakeEdge.hxx>
00042 #include <BRepBuilderAPI_MakeFace.hxx>
00043 #include <BRepBuilderAPI_MakeWire.hxx>
00044 #include <IntCurvesFace_ShapeIntersector.hxx>
00045 #include <GCPnts_QuasiUniformDeflection.hxx>
00046 #include <GCPnts_QuasiUniformAbscissa.hxx>
00047 #include <Adaptor2d_Curve2d.hxx>
00048 #include <Adaptor3d_HSurface.hxx>
00049 #include <BRep_Tool.hxx>
00050 #include <TColgp_HArray1OfPnt.hxx>
00051 #include <TColStd_HArray1OfBoolean.hxx>
00052 #include <GeomAPI_Interpolate.hxx>
00053 #include <GeomAPI_PointsToBSpline.hxx>
00054 #include <BRepAlgo_Section.hxx>
00055 #include <BRep_Tool.hxx>
00056 #include <GProp_GProps.hxx>
00057 #include <BRepGProp.hxx>
00058 #include <BRepAdaptor_Curve.hxx>
00059 #include <BRepAdaptor_Surface.hxx>
00060 #include <Geom2d_Curve.hxx>
00061 #include <Geom2dAdaptor_Curve.hxx>
00062 #include <Geom_Surface.hxx>
00063 #include <Geom_Plane.hxx>
00064 #include <Handle_Geom_Plane.hxx>
00065 #include <TopoDS_Face.hxx>
00066 #include <TopoDS_Wire.hxx>
00067 #include <TopoDS.hxx>
00068 #include <TopExp.hxx>
00069 #include <TopExp_Explorer.hxx>
00070 #include <Handle_TColStd_HArray1OfBoolean.hxx>
00071 #include <BSplCLib.hxx>
00072 #include <BRepBuilderAPI_NurbsConvert.hxx>
00073 
00074 //Own Stuff
00075 #include "cutting_tools.h"
00076 #include "best_fit.h"
00077 #include "edgesort.h"
00078 #include "WireExplorer.h"
00079 #include "BRepAdaptor_CompCurve2.h"
00080 //#include "MeshInterface.h"
00081 
00082 
00083 
00084 
00085 
00086 
00087 
00088 cutting_tools::cutting_tools(TopoDS_Shape aShape, float pitch)
00089         : m_Shape(aShape),
00090         m_aMeshAlgo(NULL),
00091         m_CAD_Mesh_Grid(NULL),
00092         m_pitch(pitch)
00093 {
00094     m_ordered_cuts.clear();
00095     m_all_offset_cuts_high.clear();
00096     m_all_offset_cuts_low.clear();
00097     m_face_bboxes.clear();
00098     m_cad = false;
00099     m_CAD_Mesh.Clear();
00100     m_FaceWireMap.clear();
00101     m_MachiningOrder.clear();
00102     getShapeBB();
00103     fillFaceBBoxes();
00104     classifyShape();
00105     //checkFlatLevel();
00106     initializeMeshStuff();
00107     //BRepBuilderAPI_Sewing aSewer;
00108     //aSewer.Add(m_Shape);
00109     //aSewer.
00110     //Everything should be initialised now
00111 
00112 }
00113 
00114 
00115 
00116 cutting_tools::cutting_tools(TopoDS_Shape aShape)
00117         :m_Shape(aShape),m_aMeshAlgo(NULL),m_CAD_Mesh_Grid(NULL),m_cad(false),m_pitch(0.0)
00118 {
00119     m_ordered_cuts.clear();
00120     m_all_offset_cuts_high.clear();
00121     m_all_offset_cuts_low.clear();
00122     m_face_bboxes.clear();
00123     m_CAD_Mesh.Clear();
00124     m_FaceWireMap.clear();
00125     m_MachiningOrder.clear();
00126     getShapeBB();
00127     fillFaceBBoxes();
00128     classifyShape();
00129     //checkFlatLevel();
00130     initializeMeshStuff();
00131 
00132 
00133 
00134 }
00135 
00136 
00137 cutting_tools::~cutting_tools()
00138 {
00139     delete m_aMeshAlgo;
00140     delete m_CAD_Mesh_Grid;
00141 }
00142 
00143 
00144 bool cutting_tools::SetMachiningOrder(const TopoDS_Face &aFace, float x,float y,float z)
00145 {
00146     std::pair<Base::Vector3f,TopoDS_Face> aTempPair;
00147     Base::Vector3f aPoint(x,y,z);
00148     aTempPair.first = aPoint;
00149     aTempPair.second = aFace;
00150     m_MachiningOrder.push_back(aTempPair);
00151     return true;
00152 }
00153 
00154 
00155 bool cutting_tools::fillFaceWireMap()
00156 {
00157     std::vector<std::pair<Base::Vector3f,TopoDS_Face> >::iterator MOrderIt;
00158     for (MOrderIt = m_MachiningOrder.begin();MOrderIt != m_MachiningOrder.end(); ++MOrderIt)
00159     {
00160         //Here we take the flat areas and put them in a map where we can easily search for the biggest, smallest Wire
00161         std::pair<TopoDS_Face,std::map<Base::BoundBox3f,TopoDS_Wire,BoundBox3f_Less> >aTempPair;
00162         aTempPair.second.clear();
00163         std::pair<Base::BoundBox3f,TopoDS_Wire> aTempBBoxPair;
00164         aTempPair.first = MOrderIt->second;
00165         //Jetzt durch das Face gehen und die Wires rausfiltern
00166         TopExp_Explorer Explore_Face;
00167         Explore_Face.Init(MOrderIt->second,TopAbs_WIRE);
00168         //If there is no Wire -> return
00169         if (!Explore_Face.More()) return false;
00170 
00171         //Jetzt alle Wires in die map schieben
00172         for (Explore_Face.ReInit();Explore_Face.More();Explore_Face.Next())
00173         {
00174             aTempBBoxPair.first = getWireBBox(TopoDS::Wire(Explore_Face.Current()));
00175             aTempBBoxPair.second = TopoDS::Wire(Explore_Face.Current());
00176             aTempPair.second.insert(aTempBBoxPair);
00177         }
00178         m_FaceWireMap.insert(aTempPair);
00179     }
00180     return true;
00181 }
00182 
00183 
00184 
00185 
00186 bool cutting_tools::getShapeBB()
00187 {
00188     //Die Cascade-Bounding Box funktioniert nicht richtig
00189     //Es wird dort wohl ne BoundingBox um dasKontrollnetz gelegt
00190     //Deshalb wird jetzt kurz das Shape tesseliert und dann die Bounding Box direkt ausgelesen
00191     best_fit::Tesselate_Shape(m_Shape,m_CAD_Mesh,float(0.1));
00192     Base::BoundBox3f aBoundBox = m_CAD_Mesh.GetBoundBox();
00193     m_maxlevel = aBoundBox.MaxZ;
00194     m_minlevel = aBoundBox.MinZ;
00195 
00196  //   //Hier testen wir noch ein paar OpenMesh Funktionen
00197  //   typedef OpenMesh::DefaultTraits MyTraits;
00198  //   typedef OpenMesh::TriMesh_ArrayKernelT<MyTraits>  MyMesh;
00199 
00201  //  Mesh::Interface<MyMesh> mesh(m_CAD_Mesh);
00203  //  MyMesh::EdgeIter e_it,e_end(mesh.edges_end());
00204  //  MyMesh::EdgeHandle eh;
00205  //  MyMesh::Scalar dist;
00206  //  MyMesh::Point startPoint,midPoint,endPoint;
00207 
00208  //  for ( e_it = mesh.edges_begin() ; e_it != e_end ; ++e_it )
00209  //  {
00210  //       eh = e_it.handle();
00211  //       dist = mesh.calc_edge_length(eh);  //get the length of the current edge
00212  //       if(dist>2.6) //Split the Edge now
00213  //       {
00214  //        
00215  //           //Get the Start and EndPoints of the Edge
00216  //          
00217  //       }
00218 
00219  //   }
00222  //mesh.release(m_CAD_Mesh);    //Function from MeshInterface to convert the Input Kernel back
00223 
00224 
00225    
00226     /* Hier ist die alte OCC BoundingBox Funktion
00227     Bnd_Box currentBBox;
00228     Standard_Real XMin, YMin, ZMin, XMax, YMax, ZMax;
00229     BRepBndLib::Add(m_shape, currentBBox );
00230        currentBBox.SetGap(1000.0);
00231        currentBBox.Get(XMin, YMin, ZMin, XMax, YMax, ZMax);
00232     */
00233     return true;
00234 }
00235 
00236 
00237 //bool cutting_tools::fillFaceMeshMap()
00238 //{
00239 // if(m_CAD_Mesh.size()>
00240 
00241 
00242 
00243 
00244 
00245 bool cutting_tools::fillFaceBBoxes()
00246 {
00247     TopoDS_Face atopo_surface;
00248     TopExp_Explorer Explorer;
00249     MeshCore::MeshKernel aFaceMesh;
00250     Base::BoundBox3f aBoundBox;
00251     Explorer.Init(m_Shape,TopAbs_FACE);
00252     for (;Explorer.More();Explorer.Next())
00253     {
00254         aFaceMesh.Clear();
00255         aBoundBox.Flush();
00256         atopo_surface = TopoDS::Face (Explorer.Current());
00257         best_fit::Tesselate_Face(atopo_surface,aFaceMesh,float(0.1));
00258         aBoundBox = aFaceMesh.GetBoundBox();
00259         aBoundBox.Enlarge(2.0);
00260         std::pair<TopoDS_Face,Base::BoundBox3f> tempPair;
00261         tempPair.first = atopo_surface;
00262         tempPair.second = aBoundBox;
00263         m_face_bboxes.push_back(tempPair);
00264     }
00265     return true;
00266 }
00267 //Hier ist die alte Version um die Bounding Box zu bestimmen
00268 //      aAdaptor_Surface.Initialize(atopo_surface);
00269 //      Standard_Real FirstUParameter, LastUParameter,FirstVParameter,LastVParameter;
00270 //      gp_Pnt aSurfacePoint;
00271 //   FirstUParameter = aAdaptor_Surface.FirstUParameter();
00272 //      LastUParameter  = aAdaptor_Surface.LastUParameter();
00273 //      FirstVParameter = aAdaptor_Surface.FirstVParameter();
00274 //      LastVParameter = aAdaptor_Surface.LastVParameter();
00275 //float urange = LastUParameter - FirstUParameter;
00276 //float vrange = LastVParameter - FirstVParameter;
00279 //Bnd_Box currentBBox;
00280 //
00281 //for(int i=0;i<10;++i)
00282 //{
00283 // for(int j=0;j<10;++j)
00284 // {
00285 //  aAdaptor_Surface.D0(FirstUParameter+((urange/10)*i),FirstVParameter+((vrange/10)*j),aSurfacePoint);
00286 //  currentBBox.Update(aSurfacePoint.X(),aSurfacePoint.Y(),aSurfacePoint.Z());
00287 // }
00288 //}
00290 //currentBBox.SetGap(0.5);
00292 //std::pair<TopoDS_Face,Bnd_Box> tempPair;
00293 //tempPair.first = atopo_surface;
00294 //tempPair.second = currentBBox;
00295 //m_face_bboxes.push_back(tempPair);
00298 //currentBBox.SetVoid();
00299 
00300 
00301 bool cutting_tools::checkPointinFaceBB(const gp_Pnt &aPnt,const Base::BoundBox3f &aBndBox)
00302 {
00303     if ((aPnt.X()>aBndBox.MinX) && (aPnt.X()<aBndBox.MaxX) && (aPnt.Y()>aBndBox.MinY) && (aPnt.Y()<aBndBox.MaxY) && (aPnt.Z()>aBndBox.MinZ) && (aPnt.Z()<aBndBox.MaxZ))
00304         return true;
00305 
00306     return false;
00307 }
00308 
00309 
00310 bool cutting_tools::initializeMeshStuff()
00311 {
00312     m_CAD_Mesh_Grid = new MeshCore::MeshFacetGrid(m_CAD_Mesh);
00313     m_aMeshAlgo = new MeshCore::MeshAlgorithm(m_CAD_Mesh);
00314     return true;
00315 }
00316 
00317 
00318 bool cutting_tools::arrangecuts_ZLEVEL()
00319 {
00320     //We have to fill the required maps first
00321     fillFaceWireMap();
00322     //Zunächst wieder checken ob CAD oder nicht
00323     if (m_cad==false)
00324     {
00325         //Cast um die Nachkommastellen wegzuschneiden
00326         int cutnumber = (int)fabs((m_maxlevel-m_minlevel)/m_pitch);
00327         //m_pitch leicht korrigieren um wirklich auf die letzte Ebene zu kommen
00328         m_pitch = fabs(m_maxlevel-m_minlevel)/cutnumber;
00329         //Jetzt die Schnitte machen. Die höchste Ebene fällt weg, da hier noch kein Blech gedrückt wird
00330         float z_level,z_level_corrected;
00331         TopoDS_Shape aCutShape;
00332         for (int i=1;i<=cutnumber;++i)
00333         {
00334             //Jetzt schneiden (die oberste Ebene auslassen)
00335             z_level = m_maxlevel-(i*m_pitch);
00336             z_level_corrected = z_level;
00337             cut(z_level,m_minlevel,aCutShape,z_level_corrected);
00338             //cut_Mesh(z_level,m_minlevel,result,z_level_corrected);
00339             //Jetzt die resultierende Wire in einen Vector pushen
00340             std::pair<float,TopoDS_Shape> tempPair;
00341             tempPair.first = z_level_corrected;
00342             tempPair.second = aCutShape;
00343             m_ordered_cuts.push_back(tempPair);
00344         }
00345         return true;
00346     }
00347     //Wenn wir mehrere Faces haben oder eine CAD-Geometrie vorhanden ist
00348     else
00349     {
00350         //Über die MachiningOrder wird jetzt die Cutting-Folge festgelegt
00351         std::vector<std::pair<Base::Vector3f,TopoDS_Face> >::iterator MOrderIt;
00352         if (m_MachiningOrder.size()<2) return false; //Did not select at least two Levels
00353         //Now take two levels and perform the Cutting Stuff
00354         for (MOrderIt = m_MachiningOrder.begin();MOrderIt != m_MachiningOrder.end(); ++MOrderIt)
00355         {
00356             float temp_max = MOrderIt->first.z;
00357             //the check if MOrderIt+1 != end is performend at the bottom of the function
00358             float temp_min = (MOrderIt+1)->first.z;
00359             //set the direction flags
00360             if (temp_max> temp_min)
00361                 m_direction = true;
00362             else m_direction = false;
00363             //Now we cut from temp_max to temp_min, without the flat areas at the top and bottom
00364 
00365             int cutnumber = (int)fabs((temp_max-temp_min)/m_UserSettings.level_distance);
00366             //m_pitch correction to really reach temp_min
00367             m_UserSettings.level_distance = fabs(temp_max-temp_min)/cutnumber;
00368 
00369             float z_level,z_level_corrected;
00370             TopoDS_Shape aCutShape;
00371             //Now lets cut and push the highest and lowest level also into the results vector
00372             std::pair<float,TopoDS_Shape> tempPair;
00373             //Highest Level push_back (only the proper Wire)
00374 
00375             tempPair.first = MOrderIt->first.z;
00376             //get the Wire with the smallest Bounding Box if we go from top to bottom for the highest area
00377             tempPair.second = m_FaceWireMap.find(MOrderIt->second)->second.begin()->second;
00378 
00379             m_ordered_cuts.push_back(tempPair);
00380             for (int i=1;i<cutnumber;++i)
00381             {
00382                 if (m_direction)
00383                     z_level = temp_max-(i*m_UserSettings.level_distance);
00384                 else
00385                     z_level = temp_max+(i*m_UserSettings.level_distance);
00386                 z_level_corrected = z_level;
00387                 cut(z_level,temp_min, aCutShape,z_level_corrected);
00388                 if (z_level_corrected != z_level)
00389                     std::cout << "Somehow we couldnt cut" << std::endl;
00390                 //Jetzt nur das gewünschte Resultat in den vector schieben (von oben nach unten große usw.)
00391                 Edgesort aCuttingShapeSorter(aCutShape);
00392                 tempPair.first = z_level_corrected;
00393                 if (m_direction)
00394                     tempPair.second = aCuttingShapeSorter.GetDesiredCutShape(2);//With an Index !=1 we get the biggest one
00395                 else
00396                     tempPair.second = aCuttingShapeSorter.GetDesiredCutShape(1);
00397                 m_ordered_cuts.push_back(tempPair);
00398             }
00399             //Now push the lowest level into the ordered_cuts_vector.
00400             //if there is no more area to cut take the biggest wire of the bottom face
00401             //otherwise take the biggest wire but continue
00402             if (MOrderIt+2 == m_MachiningOrder.end())
00403             {
00404                 tempPair.first = (MOrderIt+1)->first.z;
00405                 tempPair.second = m_FaceWireMap.find((MOrderIt+1)->second)->second.rbegin()->second;
00406                 m_ordered_cuts.push_back(tempPair);
00407                 break; //No more combination to find
00408             }
00409             else
00410             {
00411                 tempPair.first = (MOrderIt+1)->first.z;
00412                 tempPair.second = m_FaceWireMap.find((MOrderIt+1)->second)->second.rbegin()->second;
00413                 m_ordered_cuts.push_back(tempPair);
00414             }
00415         }
00416     }
00417     return true;
00418 }
00419 
00420 
00421 
00422 
00423 
00424 
00425 
00426 
00427 //}
00428 //      std::map<float,std::map<Base::BoundBox3f,TopoDS_Wire,BoundBox3f_Less> >::iterator zl_wire_it;
00429 //      //Wir holen uns jetzt den nächsten Z-Level raus. Wir müssen was kleineres
00430 //      //wie den höchsten Wert nehmen sonst gibt er immer den höchsten Wert aus
00431 //      zl_wire_it = m_zl_wire_combination.upper_bound(temp_max-0.1);
00432 //      if (zl_wire_it->first == temp_max)
00433 //      {
00434 //          cout << "Tja, es gibt wohl nur eine flache Area";
00435 //          temp_min = m_minlevel;
00436 //      }
00437 //      //Wenn es mehrere flache Bereiche gibt muss ich nochmal weitermachen
00438 //      else
00439 //      {
00440 //          temp_min = zl_wire_it->first;
00441 //          cout << "Mehrere Areas erkannt";
00442 //      }
00443 //      //Jetzt schnippeln von temp_max bis temp_min
00444 //      int cutnumber = (int)fabs((temp_max-temp_min)/m_pitch);
00445 //      //m_pitch leicht korrigieren um wirklich auf die letzte Ebene zu kommen
00446 //      m_pitch = fabs(temp_max-temp_min)/cutnumber;
00447 //      //Jetzt die Schnitte machen. Die höchste Ebene fällt weg, da hier noch kein Blech gedrückt wird
00448 //      float z_level,z_level_corrected;
00449 //      TopoDS_Shape aCutShape;
00450 //      //Jetzt schneiden (die oberste Ebene auslassen)
00451 //      for (int i=1;i<=20;++i)
00452 //      {
00453 //          z_level = temp_max-(i*m_pitch);
00454 //          z_level_corrected = z_level;
00455 //          //cut_Mesh(z_level,m_minlevel,result,z_level_corrected);
00456 //          //Jetzt die resultierenden Points in den vector schieben
00457 //          //std::pair<float,std::list<std::vector<Base::Vector3f> > > tempPair;
00458 //          //tempPair.first = z_level_corrected;
00459 //          //tempPair.second = result;
00460 //          //m_ordered_cuts.push_back(tempPair);
00461 //          cut(z_level,temp_min, aCutShape,z_level_corrected);
00462 //          //Jetzt die gefüllte Wire in den vector schieben
00463 //          std::pair<float,TopoDS_Shape> tempPair;
00464 //          tempPair.first = z_level_corrected;
00465 //          tempPair.second = aCutShape;
00466 //          m_ordered_cuts.push_back(tempPair);
00467 //      }
00468 //      return true;
00469 //  }
00470 //    return false;
00471 //}
00472 
00473 
00474 
00475 //bool cutting_tools::checkFlatLevel()
00476 //{
00477 //    //Falls keine CAD-Geometrie da ist, gleich wieder rausspringen
00478 //
00479 //    if (m_cad==false) return false;
00480 //
00481 //    TopoDS_Face atopo_surface;
00482 //    BRepAdaptor_Surface aAdaptor_Surface;
00483 //    TopExp_Explorer Explorer;
00484 //
00485 //
00486 //    for (Explorer.Init(m_Shape,TopAbs_FACE);Explorer.More();Explorer.Next())
00487 //    {
00488 //        atopo_surface = TopoDS::Face (Explorer.Current());
00489 //        aAdaptor_Surface.Initialize(atopo_surface);
00490 //        Standard_Real FirstUParameter, LastUParameter,FirstVParameter,LastVParameter;
00491 //        gp_Pnt first,second,third;
00492 //        gp_Vec first_u,first_v,second_u,second_v,third_u,third_v, Norm_first,Norm_second,Norm_third,Norm_average;
00493 //        double u_middle,v_middle;
00494 //        /*
00495 //        Generate three random point on the surface to get the surface normal and decide wether its a
00496 //        planar face or not
00497 //        */
00498 //        FirstUParameter = aAdaptor_Surface.FirstUParameter();
00499 //        LastUParameter  = aAdaptor_Surface.LastUParameter();
00500 //        FirstVParameter = aAdaptor_Surface.FirstVParameter();
00501 //        LastVParameter = aAdaptor_Surface.LastVParameter();
00502 //        u_middle = sqrt((FirstUParameter - LastUParameter)*(FirstUParameter - LastUParameter))/2;
00503 //        v_middle = sqrt((FirstVParameter - LastVParameter)*(FirstVParameter - LastVParameter))/2;
00504 //        aAdaptor_Surface.D1(sqrt((FirstUParameter-u_middle)*(FirstUParameter-u_middle))/2,sqrt((FirstVParameter-v_middle)*(FirstVParameter-v_middle))/2,first,first_u,first_v);
00505 //        aAdaptor_Surface.D1(sqrt((u_middle)*(u_middle))/2,sqrt((v_middle)*(v_middle))/2,second,second_u,second_v);
00506 //        aAdaptor_Surface.D1(sqrt((FirstUParameter+u_middle)*(FirstUParameter+u_middle))/2,sqrt((FirstVParameter+v_middle)*(FirstVParameter+v_middle))/2,third,third_u,third_v);
00507 //        //Get Surface normal as Cross-Product between two Vectors
00508 //        Norm_first = first_u.Crossed(first_v);
00509 //        Norm_first.Normalize();
00510 //        Norm_second = second_u.Crossed(second_v);
00511 //        Norm_second.Normalize();
00512 //        Norm_third = third_u.Crossed(third_v);
00513 //        Norm_third.Normalize();
00514 //        //Evaluate average normal vector
00515 //        Norm_average.SetX((Norm_first.X()+Norm_second.X()+Norm_third.X())/3);
00516 //        Norm_average.SetY((Norm_first.Y()+Norm_second.Y()+Norm_third.Y())/3);
00517 //        Norm_average.SetZ((Norm_first.Z()+Norm_second.Z()+Norm_third.Z())/3);
00518 //        Norm_average.Normalize();
00519 //        gp_Vec z_normal(0,0,1);
00520 //        gp_Vec z_normal_opposite(0,0,-1);
00521 //        if (Norm_average.IsEqual(z_normal,0.01,0.01) || Norm_average.IsEqual(z_normal_opposite,0.01,0.01))
00522 //        {
00523 //            cout << "Einen flachen Bereich gefunden";
00524 //            std::pair<float,std::map<Base::BoundBox3f,TopoDS_Wire,BoundBox3f_Less> >aTempPair;
00525 //            aTempPair.second.clear();
00526 //            std::pair<Base::BoundBox3f,TopoDS_Wire> aTempBBoxPair;
00527 //
00528 //            //Z-Wert vom flachen Bereich in ein temporäres pair pushen
00529 //            aTempPair.first = ((first.Z()+second.Z()+third.Z())/3);
00530 //            //Jetzt durch das Face gehen und die Wires rausfiltern
00531 //            TopExp_Explorer Explore_Face;
00532 //            Explore_Face.Init(atopo_surface,TopAbs_WIRE);
00533 //            //If there is no Wire -> return
00534 //            if (!Explore_Face.More()) return false;
00535 //
00536 //            //Jetzt alle Wires in die map schieben
00537 //            for (Explore_Face.ReInit();Explore_Face.More();Explore_Face.Next())
00538 //            {
00539 //                aTempBBoxPair.first = getWireBBox(TopoDS::Wire(Explore_Face.Current()));
00540 //                aTempBBoxPair.second = TopoDS::Wire(Explore_Face.Current());
00541 //                aTempPair.second.insert(aTempBBoxPair);
00542 //                //aTempPair.first ist ja noch auf dem gleichen Z-Wert wie vorher, deswegen muss da nichts abgepasst werden
00543 //            }
00544 //            m_zl_wire_combination.insert(aTempPair);
00545 //        }
00546 //    }
00547 //
00548 //    return true;
00549 //}
00550 
00551 //bool cutting_tools::projectWireToSurface(const TopoDS_Wire &aWire,const TopoDS_Shape &aShape,std::vector<projectPointContainer> &aContainer);
00552 //{
00553 // //make your wire looks like a curve to other algorithm and generate Points to offset the curve
00554 // aContainer.clear();
00555 // BRepAdaptor_CompCurve2 wireAdaptor(aWire);
00556 // GCPnts_QuasiUniformDeflection aProp(wireAdaptor,0.01);
00557 // int numberofpoints = aProp.NbPoints();
00558 // Standard_Real Umin,Vmin,lowestdistance;
00559 // TopoDS_Face atopo_surface,atopo_surface_shortest;
00560 // Handle_Geom_Surface geom_surface;
00561 //
00562 // //Now project the points to the surface and get surface normal.
00563 // for (int i=1;i<=numberofpoints;++i)
00564 // {
00565 //  lowestdistance=200;
00566 //  //Aktuellen Punkt holen
00567 //  gp_Pnt currentPoint = aProp.Value(i);
00568 //  projectPointContainer aTempContainer;
00569 //  //checken auf welches Face wir projezieren könnnen
00570 //  for(m_face_bb_it = m_face_bboxes.begin();m_face_bb_it!=m_face_bboxes.end();++m_face_bb_it)
00571 //  {
00572 //   //Wenn der aktuelle Punkt in der BBox enthalten ist, dann machen wir mit der Projection weiter
00573 //   if(checkPointinFaceBB(aProp.Value(i),m_face_bb_it->second))
00574 //   {
00575 //    atopo_surface = m_face_bb_it->first;
00576 //    geom_surface = BRep_Tool::Surface(atopo_surface);
00577 //    GeomAPI_ProjectPointOnSurf aPPS(currentPoint,geom_surface,0.001);
00578 //    //Wenn nichts projeziert werden kann, gehts gleich weiter zum nächsten Face bzw. der nächsten BBox
00579 //    if (aPPS.NbPoints() == 0) continue;
00580 //    //Jetzt muss das aktuelle Face gespeichert werden, da es eventuell das face ist, welches am nächsten ist
00581 //    double length = aPPS.LowerDistance();
00582 //    if(lowestdistance>length)
00583 //    {
00584 //     lowestdistance=length;
00585 //     atopo_surface_shortest = atopo_surface;
00586 //     aPPS.LowerDistanceParameters (Umin,Vmin);
00587 //    }
00588 //   }
00589 //  }
00590 //  gp_Vec Uvec,Vvec,normalVec;
00591 //  geom_surface = BRep_Tool::Surface(atopo_surface_shortest);
00592 //  //Das Face welches am nächsten ist in der temp-struct speichern
00593 //  aTempContainer.face = atopo_surface_shortest;
00594 //  geom_surface->D1(Umin,Vmin,aTempContainer.point,Uvec,Vvec);
00595 //  //Jetzt den Normalenvector auf die Fläche ausrechnen
00596 //  normalVec = Uvec;
00597 //  normalVec.Cross(Vvec);
00598 //  normalVec.Normalize();
00599 //  //Jetzt ist die Normale berechnet und auch normalisiert
00600 //  //Jetzt noch checken ob die Normale auch wirklich wie alle anderen auf die gleiche Seite zeigt.
00601 //  //dazu nur checken ob der Z-Wert der Normale größer Null ist (dann im 1.und 2. Quadranten)
00602 //  if(normalVec.Z()<0) normalVec.Multiply(-1.0);
00603 //  //Mal kurz den Winkel zur Grund-Ebene ausrechnen
00604 //  aTempContainer.normalvector = normalVec;
00605 //  aContainer.push_back(aTempContainer);
00606 //
00607 // }
00608 // return true;
00609 //}
00610 
00611 
00612 TopoDS_Wire cutting_tools::ordercutShape(const TopoDS_Shape &aShape)
00613 {
00614     //Bisher funktioniert das Ganze nur für Schnitte welche nur einmal rundherum laufen und noch nicht für Inseln
00615     TopExp_Explorer exploreShape;
00616     exploreShape.Init(aShape,TopAbs_EDGE);
00617     int k=0;
00618     for (; exploreShape.More(); exploreShape.Next()) //erstmal schauen wieviele Edges wir haben
00619     {
00620         k++;
00621     }
00622     //Jetzt die Edges alle in eine Wire packen (mit Add) und schauen ob ein Fehler kommt.
00623     //Wenn ja, dann die nächste Edge. Solange bis alle Edges drin sind.
00624 
00625     if (k<1)
00626     {
00627         exploreShape.ReInit();
00628         BRepBuilderAPI_MakeWire mkWire(TopoDS::Edge(exploreShape.Current()));
00629         return mkWire.Wire();
00630     }
00631     else //Nur wenn mehr als eine Edge vorhanden ist
00632     {
00633         BRepBuilderAPI_MakeWire mkWire; //WireContainer aufbauen
00634         std::vector<edge_container> listofedge_tmp,listofedge;
00635         std::vector<edge_container>::iterator it_edge;
00636         edge_container a_edge_container; //Definiert in der stuff.h
00637         listofedge.clear();
00638         listofedge_tmp.clear();
00639         exploreShape.ReInit();
00640         //Edge-Liste füllen
00641         for (; exploreShape.More(); exploreShape.Next())
00642         {
00643             a_edge_container.edge = TopoDS::Edge(exploreShape.Current());
00644             TopoDS_Vertex V1,V2;
00645             TopExp::Vertices(a_edge_container.edge,V1,V2);
00646             a_edge_container.firstPoint = BRep_Tool::Pnt(V1);;
00647             a_edge_container.lastPoint = BRep_Tool::Pnt(V2);
00648             listofedge.push_back(a_edge_container);
00649         }
00650 
00651         gp_Pnt lastpointoflastedge,firstpointoflastedge;
00652         while (listofedge.empty() == false )
00653         {
00654             listofedge_tmp.clear();
00655             for (it_edge = listofedge.begin();it_edge!=listofedge.end();++it_edge)
00656             {
00657                 mkWire.Add((*it_edge).edge);
00658                 if (mkWire.IsDone())
00659                 {
00660                     lastpointoflastedge = (*it_edge).lastPoint;
00661                     firstpointoflastedge = (*it_edge).firstPoint;
00662                 }
00663                 else
00664                 {
00665                     //Abstände ausrechnen
00666                     double abstand1=sqrt((*it_edge).firstPoint.SquareDistance(lastpointoflastedge));
00667                     double abstand2=sqrt((*it_edge).lastPoint.SquareDistance(lastpointoflastedge));
00668                     double abstand3=sqrt((*it_edge).firstPoint.SquareDistance(firstpointoflastedge));
00669                     double abstand4=sqrt((*it_edge).lastPoint.SquareDistance(firstpointoflastedge));
00670                     if (abstand1<0.5)
00671                     {
00672                         //Neue Edge erzeugen welche vom letzten Endpunkt zum aktuellen Startpunkt geht
00673                         BRepBuilderAPI_MakeEdge newedge(lastpointoflastedge,(*it_edge).firstPoint);
00674                         mkWire.Add(newedge);
00675                         mkWire.Add((*it_edge).edge);
00676                         lastpointoflastedge = (*it_edge).lastPoint;
00677                         firstpointoflastedge = (*it_edge).firstPoint;
00678                     }
00679                     else if (abstand2<0.5)
00680                     {
00681                         //Neue Edge erzeugen welche vom letzten Endpunkt zum aktuellen Startpunkt geht
00682                         BRepBuilderAPI_MakeEdge newedge(lastpointoflastedge,(*it_edge).lastPoint);
00683                         mkWire.Add(newedge);
00684                         mkWire.Add((*it_edge).edge);
00685                         lastpointoflastedge = (*it_edge).lastPoint;
00686                         firstpointoflastedge = (*it_edge).firstPoint;
00687 
00688                     }
00689 
00690                     else if (abstand3<0.5)
00691                     {
00692                         //Neue Edge erzeugen welche vom letzten Endpunkt zum aktuellen Startpunkt geht
00693                         BRepBuilderAPI_MakeEdge newedge(firstpointoflastedge,(*it_edge).firstPoint);
00694                         mkWire.Add(newedge);
00695                         mkWire.Add((*it_edge).edge);
00696                         lastpointoflastedge = (*it_edge).lastPoint;
00697                         firstpointoflastedge = (*it_edge).firstPoint;
00698                     }
00699                     else if (abstand4<0.5)
00700                     {
00701                         //Neue Edge erzeugen welche vom letzten Endpunkt zum aktuellen Startpunkt geht
00702                         BRepBuilderAPI_MakeEdge newedge(firstpointoflastedge,(*it_edge).lastPoint);
00703                         mkWire.Add(newedge);
00704                         mkWire.Add((*it_edge).edge);
00705                         lastpointoflastedge = (*it_edge).lastPoint;
00706                         firstpointoflastedge = (*it_edge).firstPoint;
00707                     }
00708                     else
00709                     {
00710                         listofedge_tmp.push_back(*it_edge);
00711                     }
00712                 }
00713             }
00714             listofedge = listofedge_tmp;
00715         }
00716         return mkWire.Wire();
00717     }
00718 
00719 }
00720 
00721 
00722 //bool cutting_tools::OffsetWires_Standard(float radius) //Version wo nur in X,Y-Ebene verschoben wird
00723 //{
00724 // Base::Builder3D build;
00725 // std::ofstream outfile;
00726 // outfile.open("c:/atest.out");
00727 //
00728 //
00729 // //Die ordered_cuts sind ein Vector wo für jede Ebene ein Pair existiert
00730 // for(m_ordered_cuts_it = m_ordered_cuts.begin();m_ordered_cuts_it!=m_ordered_cuts.end();++m_ordered_cuts_it)
00731 // {
00732 //  float current_z_level = m_ordered_cuts_it->first;
00733 //  std::vector<gp_Pnt> finalPoints;
00734 //  finalPoints.clear();
00735 //  Standard_Real Umin,Vmin,lowestdistance;
00736 //  TopoDS_Face atopo_surface,atopo_surface_shortest;
00737 //  Handle_Geom_Surface geom_surface;
00738 //  int i=0;
00739 //  for (;avector_it!=aPolyline_it->end();++avector_it)
00740 //  {
00741 //   i++;
00742 //   lowestdistance=200;
00743 //   //Aktuellen Punkt holen
00744 //   gp_Pnt currentPoint(avector_it->x,avector_it->y,avector_it->z);
00745 //   gp_Pnt nearest_Point;
00746 //   //checken auf welches Face wir projezieren könnnen
00747 //   for(m_face_bb_it = m_face_bboxes.begin();m_face_bb_it!=m_face_bboxes.end();++m_face_bb_it)
00748 //   {
00749 //    //Wenn der aktuelle Punkt in der BBox enthalten ist, dann machen wir mit der Projection weiter
00750 //    if(checkPointinFaceBB(currentPoint,m_face_bb_it->second))
00751 //    {
00752 //     atopo_surface = m_face_bb_it->first;
00753 //     geom_surface = BRep_Tool::Surface(atopo_surface);
00754 //     GeomAPI_ProjectPointOnSurf aPPS(currentPoint,geom_surface,0.001);
00755 //     //Wenn nichts projeziert werden kann, gehts gleich weiter zum nächsten Face bzw. der nächsten BBox
00756 //     if (aPPS.NbPoints() == 0) continue;
00757 //     //Jetzt muss das aktuelle Face gespeichert werden, da es eventuell das face ist, welches am nächsten ist
00758 //     double length = aPPS.LowerDistance();
00759 //     if(lowestdistance>length)
00760 //     {
00761 //      lowestdistance=length;
00762 //      atopo_surface_shortest = atopo_surface;
00763 //      //aPPS.LowerDistanceParameters (Umin,Vmin);
00764 //      nearest_Point = aPPS.NearestPoint();
00765 //     }
00766 //    }
00767 //   }
00768 //   //Für eine saubere Projection auf der aktuellen Ebene wird jetzt der Richtungsvector
00769 //   //aus dem projezierten Punkt und dem Ursprungspunkt gebildet
00770 //   //und dieser dann hergenommen um damit nochmal in dessen Richtung zu projezieren
00771 //   gp_Vec aVec(currentPoint,nearest_Point);
00772 //   aVec.Normalize();
00773 //   aVec.SetZ(0.0);
00774 //   gp_Dir aDir(aVec);
00775 //   gp_Lin aLine(currentPoint,aDir);
00776 //   IntCurvesFace_ShapeIntersector aFaceIntSect;
00777 //   aFaceIntSect.Load(m_Shape, 0.001);
00778 //   aFaceIntSect.PerformNearest(aLine,-RealLast(), +RealLast());
00779 //   //Jetzt holen wir uns auf der Fläche den U und V Wert um dann D1 und D2 bestimmen zu können
00780 //   gp_Pnt projectedPoint,OffsetPoint;
00781 //   gp_Pnt testpoint,testpoint2;
00782 //   float abstand,abstand_old;
00783 //   int number = aFaceIntSect.NbPnt();
00784 //   abstand_old = 100;
00785 //   for(int k=0;k<number;++k)
00786 //   {
00787 //    testpoint = aFaceIntSect.Pnt(k+1);
00788 //    abstand = testpoint.Distance(currentPoint);
00789 //    if(abstand<abstand_old)
00790 //    {
00791 //     Umin = aFaceIntSect.UParameter(k+1);
00792 //     Vmin = aFaceIntSect.VParameter(k+1);
00793 //     atopo_surface_shortest = aFaceIntSect.Face(k+1);
00794 //     abstand_old = abstand;
00795 //    }
00796 //   }
00797 //   gp_Vec Uvec,Vvec,normalVec,projPointVec,z_normale;
00798 //   geom_surface = BRep_Tool::Surface(atopo_surface_shortest);
00799 //   geom_surface->D1(Umin,Vmin,projectedPoint,Uvec,Vvec);
00800 //   normalVec = Uvec;
00801 //   normalVec.Cross(Vvec);
00802 //   normalVec.Normalize();
00803 //   //Jetzt ist die Surface-Normale berechnet und auch normalisiert
00804 //   //Jetzt noch checken ob die Normale auch wirklich wie alle anderen auf die gleiche Seite zeigt.
00805 //   //dazu nur checken ob der Z-Wert der Normale größer Null ist (dann im 1.und 2. Quadranten)
00806 //   if(normalVec.Z()<0) normalVec.Multiply(-1.0);
00807 //   //Jetzt die Normale auf die Radiuslänge verlängern
00808 //   normalVec.Multiply(radius);
00809 //   //Jetzt die Z-Komponente auf 0 setzen
00810 //   normalVec.SetZ(0.0);
00811 //   //float abstand = currentPoint.Distance(projectedPoint);
00812 //   //if(abstand>0.2)
00813 //   //{cout<<"error"<<endl;}
00814 //   projPointVec.SetXYZ(projectedPoint.XYZ());
00815 //   OffsetPoint.SetXYZ((projPointVec + normalVec).XYZ());
00816 //   OffsetPoint.SetZ(projectedPoint.Z()+radius);//Den Radius noch dazu addieren
00817 //   //Aktuellen OffsetPoint setzen
00818 //   finalPoints.push_back(OffsetPoint);
00819 //
00820 //   //Base::Vector3f offsetPoint,projectPoint;
00821 //   //offsetPoint.x=OffsetPoint.X();offsetPoint.y=OffsetPoint.Y();offsetPoint.z=OffsetPoint.Z();
00822 //   //projectPoint.x=projectedPoint.X();projectPoint.y=projectedPoint.Y();projectPoint.z=projectedPoint.Z();
00823 //   //build.addSingleArrow(projectPoint,offsetPoint);
00824 //   build.addSinglePoint(OffsetPoint.X(),OffsetPoint.Y(),OffsetPoint.Z());
00825 //   outfile << currentPoint.X() <<","<<currentPoint.Y()<<","<<currentPoint.Z()<<","<< projectedPoint.X() <<","<<projectedPoint.Y()<<","<<projectedPoint.Z()<<","<< OffsetPoint.X() <<","<<OffsetPoint.Y()<<","<<OffsetPoint.Z()<<","<<normalVec.X() <<","<<normalVec.Y()<<","<<normalVec.Z()<< std::endl;
00826 //  }
00827 //
00828 //
00829 // //  outfile << projectedPoint.X() <<","<<projectedPoint.Y()<<","<<projectedPoint.Z()<<std::endl;
00830 //   //Jetzt die aktuelle Kurve als BSpline interpolieren
00831 //  //check for intersections due to wrong offseted points
00832 //  checkPointIntersection(finalPoints);
00833 //  std::vector<gp_Pnt> finalPointscorrected;
00834 //  finalPointscorrected.clear();
00835 //  checkPointDistance(finalPoints,finalPointscorrected);
00836 //  Handle(TColgp_HArray1OfPnt) finalOffsetPoints = new TColgp_HArray1OfPnt(1, finalPointscorrected.size());
00837 //  for(int t=0;t<finalPointscorrected.size();++t)
00838 //  {
00839 //   finalOffsetPoints->SetValue(t+1,finalPointscorrected[t]);
00840 //  }
00841 //  GeomAPI_Interpolate aNoPeriodInterpolate(finalOffsetPoints, Standard_False, Precision::Confusion());
00842 //  aNoPeriodInterpolate.Perform();
00843 //  Handle_Geom_BSplineCurve aCurve(aNoPeriodInterpolate.Curve());
00844 //   //check results
00845 //  if (!aNoPeriodInterpolate.IsDone()) return false;
00846 //  m_all_offset_cuts_high.push_back(aCurve);
00847 // }
00848 //
00849 //
00850 //
00851 //
00852 //
00853 // build.saveToFile("c:/output.iv");
00854 // outfile.close();
00855 //
00856 //
00857 //
00858 //
00859 //
00860 //return true;
00861 //
00862 //}
00863 
00864 //bool cutting_tools::checkPointDistance(std::vector<gp_Pnt> &finalPoints,std::vector<gp_Pnt> &output)
00865 //{
00866 // std::vector<gp_Pnt>::iterator aPntIt,atempit;
00867 // output.clear();
00868 // double square_precision = Precision::Confusion()*Precision::Confusion();
00869 // int i;
00870 // for(aPntIt=finalPoints.begin();aPntIt!=finalPoints.end();++aPntIt)
00871 // {
00872 //  atempit=aPntIt;
00873 //  output.push_back(*aPntIt);
00874 //  i=1;
00875 //  while(((*(aPntIt+i)).SquareDistance(*aPntIt))< square_precision && (aPntIt+i)!=finalPoints.end())
00876 //  {
00877 //   i++;
00878 //   atempit++;
00879 //  }
00880 //  aPntIt = atempit;
00881 //
00882 //
00883 //
00884 // }
00885 //
00886 // return true;
00887 //}
00888 
00889 //bool cutting_tools::checkPointIntersection(std::vector<projectPointContainer> &finalPoints)
00890 //{
00891 // //Hier wird gecheckt ob die Punkte wirklich alle in der richtigen Reihenfolge vorliegen
00892 // std::vector<projectPointContainer>::iterator aPntIt;
00893 // double distance,distance_old;
00894 // projectPointContainer nearestPointStruct;
00895 // int k;
00896 // for(unsigned int j=0;j<finalPoints.size();++j)
00897 // {
00898 //  distance_old = 100;
00899 //  for(int i=1;i<30;++i)
00900 //  {
00901 //   //Wenn wir schon fast am Ende sind oder schon bald, dann rausspringen
00902 //   if((j+i)>=finalPoints.size()) break;
00903 //
00904 //   distance = (finalPoints[j+i].point).SquareDistance(finalPoints[j].point);
00905 //   if(distance<distance_old)
00906 //   {
00907 //    //Speichern wo wir den nächsten Punkt gefunden haben
00908 //    k=i;
00909 //    distance_old = distance;
00910 //   }
00911 //  }
00912 //  //Jetzt checken ob der nächste Punkt bereits der gesuchte ist
00913 //  if(k==1)
00914 //  {
00915 //   continue;
00916 //  }
00917 //  else
00918 //  {
00919 //   //Jetzt den Punkteaustausch vornehmen
00920 //   nearestPointStruct = finalPoints[j+k];
00921 //   finalPoints[j+k] = finalPoints[j+1];
00922 //   finalPoints[j+1] = nearestPointStruct;
00923 //  }
00924 // }
00925 //
00926 //
00927 //
00928 // return true;
00929 //}
00930 //
00931 //
00932 
00933 
00934 
00935 Handle_Geom_BSplineCurve cutting_tools::InterpolateOrderedPoints(Handle(TColgp_HArray1OfPnt) InterpolationPoints, const bool direction)
00936 {
00937     //Handle_TColStd_HArray1OfBoolean TangentFlags = new TColStd_HArray1OfBoolean(1,InterpolationPoints->Length());
00938     //for (int j=1;j<=TangentFlags->Length();++j)
00939     //    TangentFlags->SetValue(j,true);
00940 
00941     GeomAPI_Interpolate aBSplineInterpolation(InterpolationPoints, Standard_False, Precision::Confusion());
00942     //aBSplineInterpolation.Load(Tangents,TangentFlags);
00943     aBSplineInterpolation.Perform();
00944     Handle_Geom_BSplineCurve aBSplineCurve(aBSplineInterpolation.Curve());
00945     //check results
00946     //if (!aBSplineInterpolation.IsDone()) cout << "error" << endl;
00947 
00948     return aBSplineCurve;
00949 }
00950 
00951 
00952 bool cutting_tools::CheckEdgeTangency(const TopoDS_Edge& edge1, const TopoDS_Edge& edge2)
00953 {
00954     //Get the vertex which is equal to both edges
00955     TopoDS_Vertex CommonVertex;
00956     TopExp::CommonVertex(edge1,edge2,CommonVertex);
00957     if (CommonVertex.IsNull())
00958     {
00959         cout << "Not possible to calculate Tangency" << endl;
00960         return false;
00961     }
00962     gp_Pnt CommonPoint = BRep_Tool::Pnt(CommonVertex);
00963     BRepAdaptor_Curve aCurve1(edge1);
00964     BRepAdaptor_Curve aCurve2(edge2);
00965     gp_Vec Tangent1,Tangent2;
00966     gp_Pnt P;
00967     if (aCurve1.Value(aCurve1.FirstParameter()).IsEqual(CommonPoint,0.1))
00968         aCurve1.D1(aCurve1.FirstParameter(),P,Tangent1);
00969     else if (aCurve1.Value(aCurve1.LastParameter()).IsEqual(CommonPoint,0.1))
00970         aCurve1.D1(aCurve1.LastParameter(),P,Tangent1);
00971     if (aCurve2.Value(aCurve2.FirstParameter()).IsEqual(CommonPoint,0.1))
00972         aCurve2.D1(aCurve1.FirstParameter(),P,Tangent2);
00973     else if (aCurve2.Value(aCurve2.LastParameter()).IsEqual(CommonPoint,0.1))
00974         aCurve2.D1(aCurve1.LastParameter(),P,Tangent2);
00975 
00976     //Now we calculate the angle between the two Tangents and if the angle is below 10° then we say its continuous
00977     double angle = Tangent1.Angle(Tangent2);
00978     //Angle must be between +/-5°
00979     if (angle<(5.0/180.0*D_PI) || angle>(175.0/180.0*D_PI))
00980         return true;
00981     else
00982         return false;
00983 }
00984 
00985 bool cutting_tools::CheckforLastPoint(const gp_Pnt& lastPoint, int &start_index,int &start_array,const std::vector<std::vector<std::pair<gp_Pnt,double> > >& MasterPointsStorage)
00986 {
00987     float dist,distold = FLT_MAX;
00988     for (unsigned int t=0;t<MasterPointsStorage.size();++t)
00989     {
00990         for (unsigned int k=0;k<MasterPointsStorage[t].size();k++)
00991         {
00992             dist = float(MasterPointsStorage[t][k].first.SquareDistance(lastPoint));
00993             if (dist<distold)
00994             {
00995                 start_index = k;
00996                 start_array = t;
00997                 distold = dist;
00998             }
00999         }
01000     }
01001     return true;
01002 }
01003 
01004 bool cutting_tools::CheckforLastPoint(const gp_Pnt& lastPoint, int &start_index,int &start_array,const std::vector<std::vector<gp_Pnt> >& SlavePointsStorage)
01005 {
01006     float dist,distold = FLT_MAX;
01007     for (unsigned int t=0;t<SlavePointsStorage.size();++t)
01008     {
01009         for (unsigned int k=0;k<SlavePointsStorage[t].size();k++)
01010         {
01011             dist = float(SlavePointsStorage[t][k].SquareDistance(lastPoint));
01012             if (dist<distold)
01013             {
01014                 start_index = k;
01015                 start_array = t;
01016                 distold = dist;
01017             }
01018         }
01019     }
01020     return true;
01021 }
01022 
01023 bool cutting_tools::CheckforLastPoint(  const gp_Pnt& lastPoint,
01024                                         int &start_index_master,
01025                                         int &start_array_master,
01026                                         int &start_index_slave,
01027                                         int &start_array_slave,
01028                                         const std::vector<std::vector<std::pair<gp_Pnt,double> > >& MasterPointsStorage,
01029                                         const std::vector<std::vector<gp_Pnt> >& SlavePointsStorage
01030                                      )
01031 {
01032     float dist,distold = FLT_MAX;
01033     for (unsigned int t=0;t<MasterPointsStorage.size();++t)
01034     {
01035         for (unsigned int k=0;k<MasterPointsStorage[t].size();k++)
01036         {
01037             dist = float(MasterPointsStorage[t][k].first.SquareDistance(lastPoint));
01038             if (dist<distold)
01039             {
01040                 start_index_master = k;
01041                 start_array_master = t;
01042                 distold = dist;
01043             }
01044         }
01045     }
01046     distold = FLT_MAX;
01047     for (unsigned int t=0;t<SlavePointsStorage.size();++t)
01048     {
01049         for (unsigned int k=0;k<SlavePointsStorage[t].size();k++)
01050         {
01051             dist = float(SlavePointsStorage[t][k].SquareDistance(lastPoint));
01052             if (dist<distold)
01053             {
01054                 start_index_slave = k;
01055                 start_array_slave = t;
01056                 distold = dist;
01057             }
01058         }
01059     }
01060     return true;
01061 }
01062 bool cutting_tools::OffsetWires_Standard() //Version wo nur in X,Y-Ebene verschoben wird
01063 {
01064     //for debugging issues
01065     std::ofstream anoutput1,anoutput2;
01066     anoutput1.open("c:/master_output.txt");
01067     anoutput2.open("c:/slave_output.txt");
01068     std::vector<std::pair<float,TopoDS_Shape> >::iterator current_flat_level;
01069     gp_Pnt lastPoint(0.0,0.0,0.0); //Initialize the first Point to the Origin
01070     current_flat_level = m_ordered_cuts.begin();
01071     bool slave_is_wire= false; //Necessary if the slave is a wire while the master is not...
01072     //Nicht beim höchsten Anfangen, da wir den nicht mit dem Master fahren wollen
01073     for (m_ordered_cuts_it = m_ordered_cuts.begin()+1;m_ordered_cuts_it!=m_ordered_cuts.end();++m_ordered_cuts_it)
01074     {
01075         std::vector<std::pair<gp_Pnt,double> > MasterPointContainer;
01076         std::vector<std::vector<std::pair<gp_Pnt,double> > > MasterPointsStorage;
01077         std::vector<gp_Pnt> SlavePointContainer;
01078         std::vector<std::vector<gp_Pnt> > SlavePointsStorage;
01079         std::vector<std::vector<gp_Pnt> >::iterator anIterator1;
01080         std::vector<std::vector<std::pair<gp_Pnt,double> > >::iterator anIterator2;
01081         MasterPointsStorage.clear();
01082         SlavePointsStorage.clear();
01083         MasterPointContainer.clear();
01084         SlavePointContainer.clear();
01085         //Now we have to select which strategy to choose
01086         //if the current levels is bigger,the same, or less then the previous one
01087         if (m_ordered_cuts_it->first<(m_ordered_cuts_it-1)->first)
01088         {
01089             //Master is calculated as Usual, Slave follows the Master
01090             //Check if current Level has got a Wire
01091             if (m_ordered_cuts_it->second.ShapeType() == TopAbs_WIRE)
01092             {
01093                 WireExplorer aWireExplorer(TopoDS::Wire(m_ordered_cuts_it->second));
01094                 for (aWireExplorer.Init();aWireExplorer.More();aWireExplorer.Next())
01095                 {
01096                     BRepAdaptor_Curve curveAdaptor(aWireExplorer.Current());
01097                     GCPnts_QuasiUniformAbscissa aProp(curveAdaptor,100);
01098                     for (int i=1;i<=aProp.NbPoints();++i)
01099                     {
01100                         std::pair<gp_Pnt,double> aTempPair;
01101                         //Check the direction
01102                         if (aWireExplorer.Current().Orientation() != TopAbs_REVERSED)
01103                             curveAdaptor.D0(aProp.Parameter(i),aTempPair.first);
01104                         else curveAdaptor.D0(aProp.Parameter(aProp.NbPoints()-i+1),aTempPair.first);
01105                         //aTempPair.first.SetZ(aTempPair.first.Z() + m_UserSettings.master_radius);
01106                                                 aTempPair.first.SetZ(aTempPair.first.Z() );
01107                         aTempPair.second = 0.0; //Initialize of Angle
01108                         //checken ob der neue Punkt zu nahe am alten ist. Wenn ja, dann kein push_back
01109                         if (MasterPointContainer.size()>0 && (MasterPointContainer.rbegin()->first.SquareDistance(aTempPair.first)>(Precision::Confusion()*Precision::Confusion())))
01110                         {
01111                             MasterPointContainer.push_back(aTempPair);
01112                             anoutput1 << aTempPair.first.X() <<","<< aTempPair.first.Y() <<","<< aTempPair.first.Z()<<std::endl;
01113                             aTempPair.first.SetZ(aTempPair.first.Z() - m_UserSettings.master_radius - m_UserSettings.slave_radius - m_UserSettings.sheet_thickness);
01114                             SlavePointContainer.push_back(aTempPair.first);
01115                             anoutput2 << aTempPair.first.X() <<","<< aTempPair.first.Y() <<","<< aTempPair.first.Z()<<std::endl;
01116                         }
01117                         else if (MasterPointContainer.empty())
01118                         {
01119                             MasterPointContainer.push_back(aTempPair);
01120                             anoutput1 << aTempPair.first.X() <<","<< aTempPair.first.Y() <<","<< aTempPair.first.Z()<<std::endl;
01121                             aTempPair.first.SetZ(aTempPair.first.Z() - m_UserSettings.master_radius - m_UserSettings.slave_radius - m_UserSettings.sheet_thickness);
01122                             SlavePointContainer.push_back(aTempPair.first);
01123                             anoutput2 << aTempPair.first.X() <<","<< aTempPair.first.Y() <<","<< aTempPair.first.Z()<<std::endl;
01124                         }
01125                     }
01126                     //Now Interpolate the Points only if we have a non-continuous edge or if we are finished
01127                     //with all edges
01128                     bool tangency = true;
01129                     //If there are more Edges in the wire
01130                     if (aWireExplorer.MoreEdge())
01131                     {
01132                         tangency = CheckEdgeTangency(aWireExplorer.Current(),aWireExplorer.NextEdge());
01133                         if (!tangency)
01134                         {
01135                             //Store all the PointClouds in a StorageVector to arrange the Robot-Movement afterwards
01136                             MasterPointsStorage.push_back(MasterPointContainer);
01137                             SlavePointsStorage.push_back(SlavePointContainer);
01138                             MasterPointContainer.clear();
01139                             SlavePointContainer.clear();
01140                         }
01141                         else continue;
01142                     }
01143                     else
01144                     {
01145                         MasterPointsStorage.push_back(MasterPointContainer);
01146                         SlavePointsStorage.push_back(SlavePointContainer);
01147                         MasterPointContainer.clear();
01148                         SlavePointContainer.clear();
01149                     }
01150                 }
01151                 //Now check the point-cloud with the shortest distance to "lastPoint"
01152                 int start_index = 0,start_array=0;
01153                 CheckforLastPoint(lastPoint,start_index,start_array,MasterPointsStorage);
01154                 //Now Interpolate the PointClouds...Cloud by Cloud
01155                 //First we have to divide the first PointCloud as it is for sure that we start
01156                 //Somewhere in the middle of it. We will then insert the points at the current start
01157                 if (MasterPointsStorage.size() == 1) //If we have only one PointCloud
01158                 {
01159                     //To make sure that the start and end point are the same we have to use a flag
01160                     bool first = true;
01161                     for (unsigned int i=start_index;i<MasterPointsStorage.begin()->size();i++)
01162                     {
01163                         //We skip the Endpoint as it may be the same point as the start point
01164                         if (i+1 == MasterPointsStorage.begin()->size())
01165                         {
01166                             i=-1;
01167                             first = false;
01168                             continue;
01169                         }
01170                         MasterPointContainer.push_back(MasterPointsStorage[0][i]);
01171                         SlavePointContainer.push_back(SlavePointsStorage[0][i]);
01172                         if (!first && i == start_index)
01173                             break;
01174                     }
01175                     //Now lets interpolate the Point Cloud
01176                     Handle(TColgp_HArray1OfPnt) InterpolationPointsMaster = new TColgp_HArray1OfPnt(1, MasterPointContainer.size());
01177                     Handle(TColgp_HArray1OfPnt) InterpolationPointsSlave = new TColgp_HArray1OfPnt(1, SlavePointContainer.size());
01178                     for (unsigned int t=0;t<MasterPointContainer.size();++t)
01179                     {
01180                         InterpolationPointsMaster->SetValue(t+1,MasterPointContainer[t].first);
01181                         InterpolationPointsSlave->SetValue(t+1,SlavePointContainer[t]);
01182                     }
01183                     m_all_offset_cuts_high.push_back(InterpolateOrderedPoints(InterpolationPointsMaster,true));
01184                     m_all_offset_cuts_low.push_back(InterpolateOrderedPoints(InterpolationPointsSlave,true));
01185                     //Store the last point
01186                     lastPoint = MasterPointContainer.rbegin()->first;
01187                 }
01188                 else
01189                 {
01190                     anIterator1 = SlavePointsStorage.begin();
01191                     anIterator2 = MasterPointsStorage.begin();
01192                     MasterPointContainer.clear();
01193                     SlavePointContainer.clear();
01194                     for (int i=0;i<=start_index;i++)
01195                     {
01196                         MasterPointContainer.push_back(MasterPointsStorage[start_array][i]);
01197                         SlavePointContainer.push_back(SlavePointsStorage[start_array][i]);
01198                     }
01199                     MasterPointsStorage.insert((anIterator2+start_array+1),MasterPointContainer);
01200                     SlavePointsStorage.insert((anIterator1+start_array+1),SlavePointContainer);
01201                     MasterPointContainer.clear();
01202                     SlavePointContainer.clear();
01203                     //Reinitialize the Iterators
01204                     anIterator1 = SlavePointsStorage.begin();
01205                     anIterator2 = MasterPointsStorage.begin();
01206                     for (unsigned int i=start_index;i<MasterPointsStorage[start_array].size();i++)
01207                     {
01208                         MasterPointContainer.push_back(MasterPointsStorage[start_array][i]);
01209                         SlavePointContainer.push_back(SlavePointsStorage[start_array][i]);
01210                     }
01211                     MasterPointsStorage.insert((anIterator2+start_array+2),MasterPointContainer);
01212                     SlavePointsStorage.insert((anIterator1+start_array+2),SlavePointContainer);
01213                     //Reinitialize the Iterators
01214                     anIterator1 = SlavePointsStorage.begin();
01215                     anIterator2 = MasterPointsStorage.begin();
01216                     //Delete the Original PointCloud
01217                     MasterPointsStorage.erase(anIterator2+start_array);
01218                     SlavePointsStorage.erase(anIterator1+start_array);
01219                     MasterPointContainer.clear();
01220                     SlavePointContainer.clear();
01221                     //Now lets interpolate the Point Clouds
01222                     //Start at start_array+1 as the insert operations used us to do it like that
01223                     for (unsigned int j=start_array+1;j<MasterPointsStorage.size();++j)
01224                     {
01225                         Handle(TColgp_HArray1OfPnt) InterpolationPointsMaster = new TColgp_HArray1OfPnt(1, MasterPointsStorage[j].size());
01226                         Handle(TColgp_HArray1OfPnt) InterpolationPointsSlave = new TColgp_HArray1OfPnt(1, SlavePointsStorage[j].size());
01227                         for (unsigned int t=0;t<MasterPointsStorage[j].size();++t)
01228                         {
01229                             InterpolationPointsMaster->SetValue(t+1,MasterPointsStorage[j][t].first);
01230                             InterpolationPointsSlave->SetValue(t+1,SlavePointsStorage[j][t]);
01231                         }
01232                         m_all_offset_cuts_high.push_back(InterpolateOrderedPoints(InterpolationPointsMaster,true));
01233                         m_all_offset_cuts_low.push_back(InterpolateOrderedPoints(InterpolationPointsSlave,true));
01234                         if (j+1==MasterPointsStorage.size())
01235                         {
01236                             j=-1;
01237                             continue;
01238                         }
01239                         if (j+1==start_array+1)
01240                             break;
01241 
01242                     }
01243                     lastPoint = MasterPointsStorage[start_array].rbegin()->first;
01244                 }
01245             }
01246             else //If the current Curve is no Wire (Mode <)
01247             {
01248                 Edgesort aCutShapeSorter(m_ordered_cuts_it->second);
01249                 for (aCutShapeSorter.Init();aCutShapeSorter.More();aCutShapeSorter.Next())
01250                 {
01251                     //Get the PCurve and the GeomSurface
01252                     Handle_Geom2d_Curve a2DCurve;
01253                     Handle_Geom_Surface aSurface;
01254                     TopLoc_Location aLoc;
01255                     TopoDS_Edge anEdge;
01256                     double first2,last2;
01257                     bool reversed = false;
01258                     BRep_Tool::CurveOnSurface(aCutShapeSorter.Current(),a2DCurve,aSurface,aLoc,first2,last2);
01259                     //Jetzt noch die resultierende Surface und die Curve sauber drehen
01260                     //(vielleicht wurde ja das TopoDS_Face irgendwie gedreht oder die TopoDS_Edge)
01261                     if (aCutShapeSorter.Current().Orientation() == TopAbs_REVERSED)
01262                         reversed = true;
01263 
01264                     BRepAdaptor_Curve aCurveAdaptor(aCutShapeSorter.Current());
01265                     GCPnts_QuasiUniformAbscissa aPointGenerator(aCurveAdaptor,200);
01266                     int PointSize = aPointGenerator.NbPoints();
01267                     //Now get the surface normal to the generated points
01268                     for (int i=1;i<=PointSize;++i)
01269                     {
01270                         std::pair<gp_Pnt,double> PointContactPair;
01271                         gp_Pnt2d a2dParaPoint;
01272                         gp_Pnt aSurfacePoint;
01273                         TopoDS_Face aFace;
01274                         gp_Vec Uvec,Vvec,normalVec;
01275                         //If the curve is reversed we also have to reverse the point direction
01276                         if (reversed) a2DCurve->D0(aPointGenerator.Parameter(PointSize-i+1),a2dParaPoint);
01277                         else a2DCurve->D0(aPointGenerator.Parameter(i),a2dParaPoint);
01278                         GeomAdaptor_Surface aGeom_Adaptor(aSurface);
01279                         int t = aGeom_Adaptor.GetType();
01280                         aGeom_Adaptor.D1(a2dParaPoint.X(),a2dParaPoint.Y(),aSurfacePoint,Uvec,Vvec);
01281                         //Jetzt den Normalenvector auf die Fläche ausrechnen
01282                         normalVec = Uvec;
01283                         normalVec.Cross(Vvec);
01284                         normalVec.Normalize();
01285                         //Jetzt ist die Normale berechnet und auch normalisiert
01286                         //Jetzt noch checken ob die Normale auch wirklich auf die saubere Seite zeigt
01287                         //dazu nur checken ob der Z-Wert der Normale größer Null ist (dann im 1.und 2. Quadranten)
01288                         if (normalVec.Z()<0) normalVec.Multiply(-1.0);
01289 
01290                         //Mal kurz den Winkel zur Grund-Ebene ausrechnen
01291                         gp_Vec planeVec(normalVec.X(),normalVec.Y(),0.0);
01292                         //Den Winkel
01293                         PointContactPair.second = normalVec.Angle(planeVec);
01294                         gp_Vec NormalVecSlave = normalVec;
01295                         gp_Pnt SlavePoint;
01296                         //Jetzt die Z-Komponente auf 0 setzen
01297                         //normalVec.SetZ(0.0);
01298                         normalVec.Normalize();
01299                         //Jetzt die Normale mit folgender Formel multiplizieren für den Master
01300                         //double multiply = m_UserSettings.master_radius*(1-sin(PointContactPair.second))/cos(PointContactPair.second);
01301                         double multiply = m_UserSettings.master_radius;
01302                         normalVec.Multiply(multiply);
01303                         //und hier für den Slave
01304                         NormalVecSlave.Normalize();
01305                         multiply = m_UserSettings.sheet_thickness+m_UserSettings.slave_radius;
01306                         NormalVecSlave.Multiply(multiply);
01307                         //Jetzt die Richtung umdrehen
01308                         NormalVecSlave.Multiply(-1.0);
01309                         //Jetzt den OffsetPunkt berechnen
01310                         PointContactPair.first.SetXYZ(aSurfacePoint.XYZ());
01311                                                 //PointContactPair.first.SetXYZ(aSurfacePoint.XYZ() + normalVec.XYZ());
01312                         SlavePoint.SetXYZ(aSurfacePoint.XYZ() + NormalVecSlave.XYZ());
01313                         //PointContactPair.first.SetZ(PointContactPair.first.Z() + m_UserSettings.master_radius);
01314                         //Damit wir keine Punkte bekommen die zu nahe beieinander liegen
01315                         //Den letzten hinzugefügten Punkt suchen
01316                         if (MasterPointContainer.size()>0 && (MasterPointContainer.rbegin()->first.SquareDistance(PointContactPair.first)>0.001))
01317                         {
01318                             MasterPointContainer.push_back(PointContactPair);
01319                             SlavePointContainer.push_back(SlavePoint);
01320                             anoutput1 << PointContactPair.first.X() <<","<< PointContactPair.first.Y() <<","<< PointContactPair.first.Z()<<std::endl;
01321                             anoutput2 << SlavePoint.X() <<","<< SlavePoint.Y() <<","<< SlavePoint.Z()<<std::endl;
01322                         }
01323                         else if (MasterPointContainer.empty())
01324                         {
01325                             MasterPointContainer.push_back(PointContactPair);
01326                             SlavePointContainer.push_back(SlavePoint);
01327                             anoutput1 << PointContactPair.first.X() <<","<< PointContactPair.first.Y() <<","<< PointContactPair.first.Z()<<std::endl;
01328                             anoutput2 << SlavePoint.X() <<","<< SlavePoint.Y() <<","<< SlavePoint.Z()<<std::endl;
01329                         }
01330                     }
01331                 }
01332                 //Before we Output anything we check if the lowest Coordinate can still touch the "currently" highest flat area and if yes, we have to adapt the Slave toolpath
01333                 for (unsigned int k=0;k<SlavePointContainer.size();++k)
01334                 {
01335                     if ((SlavePointContainer[k].Z()+m_UserSettings.slave_radius)>(current_flat_level->first-m_UserSettings.sheet_thickness))
01336                     {
01337                         slave_is_wire = true;
01338                         TopoDS_Wire aWire = TopoDS::Wire(current_flat_level->second);
01339                         BRepAdaptor_CompCurve2 wireAdaptor(aWire);
01340                         GCPnts_QuasiUniformAbscissa aProp(wireAdaptor,1000);
01341                         SlavePointContainer.clear();
01342                         for (int i=1;i<=aProp.NbPoints();++i)
01343                         {
01344                             gp_Pnt SlaveOffsetPoint;
01345                             wireAdaptor.D0(aProp.Parameter(i),SlaveOffsetPoint);
01346                             SlaveOffsetPoint.SetZ(SlaveOffsetPoint.Z() - m_UserSettings.slave_radius - m_UserSettings.sheet_thickness);
01347                             //checken ob der neue Punkt zu nahe am alten ist. Wenn ja, dann kein push_back
01348                             if (SlavePointContainer.size()>0 && (SlavePointContainer.rbegin()->SquareDistance(SlaveOffsetPoint)>(0.001)))
01349                             {
01350                                 SlavePointContainer.push_back(SlaveOffsetPoint);
01351                                 anoutput2 << SlaveOffsetPoint.X() <<","<< SlaveOffsetPoint.Y() <<","<< SlaveOffsetPoint.Z()<<std::endl;
01352                             }
01353                             else if (SlavePointContainer.empty())
01354                             {
01355                                 SlavePointContainer.push_back(SlaveOffsetPoint);
01356                                 anoutput2 << SlaveOffsetPoint.X() <<","<< SlaveOffsetPoint.Y() <<","<< SlaveOffsetPoint.Z()<<std::endl;
01357                             }
01358                         }
01359                         break;
01360                     }
01361                 }
01362                 MasterPointsStorage.clear();
01363                 SlavePointsStorage.clear();
01364                 MasterPointsStorage.push_back(MasterPointContainer);
01365                 SlavePointsStorage.push_back(SlavePointContainer);
01366                 int start_index_master = 0,start_array_master=0,start_index_slave=0,start_array_slave=0;
01367                 CheckforLastPoint(lastPoint,start_index_master,start_array_master,start_index_slave,start_array_slave,MasterPointsStorage,SlavePointsStorage);
01368                 //If the Slave is a Wire 'slave_is_wire ==true' then we have to take care of two independent point clouds
01369                 if (!slave_is_wire)
01370                 {
01371                     //First we have to divide the first PointCloud as it is for sure that we start
01372                     //Somewhere in the middle of it. We will then insert the points at the current start
01373                     MasterPointContainer.clear();
01374                     SlavePointContainer.clear();
01375                     bool first = true;
01376                     for (unsigned int i=start_index_master;i<MasterPointsStorage.begin()->size();i++)
01377                     {
01378                         //We skip the Endpoint as it may be the same point as the start point
01379                         if (i+1 == MasterPointsStorage.begin()->size())
01380                         {
01381                             first = false;
01382                             i=-1;
01383                             continue;
01384                         }
01385                         MasterPointContainer.push_back(MasterPointsStorage[0][i]);
01386                         SlavePointContainer.push_back(SlavePointsStorage[0][i]);
01387                         if (!first && i==start_index_master)
01388                             break;
01389                     }
01390                 }
01391                 else //if slave is a wire
01392                 {
01393                     //Reset the flag
01394                     slave_is_wire = false;
01395                     //Now check the point-cloud with the shortest distance to "lastPoint"
01396                     //As the Master and the slave have different number of points we have to do it two times now
01397                     //First we have to divide the first PointCloud as it is for sure that we start
01398                     //Somewhere in the middle of it. We will then insert the points at the current start
01399                     MasterPointContainer.clear();
01400                     SlavePointContainer.clear();
01401                     bool first = true;
01402                     for (unsigned int i=start_index_master;i<MasterPointsStorage.begin()->size();i++)
01403                     {
01404                         //We skip the Endpoint as it may be the same point as the start point
01405                         if (i+1 == MasterPointsStorage.begin()->size())
01406                         {
01407                             first = false;
01408                             i=-1;
01409                             continue;
01410                         }
01411                         MasterPointContainer.push_back(MasterPointsStorage[0][i]);
01412                         if (!first && i== start_index_master)
01413                             break;
01414                     }
01415                     first = true;
01416                     for (unsigned int i=start_index_slave;i<SlavePointsStorage.begin()->size();i++)
01417                     {
01418                         //We skip the Endpoint as it may be the same point as the start point
01419                         if (i+1 == SlavePointsStorage.begin()->size())
01420                         {
01421                             first = false;
01422                             i=-1;
01423                             continue;
01424                         }
01425                         SlavePointContainer.push_back(SlavePointsStorage[0][i]);
01426                         if (!first && i== start_index_slave)
01427                             break;
01428                     }
01429                 }
01430                 //Now lets interpolate the Point Cloud
01431                 Handle(TColgp_HArray1OfPnt) InterpolationPointsMaster = new TColgp_HArray1OfPnt(1, MasterPointContainer.size());
01432                 Handle(TColgp_HArray1OfPnt) InterpolationPointsSlave = new TColgp_HArray1OfPnt(1, SlavePointContainer.size());
01433                 for (unsigned int t=0;t<MasterPointContainer.size();++t)
01434                 {
01435                     InterpolationPointsMaster->SetValue(t+1,MasterPointContainer[t].first);
01436                 }
01437                 for (unsigned int t=0;t<SlavePointContainer.size();++t)
01438                 {
01439                     InterpolationPointsSlave->SetValue(t+1,SlavePointContainer[t]);
01440                 }
01441 
01442                 /*CheckPoints(InterpolationPointsMaster);*/
01443                 /*CheckPoints(InterpolationPointsSlave);*/
01444 
01445                 m_all_offset_cuts_high.push_back(InterpolateOrderedPoints(InterpolationPointsMaster,true));
01446                 m_all_offset_cuts_low.push_back(InterpolateOrderedPoints(InterpolationPointsSlave,true));
01447                 //Store the last point
01448                 lastPoint = MasterPointContainer.rbegin()->first;
01449                 //SlaveTool Path finished
01450             }//Current Curve < last curve is finished here
01451         }
01452         if (fabs(m_ordered_cuts_it->first-(m_ordered_cuts_it-1)->first)<=0.01)
01453         {
01454             //we only set the new flat level wire here
01455             //no Toolpath is calculated
01456             current_flat_level = m_ordered_cuts_it;
01457         }//end of current == last
01458         if (m_ordered_cuts_it->first>(m_ordered_cuts_it-1)->first)
01459         {
01460             //The Slave Tool is now the Master Tool and therefore we only have to exchange < case
01461             //Check if current Level has got a Wire
01462             if (m_ordered_cuts_it->second.ShapeType() == TopAbs_WIRE)
01463             {
01464                 WireExplorer aWireExplorer(TopoDS::Wire(m_ordered_cuts_it->second));
01465                 for (aWireExplorer.Init();aWireExplorer.More();aWireExplorer.Next())
01466                 {
01467                     BRepAdaptor_Curve curveAdaptor(aWireExplorer.Current());
01468                     GCPnts_QuasiUniformAbscissa aProp(curveAdaptor,100);
01469                     for (int i=1;i<=aProp.NbPoints();++i)
01470                     {
01471                         std::pair<gp_Pnt,double> aTempPair;
01472                         //Check the direction
01473                         if (aWireExplorer.Current().Orientation() != TopAbs_REVERSED)
01474                             curveAdaptor.D0(aProp.Parameter(i),aTempPair.first);
01475                         else curveAdaptor.D0(aProp.Parameter(aProp.NbPoints()-i+1),aTempPair.first);
01476                         aTempPair.first.SetZ(aTempPair.first.Z() -m_UserSettings.slave_radius -m_UserSettings.sheet_thickness);
01477                         aTempPair.second = 0.0; //Initialize of Angle
01478                         //checken ob der neue Punkt zu nahe am alten ist. Wenn ja, dann kein push_back
01479                         if (MasterPointContainer.size()>0 && (MasterPointContainer.rbegin()->first.SquareDistance(aTempPair.first)>(Precision::Confusion()*Precision::Confusion())))
01480                         {
01481                             MasterPointContainer.push_back(aTempPair);
01482                             anoutput1 << aTempPair.first.X() <<","<< aTempPair.first.Y() <<","<< aTempPair.first.Z()<<std::endl;
01483                             aTempPair.first.SetZ(aTempPair.first.Z() + m_UserSettings.master_radius + m_UserSettings.slave_radius + m_UserSettings.sheet_thickness);
01484                             SlavePointContainer.push_back(aTempPair.first);
01485                             anoutput2 << aTempPair.first.X() <<","<< aTempPair.first.Y() <<","<< aTempPair.first.Z()<<std::endl;
01486                         }
01487                         else if (MasterPointContainer.empty())
01488                         {
01489                             MasterPointContainer.push_back(aTempPair);
01490                             anoutput1 << aTempPair.first.X() <<","<< aTempPair.first.Y() <<","<< aTempPair.first.Z()<<std::endl;
01491                             aTempPair.first.SetZ(aTempPair.first.Z() + m_UserSettings.master_radius + m_UserSettings.slave_radius + m_UserSettings.sheet_thickness);
01492                             SlavePointContainer.push_back(aTempPair.first);
01493                             anoutput2 << aTempPair.first.X() <<","<< aTempPair.first.Y() <<","<< aTempPair.first.Z()<<std::endl;
01494                         }
01495                     }
01496                     //Now Interpolate the Points only if we have a non-continuous edge or if we are finished
01497                     //with all edges
01498                     bool tangency = true;
01499                     //If there are more Edges in the wire
01500                     if (aWireExplorer.MoreEdge())
01501                     {
01502                         tangency = CheckEdgeTangency(aWireExplorer.Current(),aWireExplorer.NextEdge());
01503                         if (!tangency)
01504                         {
01505                             //Store all the PointClouds in a StorageVector to arrange the Robot-Movement afterwards
01506                             MasterPointsStorage.push_back(MasterPointContainer);
01507                             SlavePointsStorage.push_back(SlavePointContainer);
01508                             MasterPointContainer.clear();
01509                             SlavePointContainer.clear();
01510                         }
01511                         else continue;
01512                     }
01513                     else
01514                     {
01515                         MasterPointsStorage.push_back(MasterPointContainer);
01516                         SlavePointsStorage.push_back(SlavePointContainer);
01517                         MasterPointContainer.clear();
01518                         SlavePointContainer.clear();
01519                     }
01520                 }
01521                 //Now check the point-cloud with the shortest distance to "lastPoint"
01522                 int start_index = 0,start_array=0;
01523                 CheckforLastPoint(lastPoint,start_index,start_array,MasterPointsStorage);
01524                 //Now Interpolate the PointClouds...Cloud by Cloud
01525                 //First we have to divide the first PointCloud as it is for sure that we start
01526                 //Somewhere in the middle of it. We will then insert the points at the current start
01527                 if (MasterPointsStorage.size() == 1) //If we have only one PointCloud
01528                 {
01529                     bool first = true;
01530                     for (unsigned int i=start_index;i<MasterPointsStorage.begin()->size();i++)
01531                     {
01532                         //We skip the Endpoint as it may be the same point as the start point
01533                         if (i+1 == MasterPointsStorage.begin()->size())
01534                         {
01535                             i=-1;
01536                             first = false;
01537                             continue;
01538                         }
01539                         MasterPointContainer.push_back(MasterPointsStorage[0][i]);
01540                         SlavePointContainer.push_back(SlavePointsStorage[0][i]);
01541                         if (!first && i == start_index)
01542                             break;
01543                     }
01544                     //Now lets interpolate the Point Cloud
01545                     Handle(TColgp_HArray1OfPnt) InterpolationPointsMaster = new TColgp_HArray1OfPnt(1, MasterPointContainer.size());
01546                     Handle(TColgp_HArray1OfPnt) InterpolationPointsSlave = new TColgp_HArray1OfPnt(1, SlavePointContainer.size());
01547                     for (unsigned int t=0;t<MasterPointContainer.size();++t)
01548                     {
01549                         InterpolationPointsMaster->SetValue(t+1,MasterPointContainer[t].first);
01550                         InterpolationPointsSlave->SetValue(t+1,SlavePointContainer[t]);
01551                     }
01552                     m_all_offset_cuts_low.push_back(InterpolateOrderedPoints(InterpolationPointsMaster,true));
01553                     m_all_offset_cuts_high.push_back(InterpolateOrderedPoints(InterpolationPointsSlave,true));
01554                     //Store the last point
01555                     lastPoint = MasterPointContainer.rbegin()->first;
01556                 }
01557                 else
01558                 {
01559                     anIterator1 = SlavePointsStorage.begin();
01560                     anIterator2 = MasterPointsStorage.begin();
01561                     MasterPointContainer.clear();
01562                     SlavePointContainer.clear();
01563                     for (int i=0;i<=start_index;i++)
01564                     {
01565                         MasterPointContainer.push_back(MasterPointsStorage[start_array][i]);
01566                         SlavePointContainer.push_back(SlavePointsStorage[start_array][i]);
01567                     }
01568                     MasterPointsStorage.insert((anIterator2+start_array+1),MasterPointContainer);
01569                     SlavePointsStorage.insert((anIterator1+start_array+1),SlavePointContainer);
01570                     MasterPointContainer.clear();
01571                     SlavePointContainer.clear();
01572                     //Reinitialize the Iterators
01573                     anIterator1 = SlavePointsStorage.begin();
01574                     anIterator2 = MasterPointsStorage.begin();
01575                     for (unsigned int i=start_index;i<MasterPointsStorage[start_array].size();i++)
01576                     {
01577                         MasterPointContainer.push_back(MasterPointsStorage[start_array][i]);
01578                         SlavePointContainer.push_back(SlavePointsStorage[start_array][i]);
01579                     }
01580                     MasterPointsStorage.insert((anIterator2+start_array+2),MasterPointContainer);
01581                     SlavePointsStorage.insert((anIterator1+start_array+2),SlavePointContainer);
01582                     //Reinitialize the Iterators
01583                     anIterator1 = SlavePointsStorage.begin();
01584                     anIterator2 = MasterPointsStorage.begin();
01585                     //Delete the Original PointCloud
01586                     MasterPointsStorage.erase(anIterator2+start_array);
01587                     SlavePointsStorage.erase(anIterator1+start_array);
01588                     MasterPointContainer.clear();
01589                     SlavePointContainer.clear();
01590                     //Now lets interpolate the Point Clouds
01591                     //Start at start_array+1 as the insert operations used us to do it like that
01592                     for (unsigned int j=start_array+1;j<MasterPointsStorage.size();++j)
01593                     {
01594                         Handle(TColgp_HArray1OfPnt) InterpolationPointsMaster = new TColgp_HArray1OfPnt(1, MasterPointsStorage[j].size());
01595                         Handle(TColgp_HArray1OfPnt) InterpolationPointsSlave = new TColgp_HArray1OfPnt(1, SlavePointsStorage[j].size());
01596                         for (unsigned int t=0;t<MasterPointsStorage[j].size();++t)
01597                         {
01598                             InterpolationPointsMaster->SetValue(t+1,MasterPointsStorage[j][t].first);
01599                             InterpolationPointsSlave->SetValue(t+1,SlavePointsStorage[j][t]);
01600                         }
01601                         m_all_offset_cuts_low.push_back(InterpolateOrderedPoints(InterpolationPointsMaster,true));
01602                         m_all_offset_cuts_high.push_back(InterpolateOrderedPoints(InterpolationPointsSlave,true));
01603                         if (j+1==MasterPointsStorage.size())
01604                         {
01605                             j=-1;
01606                             continue;
01607                         }
01608                         if (j+1==start_array+1)
01609                             break;
01610                     }
01611                     lastPoint = MasterPointsStorage[start_array].rbegin()->first;
01612                 }
01613             }
01614             else //If the current Curve is no Wire (Mode >)
01615             {
01616                 Edgesort aCutShapeSorter(m_ordered_cuts_it->second);
01617                 for (aCutShapeSorter.Init();aCutShapeSorter.More();aCutShapeSorter.Next())
01618                 {
01619                     //Get the PCurve and the GeomSurface
01620                     Handle_Geom2d_Curve a2DCurve;
01621                     Handle_Geom_Surface aSurface;
01622                     TopLoc_Location aLoc;
01623                     TopoDS_Edge anEdge;
01624                     double first2,last2;
01625                     bool reversed = false;
01626                     BRep_Tool::CurveOnSurface(aCutShapeSorter.Current(),a2DCurve,aSurface,aLoc,first2,last2);
01627                     //Jetzt noch die resultierende Surface und die Curve sauber drehen
01628                     //(vielleicht wurde ja das TopoDS_Face irgendwie gedreht oder die TopoDS_Edge)
01629                     if (aCutShapeSorter.Current().Orientation() == TopAbs_REVERSED)
01630                         reversed = true;
01631 
01632                     BRepAdaptor_Curve aCurveAdaptor(aCutShapeSorter.Current());
01633                     GCPnts_QuasiUniformAbscissa aPointGenerator(aCurveAdaptor,200);
01634                     int PointSize = aPointGenerator.NbPoints();
01635                     //Now get the surface normal to the generated points
01636                     for (int i=1;i<=PointSize;++i)
01637                     {
01638                         std::pair<gp_Pnt,double> PointContactPair;
01639                         gp_Pnt2d a2dParaPoint;
01640                         gp_Pnt aSurfacePoint;
01641                         TopoDS_Face aFace;
01642                         gp_Vec Uvec,Vvec,normalVec;
01643                         //If the curve is reversed we also have to reverse the point direction
01644                         if (reversed) a2DCurve->D0(aPointGenerator.Parameter(PointSize-i+1),a2dParaPoint);
01645                         else a2DCurve->D0(aPointGenerator.Parameter(i),a2dParaPoint);
01646                         GeomAdaptor_Surface aGeom_Adaptor(aSurface);
01647                         int t = aGeom_Adaptor.GetType();
01648                         aGeom_Adaptor.D1(a2dParaPoint.X(),a2dParaPoint.Y(),aSurfacePoint,Uvec,Vvec);
01649                         //Jetzt den Normalenvector auf die Fläche ausrechnen
01650                         normalVec = Uvec;
01651                         normalVec.Cross(Vvec);
01652                         normalVec.Normalize();
01653                         //Jetzt ist die Normale berechnet und auch normalisiert
01654                         //Jetzt noch checken ob die Normale auch wirklich auf die saubere Seite zeigt
01655                         //dazu nur checken ob der Z-Wert der Normale größer Null ist (dann im 1.und 2. Quadranten)
01656                         if (normalVec.Z()<0) normalVec.Multiply(-1.0);
01657 
01658                         //Mal kurz den Winkel zur Grund-Ebene ausrechnen
01659                         gp_Vec planeVec(normalVec.X(),normalVec.Y(),0.0);
01660                         //Den Winkel
01661                         PointContactPair.second = normalVec.Angle(planeVec);
01662                         gp_Vec NormalVecSlave = normalVec;
01663                         gp_Pnt SlavePoint;
01664                         //Jetzt die Z-Komponente auf 0 setzen
01665                         //normalVec.SetZ(0.0);
01666                         normalVec.Normalize();
01667                         //Jetzt die Normale mit folgender Formel multiplizieren für den Master
01668                         //double multiply = (m_UserSettings.slave_radius*(1-sin(PointContactPair.second))/cos(PointContactPair.second))+m_UserSettings.sheet_thickness;
01669                         double multiply = m_UserSettings.slave_radius + m_UserSettings.sheet_thickness;
01670                         //As the Master is now the Slave we have to multiply it also by -1.0
01671                         normalVec.Multiply(-multiply);
01672                         //und hier für den Slave
01673                         NormalVecSlave.Normalize();
01674                         multiply = m_UserSettings.master_radius;
01675                         NormalVecSlave.Multiply(multiply);
01676                         //Jetzt den OffsetPunkt berechnen
01677                         PointContactPair.first.SetXYZ(aSurfacePoint.XYZ() + normalVec.XYZ());
01678                         SlavePoint.SetXYZ(aSurfacePoint.XYZ() + NormalVecSlave.XYZ());
01679                         //PointContactPair.first.SetZ(PointContactPair.first.Z() - m_UserSettings.slave_radius);
01680                         //Damit wir keine Punkte bekommen die zu nahe beieinander liegen
01681                         //Den letzten hinzugefügten Punkt suchen
01682                         if (MasterPointContainer.size()>0 && (MasterPointContainer.rbegin()->first.SquareDistance(PointContactPair.first)>(Precision::Confusion()*Precision::Confusion())))
01683                         {
01684                             MasterPointContainer.push_back(PointContactPair);
01685                             SlavePointContainer.push_back(SlavePoint);
01686                             anoutput1 << PointContactPair.first.X() <<","<< PointContactPair.first.Y() <<","<< PointContactPair.first.Z()<<std::endl;
01687                             anoutput2 << SlavePoint.X() <<","<< SlavePoint.Y() <<","<< SlavePoint.Z()<<std::endl;
01688                         }
01689                         else if (MasterPointContainer.empty())
01690                         {
01691                             MasterPointContainer.push_back(PointContactPair);
01692                             SlavePointContainer.push_back(SlavePoint);
01693                             anoutput1 << PointContactPair.first.X() <<","<< PointContactPair.first.Y() <<","<< PointContactPair.first.Z()<<std::endl;
01694                             anoutput2 << SlavePoint.X() <<","<< SlavePoint.Y() <<","<< SlavePoint.Z()<<std::endl;
01695                         }
01696                     }
01697                 }
01698                 //Before we Output anything we check if the lowest Coordinate can still touch the "currently" highest flat area and if yes, we have to adapt the Slave toolpath
01699                 for (unsigned int k=0;k<SlavePointContainer.size();++k)
01700                 {
01701                     if ((SlavePointContainer[k].Z()-m_UserSettings.master_radius)<(current_flat_level->first))
01702                     {
01703                         slave_is_wire = true;
01704                         TopoDS_Wire aWire = TopoDS::Wire(current_flat_level->second);
01705                         BRepAdaptor_CompCurve2 wireAdaptor(aWire);
01706                         GCPnts_QuasiUniformAbscissa aProp(wireAdaptor,1000);
01707                         SlavePointContainer.clear();
01708                         for (int i=1;i<=aProp.NbPoints();++i)
01709                         {
01710                             gp_Pnt SlaveOffsetPoint;
01711                             wireAdaptor.D0(aProp.Parameter(i),SlaveOffsetPoint);
01712                             SlaveOffsetPoint.SetZ(SlaveOffsetPoint.Z() + m_UserSettings.master_radius);
01713                             //checken ob der neue Punkt zu nahe am alten ist. Wenn ja, dann kein push_back
01714                             if (SlavePointContainer.size()>0 && (SlavePointContainer.rbegin()->SquareDistance(SlaveOffsetPoint)>(0.001)))
01715                             {
01716                                 SlavePointContainer.push_back(SlaveOffsetPoint);
01717                                 anoutput2 << SlaveOffsetPoint.X() <<","<< SlaveOffsetPoint.Y() <<","<< SlaveOffsetPoint.Z()<<std::endl;
01718                             }
01719                             else if (SlavePointContainer.empty())
01720                             {
01721                                 SlavePointContainer.push_back(SlaveOffsetPoint);
01722                                 anoutput2 << SlaveOffsetPoint.X() <<","<< SlaveOffsetPoint.Y() <<","<< SlaveOffsetPoint.Z()<<std::endl;
01723                             }
01724                         }
01725                         break;
01726                     }
01727                 }
01728                 MasterPointsStorage.push_back(MasterPointContainer);
01729                 SlavePointsStorage.push_back(SlavePointContainer);
01730                 int start_index_master = 0,start_array_master=0,start_index_slave=0,start_array_slave=0;
01731                 CheckforLastPoint(lastPoint,start_index_master,start_array_master,start_index_slave,start_array_slave,MasterPointsStorage,SlavePointsStorage);
01732                 //If the Slave is a Wire 'slave_is_wire ==true' then we have to take care of two independent point clouds
01733                 if (!slave_is_wire)
01734                 {
01735                     //First we have to divide the first PointCloud as it is for sure that we start
01736                     //Somewhere in the middle of it. We will then insert the points at the current start
01737                     MasterPointContainer.clear();
01738                     SlavePointContainer.clear();
01739                     bool first =  true;
01740                     for (unsigned int i=start_index_master;i<MasterPointsStorage.begin()->size();i++)
01741                     {
01742                         if (i+1 == MasterPointsStorage.begin()->size())
01743                         {
01744                             i=-1;
01745                             first = false;
01746                             continue;
01747                         }
01748                         MasterPointContainer.push_back(MasterPointsStorage[0][i]);
01749                         SlavePointContainer.push_back(SlavePointsStorage[0][i]);
01750                         if (!first && i == start_index_master)
01751                             break;
01752                     }
01753 
01754                 }
01755                 else //if slave is a wire
01756                 {
01757                     //Now check the point-cloud with the shortest distance to "lastPoint"
01758                     //As the Master and the slave have different number of points we have to do it two times now
01759                     //First we have to divide the first PointCloud as it is for sure that we start
01760                     //Somewhere in the middle of it. We will then insert the points at the current start
01761                     MasterPointContainer.clear();
01762                     SlavePointContainer.clear();
01763                     bool first = true;
01764                     for (unsigned int i=start_index_master;i<MasterPointsStorage.begin()->size();i++)
01765                     {
01766                         //We skip the Endpoint as it may be the same point as the start point
01767                         if (i+1 == MasterPointsStorage.begin()->size())
01768                         {
01769                             i=-1;
01770                             first = false;
01771                             continue;
01772                         }
01773                         MasterPointContainer.push_back(MasterPointsStorage[0][i]);
01774                         if (!first && i== start_index_master)
01775                             break;
01776                     }
01777                     for (unsigned int i=start_index_slave;i<SlavePointsStorage.begin()->size();i++)
01778                     {
01779                         //We skip the Endpoint as it may be the same point as the start point
01780                         if (i+1 == SlavePointsStorage.begin()->size())
01781                         {
01782                             i=-1;
01783                             first = false;
01784                             continue;
01785                         }
01786                         SlavePointContainer.push_back(SlavePointsStorage[0][i]);
01787                         if (!first && i == start_index_slave)
01788                             break;
01789                     }
01790                 }
01791                 //Now lets interpolate the Point Cloud
01792                 Handle(TColgp_HArray1OfPnt) InterpolationPointsMaster = new TColgp_HArray1OfPnt(1, MasterPointContainer.size());
01793                 Handle(TColgp_HArray1OfPnt) InterpolationPointsSlave = new TColgp_HArray1OfPnt(1, SlavePointContainer.size());
01794                 for (unsigned int t=0;t<MasterPointContainer.size();++t)
01795                 {
01796                     InterpolationPointsMaster->SetValue(t+1,MasterPointContainer[t].first);
01797                 }
01798                 for (unsigned int t=0;t<SlavePointContainer.size();++t)
01799                 {
01800                     InterpolationPointsSlave->SetValue(t+1,SlavePointContainer[t]);
01801                 }
01802 
01803                 /*CheckPoints(InterpolationPointsMaster);*/
01804                 /*CheckPoints(InterpolationPointsSlave);*/
01805 
01806                 m_all_offset_cuts_low.push_back(InterpolateOrderedPoints(InterpolationPointsMaster,true));
01807                 m_all_offset_cuts_high.push_back(InterpolateOrderedPoints(InterpolationPointsSlave,true));
01808                 //Store the last point
01809                 lastPoint = MasterPointContainer.rbegin()->first;
01810             }//Current Curve > last curve is finished here
01811         }
01812     }
01813     return true;
01814 }
01815 
01816 
01817 bool cutting_tools::CheckPoints(Handle(TColgp_HArray1OfPnt) PointArray)
01818 {
01819     Standard_Integer ii ;
01820     Standard_Real tolerance_squared = Precision::Confusion() * Precision::Confusion(),
01821                                       distance_squared ;
01822     Standard_Boolean result = Standard_True ;
01823     for (ii = PointArray->Lower() ; result && ii < PointArray->Upper() ; ii++)
01824     {
01825         distance_squared = PointArray->Value(ii).SquareDistance(PointArray->Value(ii+1)) ;
01826         if (distance_squared < tolerance_squared)
01827         {
01828             return false;
01829         }
01830 
01831     }
01832     return true;
01833 
01834 }
01835 Base::BoundBox3f cutting_tools::getWireBBox(TopoDS_Wire aWire)
01836 {
01837     //Fill Bounding Boxes with Wires
01838     //Therefore we have to evaluate some points on our wire and feed the BBox Algorithm
01839     Base::BoundBox3f currentBox;
01840     BRepAdaptor_CompCurve2 wireAdaptor(aWire);
01841     GCPnts_QuasiUniformDeflection aProp(wireAdaptor,0.1);
01842     Base::Vector3f aPoint;
01843     currentBox.Flush();
01844     for (int j=1;j<=aProp.NbPoints();++j)
01845     {
01846         aPoint.x = float(aProp.Value(j).X());
01847         aPoint.y = float(aProp.Value(j).Y());
01848         aPoint.z = float(aProp.Value(j).Z());
01849         currentBox.Add(aPoint);
01850     }
01851     return currentBox;
01852 }
01853 
01854 TopoDS_Shape cutting_tools::getProperCut(TopoDS_Shape& aShape)
01855 {
01856     //A cutting Shape is coming as aShape
01857     //check direction to decide which Topology to hold and which to delete
01858     if (m_direction)//From top to bottom
01859     {
01860 
01861     }
01862     TopoDS_Shape aReturnShape;
01863     return aReturnShape;
01864 }
01865 
01866 bool cutting_tools::calculateAccurateSlaveZLevel(std::vector<std::pair<gp_Pnt,double> >& OffsetPoints, double current_z_level, double &slave_z_level, double &average_sheet_thickness, double &average_angle, bool &cutpos)
01867 {
01868     //Mittelwert von allen Normalenwinkeln und damit dann den Mittelwert der Blechdicke bilden
01869 
01870     bool direction,area;
01871     //Zunächst checken in welchem Bereich vom Teil wir uns aufhalten
01872     if (current_z_level < m_MachiningOrder[0].first.z && current_z_level > m_MachiningOrder[1].first.z)
01873     {
01874         //Wir sind von oben nach unten im ersten Teil
01875         direction = true;
01876         area = true;
01877     }
01878     else if (m_MachiningOrder.size() > 2 && current_z_level < m_MachiningOrder[1].first.z)
01879     {
01880         //Wir sind von oben nach unten im zweiten Teil
01881         direction = true;
01882         area = false;
01883     }
01884     else if (m_MachiningOrder.size() > 2 && current_z_level < m_MachiningOrder[2].first.z && current_z_level > m_MachiningOrder[1].first.z)
01885     {
01886         //Wir sind von unten nach oben im 2. Teil
01887         direction = false;
01888         area = false;
01889 
01890     }
01891     else
01892     {
01893         cout << "Konnte keine Zuordnung finden" << endl;
01894     }
01895 
01896     average_angle = 0.0;
01897     double slave_z_leveltop,slave_z_levelbottom;
01898 
01899     for (unsigned int i=0;i<OffsetPoints.size();++i)
01900     {
01901         average_angle = average_angle + OffsetPoints[i].second;
01902     }
01903 
01904     average_angle = average_angle/OffsetPoints.size();
01905     //Average Sheet thickness based on sin-law
01906     average_sheet_thickness = m_UserSettings.sheet_thickness * sin ((PI/2)-average_angle);
01907 
01908 
01909     slave_z_leveltop = current_z_level + \
01910                        (m_UserSettings.master_radius*(1-sin(average_angle))) - \
01911                        (sin(average_angle)*(average_sheet_thickness+m_UserSettings.slave_radius)) + \
01912                        ((average_sheet_thickness+m_UserSettings.slave_radius)/cos(average_angle));
01913 
01914     slave_z_levelbottom = current_z_level - ( m_UserSettings.master_radius + \
01915                           m_UserSettings.slave_radius + \
01916                           average_sheet_thickness) * \
01917                           sin(average_angle) - \
01918                           m_UserSettings.master_radius;
01919 
01920     if (direction && area && slave_z_leveltop < (m_MachiningOrder[0].first.z - m_UserSettings.sheet_thickness))
01921     {
01922         slave_z_level = slave_z_leveltop;
01923         cutpos = true;
01924         return true;
01925     }
01926     else if (direction && area && slave_z_leveltop > (m_MachiningOrder[0].first.z-m_UserSettings.sheet_thickness))
01927     {
01928         if ((slave_z_levelbottom + m_UserSettings.slave_radius) < (m_MachiningOrder[0].first.z - m_UserSettings.sheet_thickness))
01929         {
01930             slave_z_level = slave_z_levelbottom;
01931             cutpos = false;
01932             return true;
01933         }
01934         else
01935         {
01936             slave_z_level = m_MachiningOrder[0].first.z;
01937             return true;
01938         }
01939     }
01940     //Die oberste Ebene ist hier abgehakt
01941     if (direction && !area && slave_z_leveltop < (m_MachiningOrder[1].first.z - m_UserSettings.sheet_thickness))
01942     {
01943         slave_z_level = slave_z_leveltop;
01944         cutpos = true;
01945         return true;
01946     }
01947     else if (direction && !area && slave_z_leveltop > (m_MachiningOrder[1].first.z-m_UserSettings.sheet_thickness))
01948     {
01949         if ((slave_z_levelbottom + m_UserSettings.slave_radius) < (m_MachiningOrder[1].first.z - m_UserSettings.sheet_thickness))
01950         {
01951             slave_z_level = slave_z_levelbottom;
01952             cutpos = false;
01953             return true;
01954         }
01955         else
01956         {
01957             slave_z_level = m_MachiningOrder[1].first.z;
01958             return true;
01959         }
01960     }
01961     //Jetzt noch die Geschichte wo wir wieder nach oben fahren
01962     if (!direction && !area && slave_z_leveltop < (m_MachiningOrder[1].first.z - m_UserSettings.sheet_thickness))
01963     {
01964         slave_z_level = slave_z_leveltop;
01965         cutpos = true;
01966         return true;
01967     }
01968     else if (direction && !area && slave_z_leveltop > (m_MachiningOrder[2].first.z-m_UserSettings.sheet_thickness))
01969     {
01970         if ((slave_z_levelbottom + m_UserSettings.slave_radius) < (m_MachiningOrder[2].first.z - m_UserSettings.sheet_thickness))
01971         {
01972             slave_z_level = slave_z_levelbottom;
01973             cutpos = false;
01974             return true;
01975         }
01976         else
01977         {
01978             slave_z_level = m_MachiningOrder[2].first.z;
01979             return true;
01980         }
01981     }
01982 
01983     return  true;
01984 }
01985 
01986 //bool cutting_tools::OffsetWires() //Hier ist die alte Version
01987 //{
01988 // for(m_it = m_all_cuts.begin();m_it<m_all_cuts.end();++m_it)
01989 // {
01990 //  // make your wire looks like a curve to other algorithm and generate Points to offset the curve
01991 //  BRepAdaptor_CompCurve2 wireAdaptor((*m_it).second);
01992 //  GCPnts_QuasiUniformDeflection aProp(wireAdaptor,0.001);
01993 //  int numberofpoints = aProp.NbPoints();
01994 //  Handle(TColgp_HArray1OfPnt) finalOffsetPoints = new TColgp_HArray1OfPnt(1, numberofpoints);
01995 //  //Now project the points to the surface. As we might have many faces just project to every face and take the min distance
01996 //  for (int i=1;i<=numberofpoints;++i)
01997 //  {
01998 //   TopExp_Explorer ExShape;
01999 //   ExShape.Init(m_Shape,TopAbs_FACE);
02000 //   Standard_Real Umin,Vmin;
02001 //   double distance_old,distance;
02002 //   Handle_Geom_Surface nearest_surface;
02003 //   distance_old = 200.0;
02004 //   for (; ExShape.More(); ExShape.Next())
02005 //   {
02006 //    const TopoDS_Face &atopo_surface =  TopoDS::Face (ExShape.Current());
02007 //    Handle_Geom_Surface geom_surface = BRep_Tool::Surface(atopo_surface);
02008 //    gp_Pnt currentPoint = aProp.Value(i);
02009 //    GeomAPI_ProjectPointOnSurf aPPS(currentPoint,geom_surface,0.001);
02010 //    if (! aPPS.IsDone())
02011 //    {
02012 //     return false;
02013 //    }
02014 //    distance = aPPS.LowerDistance();
02015 //    if(distance<distance_old)
02016 //    {
02017 //     distance_old = distance;
02018 //     aPPS.LowerDistanceParameters (Umin,Vmin);
02019 //     nearest_surface = geom_surface;
02020 //    }
02021 //   }
02022 //   gp_Pnt projectedPoint,OffsetPoint;
02023 //   gp_Vec Uvec,Vvec,normalVec,projPointVec;
02024 //   nearest_surface->D1(Umin,Vmin,projectedPoint,Uvec,Vvec);
02025 //   normalVec = Uvec;
02026 //   normalVec.Cross(Vvec);
02027 //   normalVec.Normalize(); //Jetzt ist die Normale berechnet und auch normalisiert
02028 //   //zeroPoint.SetCoord(0.0,0.0,0.0); //
02029 //   projPointVec.SetXYZ(projectedPoint.XYZ());
02030 //   OffsetPoint.SetXYZ((projPointVec + (normalVec*(-21))).XYZ());
02031 //   finalOffsetPoints->SetValue(i,OffsetPoint); //Aktuellen OffsetPoint setzen
02032 //  }
02033 //  Standard_Boolean isPeriodic = Standard_False;
02034 //  GeomAPI_Interpolate aNoPeriodInterpolate(finalOffsetPoints, isPeriodic, Precision::Confusion());
02035 //  aNoPeriodInterpolate.Perform();
02036 //  Handle_Geom_BSplineCurve aCurve(aNoPeriodInterpolate.Curve());
02037 //
02038 //  // check results
02039 //  if (!aNoPeriodInterpolate.IsDone()) return false;
02040 //  m_all_offset_cuts_high.push_back(aCurve);
02041 // }
02042 //}
02043 
02044 gp_Dir cutting_tools::getPerpendicularVec(gp_Vec& anInput)
02045 {
02046     double x,y;
02047     gp_Dir Output;
02048     x = anInput.X();
02049     y = anInput.Y();
02050     if (x != 0.0 && y != 0.0)
02051     {
02052         Output.SetCoord(1.0,(-x/y),0.0);
02053     }
02054     else if (x == 0 && y == 0)
02055     {
02056         Output.SetCoord(1.0,1.0,0.0);
02057     }
02058     else if (x == 0 && y != 0)
02059     {
02060         Output.SetCoord(1.0,0.0,0.0);
02061     }
02062     else if (x != 0 && y == 0)
02063     {
02064         Output.SetCoord(0.0,1.0,0.0);
02065     }
02066     return Output;
02067 }
02068 
02069 
02070 
02071 bool cutting_tools::OffsetWires_Spiral()
02072 {
02073     std::ofstream anoutput1;
02074     anoutput1.open("c:/spiral.txt");
02075     Base::Builder3D log;
02076     std::vector<std::pair<float,TopoDS_Shape> >::iterator current_flat_level;
02077     current_flat_level = m_ordered_cuts.begin();
02078     SpiralHelper lastPoint;
02079     lastPoint.SurfacePoint.SetCoord(0.0,0.0,0.0);
02080     bool slave_done= false; //Necessary if the slave is already output
02081     bool just_started = true; //
02082     gp_Vec direction_vector(0.0,0.0,1.0),last_direction_vector(0.0,0.0,1.0);//Just to initialize them
02083     bool direction = true; //for the Robot, this tells the algo that we have to switch the direction
02084     //Nicht beim höchsten Anfangen, da wir den nicht mit dem Master fahren wollen
02085     for (m_ordered_cuts_it = m_ordered_cuts.begin()+1;m_ordered_cuts_it!=m_ordered_cuts.end();++m_ordered_cuts_it)
02086     {
02087         std::vector<SpiralHelper> OffsetSpiralPoints,TempSpiralPoints;
02088         std::vector<gp_Pnt> SlavePointContainer;
02089         OffsetSpiralPoints.clear();
02090         TempSpiralPoints.clear();
02091 
02092         //Now we have to select which strategy to choose
02093         //if the current levels is bigger,the same, or less then the previous one
02094         if (m_ordered_cuts_it->first<(m_ordered_cuts_it-1)->first)
02095         {
02096             //Master is calculated as Usual, Slave stays at the currently highest level
02097             //Check if Last Level has got a Wire as we go from the last to the current with our Spiral
02098             SpiralHelper aSpiralStruct;
02099             double CurveLength = 0.0;
02100             if ((m_ordered_cuts_it-1)->second.ShapeType() == TopAbs_WIRE)
02101             {
02102                 WireExplorer aWireExplorer(TopoDS::Wire((m_ordered_cuts_it-1)->second));
02103                 for (aWireExplorer.Init();aWireExplorer.More();aWireExplorer.Next())
02104                 {
02105                     CurveLength = CurveLength + GetEdgeLength(aWireExplorer.Current());
02106                     BRepAdaptor_Curve curveAdaptor(aWireExplorer.Current());
02107                     //Adjust the point amount based on the curve length make every 0.3mm a point
02108                     //GCPnts_QuasiUniformAbscissa aProp(curveAdaptor,int(GetEdgeLength(aWireExplorer.Current())/0.4));
02109                     GCPnts_QuasiUniformAbscissa aProp(curveAdaptor,1000);
02110                     for (int i=1;i<=aProp.NbPoints();++i)
02111                     {
02112                         //Check the direction
02113                         if (aWireExplorer.Current().Orientation() != TopAbs_REVERSED)
02114                             curveAdaptor.D1(aProp.Parameter(i),aSpiralStruct.SurfacePoint,aSpiralStruct.LineD1);
02115                         else curveAdaptor.D1(aProp.Parameter(aProp.NbPoints()-i+1),aSpiralStruct.SurfacePoint,aSpiralStruct.LineD1);
02116 
02117                         aSpiralStruct.SurfaceNormal.SetCoord(0.0,0.0,1.0);
02118                         TempSpiralPoints.push_back(aSpiralStruct);
02119                     }
02120                 }
02121             }
02122             else
02123             {
02124                 CurveLength = 0.0;
02125                 Edgesort aCutShapeSorter((m_ordered_cuts_it-1)->second);
02126                 for (aCutShapeSorter.Init();aCutShapeSorter.More();aCutShapeSorter.Next())
02127                 {
02128                     CurveLength = CurveLength + GetEdgeLength(aCutShapeSorter.Current());
02129                     //Get the PCurve and the GeomSurface
02130                     Handle_Geom2d_Curve a2DCurve;
02131                     Handle_Geom_Surface aSurface;
02132                     TopLoc_Location aLoc;
02133                     double first2,last2;
02134                     bool reversed = false;
02135                     BRep_Tool::CurveOnSurface(aCutShapeSorter.Current(),a2DCurve,aSurface,aLoc,first2,last2);
02136                     //Jetzt noch die resultierende Surface und die Curve sauber drehen
02137                     //(vielleicht wurde ja das TopoDS_Face irgendwie gedreht oder die TopoDS_Edge)
02138                     if (aCutShapeSorter.Current().Orientation() == TopAbs_REVERSED)
02139                         reversed = true;
02140 
02141                     BRepAdaptor_Curve aCurveAdaptor(aCutShapeSorter.Current());
02142                     GCPnts_QuasiUniformAbscissa aPointGenerator(aCurveAdaptor,1000);
02143                     int PointSize = aPointGenerator.NbPoints();
02144                     //Now get the surface normal to the generated points
02145                     for (int i=1;i<=PointSize;++i)
02146                     {
02147                         gp_Pnt2d a2dParaPoint;
02148                         gp_Pnt aSurfacePoint;
02149                         TopoDS_Face aFace;
02150                         gp_Vec Uvec,Vvec,normalVec;
02151                         //If the curve is reversed we also have to reverse the point direction
02152                         if (reversed)
02153                         {
02154                             a2DCurve->D0(aPointGenerator.Parameter(PointSize-i+1),a2dParaPoint);
02155                             aCurveAdaptor.D1(aPointGenerator.Parameter(PointSize-i+1),aSurfacePoint,aSpiralStruct.LineD1);
02156                         }
02157                         else
02158                         {
02159                             a2DCurve->D0(aPointGenerator.Parameter(i),a2dParaPoint);
02160                             aCurveAdaptor.D1(aPointGenerator.Parameter(i),aSurfacePoint,aSpiralStruct.LineD1);
02161                         }
02162                         GeomAdaptor_Surface aGeom_Adaptor(aSurface);
02163                         aGeom_Adaptor.D1(a2dParaPoint.X(),a2dParaPoint.Y(),aSurfacePoint,Uvec,Vvec);
02164                         //Jetzt den Normalenvector auf die Fläche ausrechnen
02165                         normalVec = Uvec;
02166                         normalVec.Cross(Vvec);
02167                         normalVec.Normalize();
02168                         //Jetzt ist die Normale berechnet und auch normalisiert
02169                         //Jetzt noch checken ob die Normale auch wirklich auf die saubere Seite zeigt
02170                         //dazu nur checken ob der Z-Wert der Normale größer Null ist (dann im 1.und 2. Quadranten)
02171                         if (normalVec.Z()<0)
02172                             normalVec.Multiply(-1.0);
02173 
02174                         //Mal kurz den Winkel zur Grund-Ebene ausrechnen
02175                         gp_Vec planeVec(normalVec.X(),normalVec.Y(),0.0);
02176                         //Den Winkel speichern
02177                         float angle = float(normalVec.Angle(planeVec));
02178                         aSpiralStruct.SurfaceNormal = normalVec;
02179                         aSpiralStruct.SurfacePoint = aSurfacePoint;
02180                         TempSpiralPoints.push_back(aSpiralStruct);
02181                     }
02182                 }
02183             }
02184 
02185             //Now we have to find the shortest distance to the lastPoint of the previous spiral.
02186             //At the beginning the lastPoint is the Origin
02187             //This represents our startPoint. If we just started, then we skip this point
02188 
02189             unsigned int start_index = 0,adapted_start_index=0;
02190             float dist,distold = FLT_MAX;
02191             for (unsigned int t=0;t<TempSpiralPoints.size();t++)
02192             {
02193                 dist = float(TempSpiralPoints[t].SurfacePoint.SquareDistance(lastPoint.SurfacePoint));
02194                 if (dist<distold)
02195                 {
02196                     start_index = t;
02197                     distold = dist;
02198                 }
02199             }
02200 
02201             //now we know where to  start at our PointCloud, its the index t
02202 
02203             //Calculate the Slave Toolpath for the current flat area
02204             if (!slave_done)//if we did not calculate the slave toolpath for the current flat area
02205             {
02206                 const TopoDS_Wire &aWire = TopoDS::Wire(current_flat_level->second);
02207                 BRepAdaptor_CompCurve2 wireAdaptor(aWire);
02208                 GCPnts_QuasiUniformAbscissa aProp(wireAdaptor,1000);
02209                 SlavePointContainer.clear();
02210                 gp_Pnt SlaveOffsetPoint;
02211                 for (int i=1;i<=aProp.NbPoints();++i)
02212                 {
02213                     wireAdaptor.D0(aProp.Parameter(i),SlaveOffsetPoint);
02214                     SlaveOffsetPoint.SetZ(SlaveOffsetPoint.Z() - m_UserSettings.sheet_thickness - m_UserSettings.slave_radius);
02215                     //checken ob der neue Punkt zu nahe am alten ist. Wenn ja, dann kein push_back
02216                     if (SlavePointContainer.size()>0 && (SlavePointContainer.rbegin()->SquareDistance(SlaveOffsetPoint)>(Precision::Confusion()*Precision::Confusion())))
02217                         SlavePointContainer.push_back(SlaveOffsetPoint);
02218                     else if (SlavePointContainer.empty())
02219                         SlavePointContainer.push_back(SlaveOffsetPoint);
02220                 }
02221                 //Now Interpolate the Slave with reordered points based on the last point
02222                 int index = 0;
02223                 distold = FLT_MAX;
02224                 for (unsigned int t=0;t<SlavePointContainer.size();t++)
02225                 {
02226                     dist = float(SlavePointContainer[t].SquareDistance(lastPoint.SurfacePoint));
02227                     if (dist<distold)
02228                     {
02229                         index = t;
02230                         distold = dist;
02231                     }
02232                 }
02233                 Handle(TColgp_HArray1OfPnt) InterpolationPoints = new TColgp_HArray1OfPnt(1, SlavePointContainer.size());
02234                 adapted_start_index = start_index+1;
02235                 for (unsigned int t=index+1;t<SlavePointContainer.size();++t)
02236                 {
02237                     InterpolationPoints->SetValue(t+1,SlavePointContainer[t]);
02238                     if (t==index)
02239                         break;
02240                     if (t+1==SlavePointContainer.size())
02241                         t=-1;
02242                 }
02243 
02244                 m_all_offset_cuts_low.push_back(InterpolateOrderedPoints(InterpolationPoints,true));
02245                 slave_done = true;
02246             } //Slave done
02247 
02248             gp_Pnt PreviousPoint = TempSpiralPoints[start_index].SurfacePoint;
02249             //check the current direction we would go
02250             gp_Vec help_Vec(TempSpiralPoints[start_index].SurfacePoint.Coord());
02251             if (!start_index+1>=TempSpiralPoints.size())
02252                 direction_vector = TempSpiralPoints[start_index+1].SurfacePoint.Coord();
02253             else
02254                 direction_vector = TempSpiralPoints[1].SurfacePoint.Coord();//As Start and End-Point are the same
02255             direction_vector.Subtract(help_Vec);
02256             //direction_vector.SetZ(0.0);
02257             direction_vector.Normalize();
02258             direction_vector.Multiply(1.0); //Zum testen bauen wir keinen Offset ein
02259             //switch the Spiral-direction if the clockwise flag is checked and  the
02260             //angle between the last and current round is more then 90°
02261             double angle = direction_vector.Angle(last_direction_vector);
02262             if (m_UserSettings.clockwise && angle<(D_PI*0.5))
02263                 direction = true; //We are already in the wright direction
02264             else if (m_UserSettings.clockwise && angle >(D_PI*0.5))
02265                 direction = false; //we have to switch the direction
02266             else if (!m_UserSettings.clockwise && angle<(D_PI*0.5))
02267                 direction = false;
02268             else if (!m_UserSettings.clockwise && angle>(D_PI*0.5))
02269                 direction = true;
02270 
02271 
02272             IntCurvesFace_ShapeIntersector anIntersector;
02273             anIntersector.Load(m_Shape,0.01);
02274 
02275             //Insert the first point into the TempSpiralPoints if we have just started
02276             std::vector<SpiralHelper> TempSpiralPointsFinal;
02277             TempSpiralPointsFinal.clear();
02278             if (!just_started)
02279                 TempSpiralPointsFinal.push_back(lastPoint);
02280             else
02281                 just_started = false;//The first point is now done
02282 
02283             if (direction && ((start_index+1)<TempSpiralPoints.size()))
02284                 adapted_start_index = start_index+1;
02285             else if (direction && ((start_index+1)>=TempSpiralPoints.size()))
02286                 adapted_start_index = 1;//Not 0 because the last one is already added
02287             else
02288             {
02289                 if (start_index==0)
02290                     adapted_start_index = TempSpiralPoints.size()-2; //Skip the last Point as its equal to the first one
02291                 else
02292                     adapted_start_index = start_index-1;
02293             }
02294             std::cout<<"Angle ="<< angle<< " Direction = "<< direction << "Start_Index: "<< adapted_start_index <<","<<start_index<<std::endl;
02295             double distance=0.0;
02296             for (unsigned int j=adapted_start_index;j<TempSpiralPoints.size();++j)
02297             {
02298                 distance = distance + PreviousPoint.Distance(TempSpiralPoints[j].SurfacePoint);
02299                 double delta_z = distance * m_UserSettings.level_distance / CurveLength;
02300                 //we have to store the currentPoint for the distance calculation
02301                 //before we change something at its coordinates
02302                 PreviousPoint = TempSpiralPoints[j].SurfacePoint;
02303 
02304                 TempSpiralPoints[j].SurfacePoint.SetZ(TempSpiralPoints[j].SurfacePoint.Z()-delta_z);
02305                 //before we shoot we check if the z-level is not exactly the same as the next round
02306                 //if (fabs(current_z_value-m_UserSettings.level_distance-TempSpiralPoints[j].SurfacePoint.Z())<=0.04)
02307                 //    break; //We have nearly reached the next z-level, therefore we stop here.
02308                 //Now we have to shoot to get the real Point we want
02309                 //Therefore we have to generate the Direction Vector where to Shoot
02310                 gp_Dir Shooting_Direction = getPerpendicularVec(TempSpiralPoints[j].LineD1);
02311                 gp_Lin aLine(TempSpiralPoints[j].SurfacePoint,Shooting_Direction);
02312                 anIntersector.Perform(aLine,-RealLast(),RealLast());
02313                 if (anIntersector.NbPnt()<=1) //Just to debug
02314                     anIntersector.Perform(aLine,-RealLast(),RealLast());
02315                 //Now we set the real Surface Point
02316                 //How many Points did we get??
02317                 int current_index;
02318                 int points = anIntersector.NbPnt();
02319                 if (points>0)
02320                 {
02321                     float shortestDistance, shortestDistanceOld = FLT_MAX;
02322                     for (int g=1;g<=points;g++)
02323                     {
02324                         const gp_Pnt& TestPoint = anIntersector.Pnt(g);
02325                         shortestDistance = float(TestPoint.SquareDistance(TempSpiralPoints[j].SurfacePoint));
02326                         if (shortestDistance<shortestDistanceOld)
02327                         {
02328                             current_index = g;
02329                             shortestDistanceOld = shortestDistance;
02330                         }
02331                     }
02332                     //Now we check how far the shortest Distance is. If its more then 14mm then we jump to the
02333                     //next Point
02334 
02335                     if (shortestDistanceOld>156)//The point is more then 14mm away (square distance)
02336                         continue;
02337                     TempSpiralPoints[j].SurfacePoint = anIntersector.Pnt(current_index);
02338                 }
02339                 else //We have to try a mesh intersection as the Nurb Intersection does not seem to work
02340                 {
02341                     cout << "Big Probleme";
02342                     continue;
02343                 }
02344                 //Now get the Proper Normal at this point
02345                 BRepAdaptor_Surface aFaceAdaptor(anIntersector.Face(current_index));
02346                 gp_Pnt P;
02347                 gp_Vec U_Vec,V_Vec;
02348                 aFaceAdaptor.D1(anIntersector.UParameter(current_index),anIntersector.VParameter(current_index),P,U_Vec,V_Vec);
02349                 U_Vec.Cross(V_Vec);
02350                 U_Vec.Normalize();
02351                 if (U_Vec.Z() < 0) U_Vec.Multiply(-1.0);
02352 
02353                 TempSpiralPoints[j].SurfaceNormal = U_Vec;
02354                 TempSpiralPointsFinal.push_back(TempSpiralPoints[j]);
02355                 //If we reached the end before we processed all points, then we start at the beginning.
02356                 if (direction)
02357                 {
02358                     if (j==start_index)
02359                         break; //Now we have completed all Points
02360                     else if (j+1==TempSpiralPoints.size())
02361                     {
02362                         j=-1;    //-1 because at the for we ++ the variable directly
02363                         continue;
02364                     }
02365 
02366                 }
02367                 else
02368                 {
02369                     if (j==start_index)
02370                         break; //Now we have completed all Points
02371                     else if (j-1<0)
02372                     {
02373                         j=TempSpiralPoints.size()-3;
02374                         continue;
02375                     }
02376                     //We switch to the end and skip the last point
02377                     //as its the same as the point at j=0;
02378                     j=j-2;//As the for puts +1 for each step
02379                 }
02380             }
02381             //Offset for Master and Slave
02382             OffsetSpiralPoints = OffsetSpiral(TempSpiralPointsFinal);
02383             //Now store the lastPoint of the currentSpiral as we need it for the next one
02384             lastPoint = *(TempSpiralPointsFinal.rbegin());
02385             gp_Vec temp_vector((OffsetSpiralPoints.rbegin()+5)->SurfacePoint.Coord());
02386             last_direction_vector = OffsetSpiralPoints.rbegin()->SurfacePoint.Coord();
02387             last_direction_vector.Subtract(temp_vector);
02388             //last_direction_vector.SetZ(0.0);
02389             last_direction_vector.Normalize();
02390             last_direction_vector.Multiply(10.0);
02391             Handle(TColgp_HArray1OfPnt) InterpolationPoints = new TColgp_HArray1OfPnt(1,OffsetSpiralPoints.size());
02392             TColgp_Array1OfVec Tangents(1,OffsetSpiralPoints.size());
02393             for (unsigned int t=0;t<OffsetSpiralPoints.size();++t)
02394             {
02395                 InterpolationPoints->SetValue(t+1,OffsetSpiralPoints[t].SurfacePoint);
02396             }
02397             bool check = CheckPoints(InterpolationPoints);
02398             //Here we interpolate. If direction == true this means that the rotation is like the initial rotation
02399             m_all_offset_cuts_high.push_back(InterpolateOrderedPoints(InterpolationPoints,true));
02400         }
02401         if (m_ordered_cuts_it->first==(m_ordered_cuts_it-1)->first)
02402         {
02403             //we only set the new flat level wire here
02404             //no Toolpath is calculated
02405             current_flat_level = m_ordered_cuts_it;
02406             slave_done = false; //This is to generate the next flat level for the slave
02407             just_started = true; //We start a new section
02408         }//end of current == last
02409         //Now lets take the case when we move up again
02410         if (m_ordered_cuts_it->first>(m_ordered_cuts_it-1)->first)
02411         {
02412             //Slave is calculated as Usual, Master stays at the currently highest level
02413             //Check if Last Level has got a Wire as we go from the last to the current with our Spiral
02414             SpiralHelper aSpiralStruct;
02415             double CurveLength = 0.0;
02416             if ((m_ordered_cuts_it-1)->second.ShapeType() == TopAbs_WIRE)
02417             {
02418                 WireExplorer aWireExplorer(TopoDS::Wire((m_ordered_cuts_it-1)->second));
02419                 for (aWireExplorer.Init();aWireExplorer.More();aWireExplorer.Next())
02420                 {
02421                     CurveLength = CurveLength + GetEdgeLength(aWireExplorer.Current());
02422                     BRepAdaptor_Curve curveAdaptor(aWireExplorer.Current());
02423                     //Adjust the point amount based on the curve length make every 0.3mm a point
02424                     //GCPnts_QuasiUniformAbscissa aProp(curveAdaptor,int(GetEdgeLength(aWireExplorer.Current())/0.4));
02425                     GCPnts_QuasiUniformAbscissa aProp(curveAdaptor,1000);
02426                     for (int i=1;i<=aProp.NbPoints();++i)
02427                     {
02428                         //Check the direction
02429                         if (aWireExplorer.Current().Orientation() != TopAbs_REVERSED)
02430                             curveAdaptor.D1(aProp.Parameter(i),aSpiralStruct.SurfacePoint,aSpiralStruct.LineD1);
02431                         else curveAdaptor.D1(aProp.Parameter(aProp.NbPoints()-i+1),aSpiralStruct.SurfacePoint,aSpiralStruct.LineD1);
02432 
02433                         aSpiralStruct.SurfaceNormal.SetCoord(0.0,0.0,1.0);
02434                         TempSpiralPoints.push_back(aSpiralStruct);
02435                     }
02436                 }
02437             }
02438             else
02439             {
02440                 CurveLength = 0.0;
02441                 Edgesort aCutShapeSorter((m_ordered_cuts_it-1)->second);
02442                 for (aCutShapeSorter.Init();aCutShapeSorter.More();aCutShapeSorter.Next())
02443                 {
02444                     CurveLength = CurveLength + GetEdgeLength(aCutShapeSorter.Current());
02445                     //Get the PCurve and the GeomSurface
02446                     Handle_Geom2d_Curve a2DCurve;
02447                     Handle_Geom_Surface aSurface;
02448                     TopLoc_Location aLoc;
02449                     double first2,last2;
02450                     bool reversed = false;
02451                     BRep_Tool::CurveOnSurface(aCutShapeSorter.Current(),a2DCurve,aSurface,aLoc,first2,last2);
02452                     //Jetzt noch die resultierende Surface und die Curve sauber drehen
02453                     //(vielleicht wurde ja das TopoDS_Face irgendwie gedreht oder die TopoDS_Edge)
02454                     if (aCutShapeSorter.Current().Orientation() == TopAbs_REVERSED)
02455                         reversed = true;
02456 
02457                     BRepAdaptor_Curve aCurveAdaptor(aCutShapeSorter.Current());
02458                     GCPnts_QuasiUniformAbscissa aPointGenerator(aCurveAdaptor,1000);
02459                     int PointSize = aPointGenerator.NbPoints();
02460                     //Now get the surface normal to the generated points
02461                     for (int i=1;i<=PointSize;++i)
02462                     {
02463                         gp_Pnt2d a2dParaPoint;
02464                         gp_Pnt aSurfacePoint;
02465                         TopoDS_Face aFace;
02466                         gp_Vec Uvec,Vvec,normalVec;
02467                         //If the curve is reversed we also have to reverse the point direction
02468                         if (reversed)
02469                         {
02470                             a2DCurve->D0(aPointGenerator.Parameter(PointSize-i+1),a2dParaPoint);
02471                             aCurveAdaptor.D1(aPointGenerator.Parameter(PointSize-i+1),aSurfacePoint,aSpiralStruct.LineD1);
02472                         }
02473                         else
02474                         {
02475                             a2DCurve->D0(aPointGenerator.Parameter(i),a2dParaPoint);
02476                             aCurveAdaptor.D1(aPointGenerator.Parameter(i),aSurfacePoint,aSpiralStruct.LineD1);
02477                         }
02478                         GeomAdaptor_Surface aGeom_Adaptor(aSurface);
02479                         aGeom_Adaptor.D1(a2dParaPoint.X(),a2dParaPoint.Y(),aSurfacePoint,Uvec,Vvec);
02480                         //Jetzt den Normalenvector auf die Fläche ausrechnen
02481                         normalVec = Uvec;
02482                         normalVec.Cross(Vvec);
02483                         normalVec.Normalize();
02484                         //Jetzt ist die Normale berechnet und auch normalisiert
02485                         //Jetzt noch checken ob die Normale auch wirklich auf die saubere Seite zeigt
02486                         //dazu nur checken ob der Z-Wert der Normale größer Null ist (dann im 1.und 2. Quadranten)
02487                         if (normalVec.Z()<0)
02488                             normalVec.Multiply(-1.0);
02489 
02490                         //Mal kurz den Winkel zur Grund-Ebene ausrechnen
02491                         gp_Vec planeVec(normalVec.X(),normalVec.Y(),0.0);
02492                         //Den Winkel speichern
02493                         float angle = float(normalVec.Angle(planeVec));
02494                         aSpiralStruct.SurfaceNormal = normalVec;
02495                         aSpiralStruct.SurfacePoint = aSurfacePoint;
02496                         TempSpiralPoints.push_back(aSpiralStruct);
02497                     }
02498                 }
02499             }
02500 
02501             //Now we have to find the shortest distance to the lastPoint of the previous spiral.
02502             //At the beginning the lastPoint is the Origin
02503             //This represents our startPoint. If we just started, then we skip this point
02504 
02505             int start_index = 0,adapted_start_index=0;
02506             float dist,distold = FLT_MAX;
02507             for (unsigned int t=0;t<TempSpiralPoints.size();t++)
02508             {
02509                 dist = float(TempSpiralPoints[t].SurfacePoint.SquareDistance(lastPoint.SurfacePoint));
02510                 if (dist<distold)
02511                 {
02512                     start_index = t;
02513                     distold = dist;
02514                 }
02515             }
02516 
02517             //now we know where to  start at our PointCloud, its the index t
02518 
02519             //Calculate the Slave Toolpath for the current flat area
02520             if (!slave_done)//if we did not calculate the slave toolpath for the current flat area
02521             {
02522                 const TopoDS_Wire &aWire = TopoDS::Wire(current_flat_level->second);
02523                 BRepAdaptor_CompCurve2 wireAdaptor(aWire);
02524                 GCPnts_QuasiUniformAbscissa aProp(wireAdaptor,1000);
02525                 SlavePointContainer.clear();
02526                 gp_Pnt SlaveOffsetPoint;
02527                 for (int i=1;i<=aProp.NbPoints();++i)
02528                 {
02529                     wireAdaptor.D0(aProp.Parameter(i),SlaveOffsetPoint);
02530                     SlaveOffsetPoint.SetZ(SlaveOffsetPoint.Z() + m_UserSettings.master_radius);
02531                     //checken ob der neue Punkt zu nahe am alten ist. Wenn ja, dann kein push_back
02532                     if (SlavePointContainer.size()>0 && (SlavePointContainer.rbegin()->SquareDistance(SlaveOffsetPoint)>(Precision::Confusion()*Precision::Confusion())))
02533                         SlavePointContainer.push_back(SlaveOffsetPoint);
02534                     else if (SlavePointContainer.empty())
02535                         SlavePointContainer.push_back(SlaveOffsetPoint);
02536                 }
02537 
02538                 //Now Interpolate the Slave with reordered points based on the last point
02539                 Handle(TColgp_HArray1OfPnt) InterpolationPoints = new TColgp_HArray1OfPnt(1, SlavePointContainer.size());
02540                 adapted_start_index = start_index+1;
02541                 for (int t=adapted_start_index;t<SlavePointContainer.size();++t)
02542                 {
02543                     InterpolationPoints->SetValue(t+1,SlavePointContainer[t]);
02544                     if (t==start_index)
02545                         break;
02546                     if (t+1==SlavePointContainer.size())
02547                         t=-1;
02548                 }
02549 
02550                 m_all_offset_cuts_high.push_back(InterpolateOrderedPoints(InterpolationPoints,true));
02551                 slave_done = true;
02552             } //Slave done
02553 
02554             gp_Pnt PreviousPoint = TempSpiralPoints[start_index].SurfacePoint;
02555             //check the current direction we would go
02556             gp_Vec help_Vec(TempSpiralPoints[start_index].SurfacePoint.Coord());
02557             direction_vector = TempSpiralPoints[start_index+1].SurfacePoint.Coord();
02558             direction_vector.Subtract(help_Vec);
02559             //direction_vector.SetZ(0.0);
02560             direction_vector.Normalize();
02561             direction_vector.Multiply(10.0);
02562             //switch the Spiral-direction if the clockwise flag is checked and  the
02563             //angle between the last and current round is more then 90°
02564             double angle = direction_vector.Angle(last_direction_vector);
02565 
02566             if (m_UserSettings.clockwise && angle<(D_PI*0.5))
02567                 direction = true; //We are already in the wright direction
02568             else if (m_UserSettings.clockwise && angle >(D_PI*0.5))
02569                 direction = false; //we have to switch the direction
02570             else if (!m_UserSettings.clockwise && angle<(D_PI*0.5))
02571                 direction = false;
02572             else if (!m_UserSettings.clockwise && angle>(D_PI*0.5))
02573                 direction = true;
02574 
02575 
02576             IntCurvesFace_ShapeIntersector anIntersector;
02577             anIntersector.Load(m_Shape,0.01);
02578 
02579             //Insert the first point into the TempSpiralPoints if we have just started
02580             std::vector<SpiralHelper> TempSpiralPointsFinal;
02581             TempSpiralPointsFinal.clear();
02582             gp_Pnt origin(0.0,0.0,0.0);
02583             if (!just_started)
02584                 TempSpiralPointsFinal.push_back(lastPoint);
02585             else
02586                 just_started=false;
02587 
02588             if (direction)
02589                 adapted_start_index = start_index+1;
02590             else
02591             {
02592                 if (start_index==0)
02593                     adapted_start_index = TempSpiralPoints.size()-2; //Skip the last Point as its equal to the first one
02594                 else
02595                     adapted_start_index = start_index-1;
02596             }
02597             std::cout<<"Angle ="<< angle<< " Direction = "<< direction << "Start_Index: "<< adapted_start_index <<","<<start_index<<std::endl;
02598             double distance=0.0;
02599             for (int j=adapted_start_index;j<TempSpiralPoints.size();++j)
02600             {
02601                 distance = distance + PreviousPoint.Distance(TempSpiralPoints[j].SurfacePoint);
02602                 double delta_z = distance * m_UserSettings.level_distance / CurveLength;
02603                 //we have to store the currentPoint for the distance calculation
02604                 //before we change something at its coordinates
02605                 PreviousPoint = TempSpiralPoints[j].SurfacePoint;
02606 
02607                 TempSpiralPoints[j].SurfacePoint.SetZ(TempSpiralPoints[j].SurfacePoint.Z()+delta_z);
02608                 //before we shoot we check if the z-level is not exactly the same as the next round
02609                 //if (fabs(current_z_value-m_UserSettings.level_distance-TempSpiralPoints[j].SurfacePoint.Z())<=0.04)
02610                 //    break; //We have nearly reached the next z-level, therefore we stop here.
02611                 //Now we have to shoot to get the real Point we want
02612                 //Therefore we have to generate the Direction Vector where to Shoot
02613                 gp_Dir Shooting_Direction = getPerpendicularVec(TempSpiralPoints[j].LineD1);
02614                 gp_Lin aLine(TempSpiralPoints[j].SurfacePoint,Shooting_Direction);
02615                 anIntersector.Perform(aLine,-RealLast(),RealLast());
02616                 if (anIntersector.NbPnt()<=1) //Just to debug
02617                     anIntersector.Perform(aLine,-RealLast(),RealLast());
02618                 //Now we set the real Surface Point
02619                 //How many Points did we get??
02620                 int current_index;
02621                 int points = anIntersector.NbPnt();
02622                 if (points>0)
02623                 {
02624                     float shortestDistance, shortestDistanceOld = FLT_MAX;
02625                     for (int g=1;g<=points;g++)
02626                     {
02627                         const gp_Pnt& TestPoint = anIntersector.Pnt(g);
02628                         shortestDistance = float(TestPoint.SquareDistance(TempSpiralPoints[j].SurfacePoint));
02629                         if (shortestDistance<shortestDistanceOld)
02630                         {
02631                             current_index = g;
02632                             shortestDistanceOld = shortestDistance;
02633                         }
02634                     }
02635                     //Now we check how far the shortest Distance is. If its more than 5mm then we jump to the
02636                     //next Point
02637 
02638                     if (shortestDistanceOld>50 )
02639                         continue;
02640                     TempSpiralPoints[j].SurfacePoint = anIntersector.Pnt(current_index);
02641                 }
02642                 else //We have to try a mesh intersection as the Nurb Intersection does not seem to work
02643                 {
02644                     cout << "Big Probleme";
02645                     continue;
02646                 }
02647                 //Now get the Proper Normal at this point
02648                 BRepAdaptor_Surface aFaceAdaptor(anIntersector.Face(current_index));
02649                 gp_Pnt P;
02650                 gp_Vec U_Vec,V_Vec;
02651                 aFaceAdaptor.D1(anIntersector.UParameter(current_index),anIntersector.VParameter(current_index),P,U_Vec,V_Vec);
02652                 U_Vec.Cross(V_Vec);
02653                 U_Vec.Normalize();
02654                 if (U_Vec.Z() < 0) U_Vec.Multiply(-1.0);
02655 
02656                 TempSpiralPoints[j].SurfaceNormal = U_Vec;
02657                 TempSpiralPointsFinal.push_back(TempSpiralPoints[j]);
02658                 //If we reached the end before we processed all points, then we start at the beginning.
02659                 if (direction)
02660                 {
02661                     if (j==start_index)
02662                         break; //Now we have completed all Points
02663                     else if (j+1==TempSpiralPoints.size())
02664                     {
02665                         j=-1;    //-1 because at the for we ++ the variable directly
02666                         continue;
02667                     }
02668 
02669                 }
02670                 else
02671                 {
02672                     if (j==start_index)
02673                         break; //Now we have completed all Points
02674                     else if (j-1<0)
02675                     {
02676                         j=TempSpiralPoints.size()-3;
02677                         continue;
02678                     }
02679                     //We switch to the end and skip the last point
02680                     //as its the same as the point at j=0;
02681                     j=j-2;//As the for puts +1 for each step
02682                 }
02683             }
02684             //Offset for the slave
02685             OffsetSpiralPoints = OffsetSpiral(TempSpiralPointsFinal,false);
02686             //Now store the lastPoint of the currentSpiral as we need it for the next one
02687             lastPoint = *(TempSpiralPointsFinal.rbegin());
02688             gp_Vec temp_vector((OffsetSpiralPoints.rbegin()+5)->SurfacePoint.Coord());
02689             last_direction_vector = OffsetSpiralPoints.rbegin()->SurfacePoint.Coord();
02690             last_direction_vector.Subtract(temp_vector);
02691             //last_direction_vector.SetZ(0.0);
02692             last_direction_vector.Normalize();
02693             last_direction_vector.Multiply(10.0);
02694             Handle(TColgp_HArray1OfPnt) InterpolationPoints = new TColgp_HArray1OfPnt(1,OffsetSpiralPoints.size());
02695             TColgp_Array1OfVec Tangents(1,OffsetSpiralPoints.size());
02696             for (unsigned int t=0;t<OffsetSpiralPoints.size();++t)
02697             {
02698                 InterpolationPoints->SetValue(t+1,OffsetSpiralPoints[t].SurfacePoint);
02699             }
02700             bool check = CheckPoints(InterpolationPoints);
02701             //Here we interpolate. If direction == true this means that the rotation is like the initial rotation
02702             m_all_offset_cuts_low.push_back(InterpolateOrderedPoints(InterpolationPoints,true));
02703         }
02704     }
02705     anoutput1.close();
02706     log.saveToFile("C:/normals.iv");
02707     return true;
02708 }
02709 
02710 
02711 std::vector<SpiralHelper> cutting_tools::OffsetSpiral(const std::vector<SpiralHelper>& SpiralPoints,bool master_or_slave)
02712 {
02713     std::vector<SpiralHelper> OffsetPoints;
02714     SpiralHelper OffsetPoint;
02715     OffsetPoints.clear();
02716     //Offset the Points now
02717 
02718     for (unsigned int i=0;i<SpiralPoints.size();++i)
02719     {
02720         OffsetPoint = SpiralPoints[i];
02721         if (master_or_slave)
02722         {
02723             OffsetPoint.SurfaceNormal.Multiply(m_UserSettings.master_radius);
02724             OffsetPoint.SurfacePoint.SetXYZ(OffsetPoint.SurfacePoint.XYZ() + OffsetPoint.SurfaceNormal.XYZ());
02725         }
02726         else
02727         {
02728             OffsetPoint.SurfaceNormal.Multiply(m_UserSettings.slave_radius+m_UserSettings.sheet_thickness);
02729             OffsetPoint.SurfacePoint.SetXYZ(OffsetPoint.SurfacePoint.XYZ() - OffsetPoint.SurfaceNormal.XYZ());
02730         }
02731         if (OffsetPoints.size()>0 && (OffsetPoints.rbegin()->SurfacePoint.SquareDistance(OffsetPoint.SurfacePoint)>(Precision::Confusion()*Precision::Confusion())) && (fabs(OffsetPoints.rbegin()->SurfacePoint.Z()-OffsetPoint.SurfacePoint.Z())< (m_UserSettings.level_distance/10.0)))
02732         {
02733             OffsetPoints.push_back(OffsetPoint);
02734         }
02735         else if (OffsetPoints.empty())
02736         {
02737             OffsetPoints.push_back(OffsetPoint);
02738         }
02739         else if ((i+1==SpiralPoints.size()) && (OffsetPoints.rbegin()->SurfacePoint.SquareDistance(OffsetPoint.SurfacePoint)<(Precision::Confusion()*Precision::Confusion())))
02740         {
02741             //This part is necessary as the last point of the current spiral would otherwise not be offsetted
02742             OffsetPoints.pop_back();//Delete the two currently last points
02743             OffsetPoints.pop_back();
02744             OffsetPoints.push_back(OffsetPoint);//Add the last point
02745         }
02746     }
02747     return OffsetPoints;
02748 }
02749 std::vector<float> cutting_tools::getFlatAreas()
02750 {
02751     std::vector<float> FlatAreas;
02752     FlatAreas.clear();
02753     for (unsigned int i=0;i<m_MachiningOrder.size();++i)
02754         FlatAreas.push_back(m_MachiningOrder[i].first.z);
02755     return FlatAreas;
02756 }
02757 
02758 
02759 bool cutting_tools::OffsetWires_FeatureBased()
02760 {
02761     std::vector<std::pair<float,TopoDS_Shape> >::iterator current_flat_level;
02762     gp_Pnt lastPoint(0.0,0.0,0.0); //Initialize the first Point to the Origin
02763     current_flat_level = m_ordered_cuts.begin();
02764     bool slave_done= false; //Necessary if the slave is already put out
02765     //Nicht beim höchsten Anfangen, da wir den nicht mit dem Master fahren wollen
02766     for (m_ordered_cuts_it = m_ordered_cuts.begin()+1;m_ordered_cuts_it!=m_ordered_cuts.end();++m_ordered_cuts_it)
02767     {
02768         std::vector<std::pair<gp_Pnt,double> > MasterPointContainer;
02769         std::vector<std::vector<std::pair<gp_Pnt,double> > > MasterPointsStorage;
02770         std::vector<gp_Pnt> SlavePointContainer;
02771         std::vector<std::vector<gp_Pnt> > SlavePointsStorage;
02772         std::vector<std::vector<gp_Pnt> >::iterator anIterator1;
02773         std::vector<std::vector<std::pair<gp_Pnt,double> > >::iterator anIterator2;
02774         MasterPointsStorage.clear();
02775         SlavePointsStorage.clear();
02776         MasterPointContainer.clear();
02777         SlavePointContainer.clear();
02778         //Now we have to select which strategy to choose
02779         //if the current levels is bigger,the same, or less then the previous one
02780         if (m_ordered_cuts_it->first<(m_ordered_cuts_it-1)->first)
02781         {
02782             //Master is calculated as Usual, Slave stays at the currently highest level
02783             //Check if current Level has got a Wire
02784             if (m_ordered_cuts_it->second.ShapeType() == TopAbs_WIRE)
02785             {
02786                 WireExplorer aWireExplorer(TopoDS::Wire(m_ordered_cuts_it->second));
02787                 for (aWireExplorer.Init();aWireExplorer.More();aWireExplorer.Next())
02788                 {
02789                     BRepAdaptor_Curve curveAdaptor(aWireExplorer.Current());
02790                     GCPnts_QuasiUniformAbscissa aProp(curveAdaptor,100);
02791                     for (int i=1;i<=aProp.NbPoints();++i)
02792                     {
02793                         std::pair<gp_Pnt,double> aTempPair;
02794                         //Check the direction
02795                         if (aWireExplorer.Current().Orientation() != TopAbs_REVERSED)
02796                             curveAdaptor.D0(aProp.Parameter(i),aTempPair.first);
02797                         else curveAdaptor.D0(aProp.Parameter(aProp.NbPoints()-i+1),aTempPair.first);
02798                         aTempPair.first.SetZ(aTempPair.first.Z() + m_UserSettings.master_radius);
02799                         aTempPair.second = 0.0; //Initialize of Angle
02800                         //checken ob der neue Punkt zu nahe am alten ist. Wenn ja, dann kein push_back
02801                         if (MasterPointContainer.size()>0 && (MasterPointContainer.rbegin()->first.SquareDistance(aTempPair.first)>(Precision::Confusion()*Precision::Confusion())))
02802                         {
02803                             MasterPointContainer.push_back(aTempPair);
02804                         }
02805                         else if (MasterPointContainer.empty())
02806                         {
02807                             MasterPointContainer.push_back(aTempPair);
02808                         }
02809                     }
02810                     //Now Interpolate the Points only if we have a non-continuous edge or if we are finished
02811                     //with all edges
02812                     bool tangency = true;
02813                     //If there are more Edges in the wire
02814                     if (aWireExplorer.MoreEdge())
02815                     {
02816                         tangency = CheckEdgeTangency(aWireExplorer.Current(),aWireExplorer.NextEdge());
02817                         if (!tangency)
02818                         {
02819                             //Store all the PointClouds in a StorageVector to arrange the Robot-Movement afterwards
02820                             MasterPointsStorage.push_back(MasterPointContainer);
02821                             MasterPointContainer.clear();
02822                         }
02823                         else continue;
02824                     }
02825                     else
02826                     {
02827                         MasterPointsStorage.push_back(MasterPointContainer);
02828                         MasterPointContainer.clear();
02829                     }
02830                 }
02831                 //Now check the point-cloud with the shortest distance to "lastPoint"
02832                 int start_index = 0,start_array=0;
02833                 CheckforLastPoint(lastPoint,start_index,start_array,MasterPointsStorage);
02834                 //Now Interpolate the PointClouds...Cloud by Cloud
02835                 //First we have to divide the first PointCloud as it is for sure that we start
02836                 //Somewhere in the middle of it. We will then insert the points at the current start
02837                 if (MasterPointsStorage.size() == 1) //If we have only one PointCloud
02838                 {
02839                     MasterPointContainer.clear();
02840                     bool first = true;
02841                     for (unsigned int i=start_index;i<MasterPointsStorage.begin()->size();i++)
02842                     {
02843                         if (i+1 == MasterPointsStorage.begin()->size())
02844                         {
02845                             first = false;
02846                             i=-1;
02847                             continue;
02848                         }
02849                         MasterPointContainer.push_back(MasterPointsStorage[0][i]);
02850                         if (!first && i == start_index)
02851                             break;
02852                     }
02853                     //Now lets interpolate the Point Cloud
02854                     Handle(TColgp_HArray1OfPnt) InterpolationPointsMaster = new TColgp_HArray1OfPnt(1, MasterPointContainer.size());
02855                     for (unsigned int t=0;t<MasterPointContainer.size();++t)
02856                     {
02857                         InterpolationPointsMaster->SetValue(t+1,MasterPointContainer[t].first);
02858                     }
02859                     m_all_offset_cuts_high.push_back(InterpolateOrderedPoints(InterpolationPointsMaster,true));
02860                     //Store the last point
02861                     lastPoint = MasterPointContainer.rbegin()->first;
02862                 }
02863                 else //If we have more than one PointCloud
02864                 {
02865                     anIterator2 = MasterPointsStorage.begin();
02866                     MasterPointContainer.clear();
02867                     for (int i=0;i<=start_index;i++)
02868                     {
02869                         MasterPointContainer.push_back(MasterPointsStorage[start_array][i]);
02870                     }
02871                     MasterPointsStorage.insert((anIterator2+start_array+1),MasterPointContainer);
02872                     MasterPointContainer.clear();
02873                     //Reinitialize the Iterators
02874                     anIterator2 = MasterPointsStorage.begin();
02875                     for (unsigned int i=start_index;i<MasterPointsStorage[start_array].size();i++)
02876                     {
02877                         MasterPointContainer.push_back(MasterPointsStorage[start_array][i]);
02878                     }
02879                     MasterPointsStorage.insert((anIterator2+start_array+2),MasterPointContainer);
02880                     //Reinitialize the Iterators
02881                     anIterator2 = MasterPointsStorage.begin();
02882                     //Delete the Original PointCloud
02883                     MasterPointsStorage.erase(anIterator2+start_array);
02884                     MasterPointContainer.clear();
02885                     //Now lets interpolate the Point Clouds
02886                     //Start at start_array+1 as the insert operations used us to do it like that
02887                     for (unsigned int j=start_array+1;j<MasterPointsStorage.size();++j)
02888                     {
02889                         Handle(TColgp_HArray1OfPnt) InterpolationPointsMaster = new TColgp_HArray1OfPnt(1, MasterPointsStorage[j].size());
02890                         for (unsigned int t=0;t<MasterPointsStorage[j].size();++t)
02891                         {
02892                             InterpolationPointsMaster->SetValue(t+1,MasterPointsStorage[j][t].first);
02893                         }
02894                         m_all_offset_cuts_high.push_back(InterpolateOrderedPoints(InterpolationPointsMaster,true));
02895                         if (j+1==MasterPointsStorage.size())
02896                         {
02897                             j=-1;
02898                             continue;
02899                         }
02900                         if (j+1==start_array+1)
02901                             break;
02902                     }
02903                     lastPoint = MasterPointsStorage[start_array].rbegin()->first;
02904                 }
02905             }
02906             else //If the current Curve is no Wire
02907             {
02908                 Edgesort aCutShapeSorter(m_ordered_cuts_it->second);
02909                 for (aCutShapeSorter.Init();aCutShapeSorter.More();aCutShapeSorter.Next())
02910                 {
02911                     //Get the PCurve and the GeomSurface
02912                     Handle_Geom2d_Curve a2DCurve;
02913                     Handle_Geom_Surface aSurface;
02914                     TopLoc_Location aLoc;
02915                     TopoDS_Edge anEdge;
02916                     double first2,last2;
02917                     bool reversed = false;
02918                     BRep_Tool::CurveOnSurface(aCutShapeSorter.Current(),a2DCurve,aSurface,aLoc,first2,last2);
02919                     //Jetzt noch die resultierende Surface und die Curve sauber drehen
02920                     //(vielleicht wurde ja das TopoDS_Face irgendwie gedreht oder die TopoDS_Edge)
02921                     if (aCutShapeSorter.Current().Orientation() == TopAbs_REVERSED)
02922                         reversed = true;
02923 
02924                     BRepAdaptor_Curve aCurveAdaptor(aCutShapeSorter.Current());
02925                     GCPnts_QuasiUniformAbscissa aPointGenerator(aCurveAdaptor,200);
02926                     int PointSize = aPointGenerator.NbPoints();
02927                     //Now get the surface normal to the generated points
02928                     for (int i=1;i<=PointSize;++i)
02929                     {
02930                         std::pair<gp_Pnt,double> PointContactPair;
02931                         gp_Pnt2d a2dParaPoint;
02932                         gp_Pnt aSurfacePoint;
02933                         TopoDS_Face aFace;
02934                         gp_Vec Uvec,Vvec,normalVec;
02935                         //If the curve is reversed we also have to reverse the point direction
02936                         if (reversed) a2DCurve->D0(aPointGenerator.Parameter(PointSize-i+1),a2dParaPoint);
02937                         else a2DCurve->D0(aPointGenerator.Parameter(i),a2dParaPoint);
02938                         GeomAdaptor_Surface aGeom_Adaptor(aSurface);
02939                         int t = aGeom_Adaptor.GetType();
02940                         aGeom_Adaptor.D1(a2dParaPoint.X(),a2dParaPoint.Y(),aSurfacePoint,Uvec,Vvec);
02941                         //Jetzt den Normalenvector auf die Fläche ausrechnen
02942                         normalVec = Uvec;
02943                         normalVec.Cross(Vvec);
02944                         normalVec.Normalize();
02945                         //Jetzt ist die Normale berechnet und auch normalisiert
02946                         //Jetzt noch checken ob die Normale auch wirklich auf die saubere Seite zeigt
02947                         //dazu nur checken ob der Z-Wert der Normale größer Null ist (dann im 1.und 2. Quadranten)
02948                         if (normalVec.Z()<0) normalVec.Multiply(-1.0);
02949 
02950                         //Mal kurz den Winkel zur Grund-Ebene ausrechnen
02951                         gp_Vec planeVec(normalVec.X(),normalVec.Y(),0.0);
02952                         //Den Winkel
02953                         PointContactPair.second = normalVec.Angle(planeVec);
02954                         gp_Vec NormalVecSlave = normalVec;
02955                         //Jetzt die Z-Komponente auf 0 setzen
02956                         //normalVec.SetZ(0.0);
02957                         normalVec.Normalize();
02958                         //Jetzt die Normale mit folgender Formel multiplizieren für den Master
02959                         //double multiply = m_UserSettings.master_radius*(1-sin(PointContactPair.second))/cos(PointContactPair.second);
02960                         double multiply = m_UserSettings.master_radius;
02961                         normalVec.Multiply(multiply);
02962                         //Jetzt den OffsetPunkt berechnen
02963                         PointContactPair.first.SetXYZ(aSurfacePoint.XYZ() + normalVec.XYZ());
02964                         //Damit wir keine Punkte bekommen die zu nahe beieinander liegen
02965                         //Den letzten hinzugefügten Punkt suchen
02966                         if (MasterPointContainer.size()>0 && (MasterPointContainer.rbegin()->first.SquareDistance(PointContactPair.first)>0.001))
02967                         {
02968                             MasterPointContainer.push_back(PointContactPair);
02969                         }
02970                         else if (MasterPointContainer.empty())
02971                         {
02972                             MasterPointContainer.push_back(PointContactPair);
02973                         }
02974                     }
02975                 }
02976                 MasterPointsStorage.push_back(MasterPointContainer);
02977                 int start_index_master = 0,start_array_master=0;
02978                 CheckforLastPoint(lastPoint,start_index_master,start_array_master,MasterPointsStorage);
02979                 //First we have to divide the first PointCloud as it is for sure that we start
02980                 //Somewhere in the middle of it. We will then insert the points at the current start
02981                 MasterPointContainer.clear();
02982                 bool first = true;
02983                 for (unsigned int i=start_index_master;i<MasterPointsStorage.begin()->size();i++)
02984                 {
02985                     if (i+1 == MasterPointsStorage.begin()->size())
02986                     {
02987                         first = false;
02988                         i=-1;
02989                         continue;
02990                     }
02991                     MasterPointContainer.push_back(MasterPointsStorage[0][i]);
02992                     if (!first && i == start_index_master)
02993                         break;
02994                 }
02995                 //Now lets interpolate the Point Cloud
02996                 Handle(TColgp_HArray1OfPnt) InterpolationPointsMaster = new TColgp_HArray1OfPnt(1, MasterPointContainer.size());
02997                 for (unsigned int t=0;t<MasterPointContainer.size();++t)
02998                     InterpolationPointsMaster->SetValue(t+1,MasterPointContainer[t].first);
02999 
03000                 m_all_offset_cuts_high.push_back(InterpolateOrderedPoints(InterpolationPointsMaster,true));
03001                 //Store the last point
03002                 lastPoint = MasterPointContainer.rbegin()->first;
03003                 //SlaveTool Path finished
03004             }//end calculation of the master if its not a wire
03005             //Calculate the Slave Toolpath
03006             if (!slave_done)//if we did not calculate the slave toolpath for the current flat area
03007             {
03008                 TopoDS_Wire aWire = TopoDS::Wire(current_flat_level->second);
03009                 BRepAdaptor_CompCurve2 wireAdaptor(aWire);
03010                 GCPnts_QuasiUniformAbscissa aProp(wireAdaptor,1000);
03011                 SlavePointContainer.clear();
03012                 SlavePointsStorage.clear();
03013                 for (int i=1;i<=aProp.NbPoints();++i)
03014                 {
03015                     gp_Pnt SlaveOffsetPoint;
03016                     wireAdaptor.D0(aProp.Parameter(i),SlaveOffsetPoint);
03017                     SlaveOffsetPoint.SetZ(SlaveOffsetPoint.Z() - m_UserSettings.sheet_thickness - m_UserSettings.slave_radius);
03018                     //checken ob der neue Punkt zu nahe am alten ist. Wenn ja, dann kein push_back
03019                     if (SlavePointContainer.size()>0 && (SlavePointContainer.rbegin()->SquareDistance(SlaveOffsetPoint)>(Precision::Confusion()*Precision::Confusion())))
03020                         SlavePointContainer.push_back(SlaveOffsetPoint);
03021                     else if (SlavePointContainer.empty())
03022                         SlavePointContainer.push_back(SlaveOffsetPoint);
03023                 }
03024                 SlavePointsStorage.push_back(SlavePointContainer);
03025                 int start_index_slave = 0,start_array_slave=0;
03026                 CheckforLastPoint(lastPoint,start_index_slave,start_array_slave,SlavePointsStorage);
03027                 //First we have to divide the first PointCloud as it is for sure that we start
03028                 //Somewhere in the middle of it. We will then insert the points at the current start
03029                 SlavePointContainer.clear();
03030                 bool first = true;
03031                 for (unsigned int i=start_index_slave;i<SlavePointsStorage.begin()->size();i++)
03032                 {
03033                     if (i+1 == SlavePointsStorage.begin()->size())
03034                     {
03035                         first = false;
03036                         i=-1;
03037                         continue;
03038                     }
03039                     SlavePointContainer.push_back(SlavePointsStorage[0][i]);
03040                     if (!first && i == start_index_slave)
03041                         break;
03042                 }
03043                 //Now Interpolate the Slave, therefore we also have to take the curves normal directions
03044                 Handle(TColgp_HArray1OfPnt) InterpolationPoints = new TColgp_HArray1OfPnt(1, SlavePointContainer.size());
03045                 for (unsigned int t=0;t<SlavePointContainer.size();++t)
03046                     InterpolationPoints->SetValue(t+1,SlavePointContainer[t]);
03047 
03048                 m_all_offset_cuts_low.push_back(InterpolateOrderedPoints(InterpolationPoints,true));
03049                 slave_done = true;
03050             } //Slave done
03051         }//Current Curve < last curve is finished here
03052         if (m_ordered_cuts_it->first==(m_ordered_cuts_it-1)->first)
03053         {
03054             //we only set the new flat level wire here
03055             //no Toolpath is calculated
03056             current_flat_level = m_ordered_cuts_it;
03057             slave_done = false; //This is to generate the next flat level for the slave
03058         }//end of current == last
03059         if (m_ordered_cuts_it->first>(m_ordered_cuts_it-1)->first)
03060         {
03061             //The Slave Tool is now the Master Tool and therefore we only have to exchange < case
03062             if (m_ordered_cuts_it->second.ShapeType() == TopAbs_WIRE)
03063             {
03064                 WireExplorer aWireExplorer(TopoDS::Wire(m_ordered_cuts_it->second));
03065                 for (aWireExplorer.Init();aWireExplorer.More();aWireExplorer.Next())
03066                 {
03067                     BRepAdaptor_Curve curveAdaptor(aWireExplorer.Current());
03068                     GCPnts_QuasiUniformAbscissa aProp(curveAdaptor,100);
03069                     for (int i=1;i<=aProp.NbPoints();++i)
03070                     {
03071                         std::pair<gp_Pnt,double> aTempPair;
03072                         //Check the direction
03073                         if (aWireExplorer.Current().Orientation() != TopAbs_REVERSED)
03074                             curveAdaptor.D0(aProp.Parameter(i),aTempPair.first);
03075                         else curveAdaptor.D0(aProp.Parameter(aProp.NbPoints()-i+1),aTempPair.first);
03076                         aTempPair.first.SetZ(aTempPair.first.Z() - m_UserSettings.slave_radius - m_UserSettings.sheet_thickness);
03077                         aTempPair.second = 0.0; //Initialize of Angle
03078                         //checken ob der neue Punkt zu nahe am alten ist. Wenn ja, dann kein push_back
03079                         if (MasterPointContainer.size()>0 && (MasterPointContainer.rbegin()->first.SquareDistance(aTempPair.first)>(Precision::Confusion()*Precision::Confusion())))
03080                         {
03081                             MasterPointContainer.push_back(aTempPair);
03082                         }
03083                         else if (MasterPointContainer.empty())
03084                         {
03085                             MasterPointContainer.push_back(aTempPair);
03086                         }
03087                     }
03088                     //Now Interpolate the Points only if we have a non-continuous edge or if we are finished
03089                     //with all edges
03090                     bool tangency = true;
03091                     //If there are more Edges in the wire
03092                     if (aWireExplorer.MoreEdge())
03093                     {
03094                         tangency = CheckEdgeTangency(aWireExplorer.Current(),aWireExplorer.NextEdge());
03095                         if (!tangency)
03096                         {
03097                             //Store all the PointClouds in a StorageVector to arrange the Robot-Movement afterwards
03098                             MasterPointsStorage.push_back(MasterPointContainer);
03099                             MasterPointContainer.clear();
03100                         }
03101                         else continue;
03102                     }
03103                     else
03104                     {
03105                         MasterPointsStorage.push_back(MasterPointContainer);
03106                         MasterPointContainer.clear();
03107                     }
03108                 }
03109                 //Now check the point-cloud with the shortest distance to "lastPoint"
03110                 int start_index = 0,start_array=0;
03111                 CheckforLastPoint(lastPoint,start_index,start_array,MasterPointsStorage);
03112                 //Now Interpolate the PointClouds...Cloud by Cloud
03113                 //First we have to divide the first PointCloud as it is for sure that we start
03114                 //Somewhere in the middle of it. We will then insert the points at the current start
03115                 if (MasterPointsStorage.size() == 1) //If we have only one PointCloud
03116                 {
03117                     MasterPointContainer.clear();
03118                     bool first = true;
03119                     for (unsigned int i=start_index;i<MasterPointsStorage.begin()->size();i++)
03120                     {
03121                         if (i+1 == MasterPointsStorage.begin()->size())
03122                         {
03123                             first = false;
03124                             i=-1;
03125                             continue;
03126                         }
03127                         MasterPointContainer.push_back(MasterPointsStorage[0][i]);
03128                         if (!first && i == start_index)
03129                             break;
03130                     }
03131                     //Now lets interpolate the Point Cloud
03132                     Handle(TColgp_HArray1OfPnt) InterpolationPointsMaster = new TColgp_HArray1OfPnt(1, MasterPointContainer.size());
03133                     for (unsigned int t=0;t<MasterPointContainer.size();++t)
03134                     {
03135                         InterpolationPointsMaster->SetValue(t+1,MasterPointContainer[t].first);
03136                     }
03137                     m_all_offset_cuts_low.push_back(InterpolateOrderedPoints(InterpolationPointsMaster,true));
03138                     //Store the last point
03139                     lastPoint = MasterPointContainer.rbegin()->first;
03140                 }
03141                 else //If we have more than one PointCloud
03142                 {
03143                     anIterator2 = MasterPointsStorage.begin();
03144                     MasterPointContainer.clear();
03145                     for (int i=0;i<=start_index;i++)
03146                     {
03147                         MasterPointContainer.push_back(MasterPointsStorage[start_array][i]);
03148                     }
03149                     MasterPointsStorage.insert((anIterator2+start_array+1),MasterPointContainer);
03150                     MasterPointContainer.clear();
03151                     //Reinitialize the Iterators
03152                     anIterator2 = MasterPointsStorage.begin();
03153                     for (unsigned int i=start_index;i<MasterPointsStorage[start_array].size();i++)
03154                     {
03155                         MasterPointContainer.push_back(MasterPointsStorage[start_array][i]);
03156                     }
03157                     MasterPointsStorage.insert((anIterator2+start_array+2),MasterPointContainer);
03158                     //Reinitialize the Iterators
03159                     anIterator2 = MasterPointsStorage.begin();
03160                     //Delete the Original PointCloud
03161                     MasterPointsStorage.erase(anIterator2+start_array);
03162                     MasterPointContainer.clear();
03163                     //Now lets interpolate the Point Clouds
03164                     //Start at start_array+1 as the insert operations used us to do it like that
03165                     for (unsigned int j=start_array+1;j<MasterPointsStorage.size();++j)
03166                     {
03167                         Handle(TColgp_HArray1OfPnt) InterpolationPointsMaster = new TColgp_HArray1OfPnt(1, MasterPointsStorage[j].size());
03168                         for (unsigned int t=0;t<MasterPointsStorage[j].size();++t)
03169                         {
03170                             InterpolationPointsMaster->SetValue(t+1,MasterPointsStorage[j][t].first);
03171                         }
03172                         m_all_offset_cuts_low.push_back(InterpolateOrderedPoints(InterpolationPointsMaster,true));
03173                         if (j+1==MasterPointsStorage.size())
03174                         {
03175                             j=-1;
03176                             continue;
03177                         }
03178                         if (j+1==start_array+1)
03179                             break;
03180                     }
03181                     lastPoint = MasterPointsStorage[start_array].rbegin()->first;
03182                 }
03183             }
03184             else //If the current Curve is no Wire
03185             {
03186                 Edgesort aCutShapeSorter(m_ordered_cuts_it->second);
03187                 for (aCutShapeSorter.Init();aCutShapeSorter.More();aCutShapeSorter.Next())
03188                 {
03189                     //Get the PCurve and the GeomSurface
03190                     Handle_Geom2d_Curve a2DCurve;
03191                     Handle_Geom_Surface aSurface;
03192                     TopLoc_Location aLoc;
03193                     TopoDS_Edge anEdge;
03194                     double first2,last2;
03195                     bool reversed = false;
03196                     BRep_Tool::CurveOnSurface(aCutShapeSorter.Current(),a2DCurve,aSurface,aLoc,first2,last2);
03197                     //Jetzt noch die resultierende Surface und die Curve sauber drehen
03198                     //(vielleicht wurde ja das TopoDS_Face irgendwie gedreht oder die TopoDS_Edge)
03199                     if (aCutShapeSorter.Current().Orientation() == TopAbs_REVERSED)
03200                         reversed = true;
03201 
03202                     BRepAdaptor_Curve aCurveAdaptor(aCutShapeSorter.Current());
03203                     GCPnts_QuasiUniformAbscissa aPointGenerator(aCurveAdaptor,200);
03204                     int PointSize = aPointGenerator.NbPoints();
03205                     //Now get the surface normal to the generated points
03206                     for (int i=1;i<=PointSize;++i)
03207                     {
03208                         std::pair<gp_Pnt,double> PointContactPair;
03209                         gp_Pnt2d a2dParaPoint;
03210                         gp_Pnt aSurfacePoint;
03211                         TopoDS_Face aFace;
03212                         gp_Vec Uvec,Vvec,normalVec;
03213                         //If the curve is reversed we also have to reverse the point direction
03214                         if (reversed) a2DCurve->D0(aPointGenerator.Parameter(PointSize-i+1),a2dParaPoint);
03215                         else a2DCurve->D0(aPointGenerator.Parameter(i),a2dParaPoint);
03216                         GeomAdaptor_Surface aGeom_Adaptor(aSurface);
03217                         int t = aGeom_Adaptor.GetType();
03218                         aGeom_Adaptor.D1(a2dParaPoint.X(),a2dParaPoint.Y(),aSurfacePoint,Uvec,Vvec);
03219                         //Jetzt den Normalenvector auf die Fläche ausrechnen
03220                         normalVec = Uvec;
03221                         normalVec.Cross(Vvec);
03222                         normalVec.Normalize();
03223                         //Jetzt ist die Normale berechnet und auch normalisiert
03224                         //Jetzt noch checken ob die Normale auch wirklich auf die saubere Seite zeigt
03225                         //dazu nur checken ob der Z-Wert der Normale größer Null ist (dann im 1.und 2. Quadranten)
03226                         if (normalVec.Z()<0) normalVec.Multiply(-1.0);
03227 
03228                         //Mal kurz den Winkel zur Grund-Ebene ausrechnen
03229                         gp_Vec planeVec(normalVec.X(),normalVec.Y(),0.0);
03230                         //Den Winkel
03231                         PointContactPair.second = normalVec.Angle(planeVec);
03232                         gp_Vec NormalVecSlave = normalVec;
03233                         //Jetzt die Z-Komponente auf 0 setzen
03234                         //normalVec.SetZ(0.0);
03235                         normalVec.Normalize();
03236                         //Jetzt die Normale mit folgender Formel multiplizieren für den Master
03237                         //double multiply = m_UserSettings.master_radius*(1-sin(PointContactPair.second))/cos(PointContactPair.second);
03238                         double multiply = m_UserSettings.slave_radius + m_UserSettings.sheet_thickness;
03239                         normalVec.Multiply(multiply);
03240                         normalVec.Multiply(-1.0); //As the master is the slave
03241                         //Jetzt den OffsetPunkt berechnen
03242                         PointContactPair.first.SetXYZ(aSurfacePoint.XYZ() + normalVec.XYZ());
03243                         //Damit wir keine Punkte bekommen die zu nahe beieinander liegen
03244                         //Den letzten hinzugefügten Punkt suchen
03245                         if (MasterPointContainer.size()>0 && (MasterPointContainer.rbegin()->first.SquareDistance(PointContactPair.first)>0.001))
03246                         {
03247                             MasterPointContainer.push_back(PointContactPair);
03248                         }
03249                         else if (MasterPointContainer.empty())
03250                         {
03251                             MasterPointContainer.push_back(PointContactPair);
03252                         }
03253                     }
03254                 }
03255                 MasterPointsStorage.push_back(MasterPointContainer);
03256                 int start_index_master = 0,start_array_master=0;
03257                 CheckforLastPoint(lastPoint,start_index_master,start_array_master,MasterPointsStorage);
03258                 //First we have to divide the first PointCloud as it is for sure that we start
03259                 //Somewhere in the middle of it. We will then insert the points at the current start
03260                 MasterPointContainer.clear();
03261                 bool first = true;
03262                 for (unsigned int i=start_index_master;i<MasterPointsStorage.begin()->size();i++)
03263                 {
03264                     if (i+1 == MasterPointsStorage.begin()->size())
03265                     {
03266                         first = false;
03267                         i=-1;
03268                         continue;
03269                     }
03270                     MasterPointContainer.push_back(MasterPointsStorage[0][i]);
03271                     if (!first && i == start_index_master)
03272                         break;
03273                 }
03274                 //Now lets interpolate the Point Cloud
03275                 Handle(TColgp_HArray1OfPnt) InterpolationPointsMaster = new TColgp_HArray1OfPnt(1, MasterPointContainer.size());
03276                 for (unsigned int t=0;t<MasterPointContainer.size();++t)
03277                     InterpolationPointsMaster->SetValue(t+1,MasterPointContainer[t].first);
03278 
03279                 m_all_offset_cuts_low.push_back(InterpolateOrderedPoints(InterpolationPointsMaster,true));
03280                 //Store the last point
03281                 lastPoint = MasterPointContainer.rbegin()->first;
03282                 //SlaveTool Path finished
03283             }//end calculation of the master if its not a wire
03284             //Calculate the Slave Toolpath
03285             if (!slave_done)//if we did not calculate the slave toolpath for the current flat area
03286             {
03287                 TopoDS_Wire aWire = TopoDS::Wire(current_flat_level->second);
03288                 BRepAdaptor_CompCurve2 wireAdaptor(aWire);
03289                 GCPnts_QuasiUniformAbscissa aProp(wireAdaptor,1000);
03290                 SlavePointContainer.clear();
03291                 SlavePointsStorage.clear();
03292                 for (int i=1;i<=aProp.NbPoints();++i)
03293                 {
03294                     gp_Pnt SlaveOffsetPoint;
03295                     wireAdaptor.D0(aProp.Parameter(i),SlaveOffsetPoint);
03296                     SlaveOffsetPoint.SetZ(SlaveOffsetPoint.Z() + m_UserSettings.master_radius);
03297                     //checken ob der neue Punkt zu nahe am alten ist. Wenn ja, dann kein push_back
03298                     if (SlavePointContainer.size()>0 && (SlavePointContainer.rbegin()->SquareDistance(SlaveOffsetPoint)>(Precision::Confusion()*Precision::Confusion())))
03299                     {
03300                         SlavePointContainer.push_back(SlaveOffsetPoint);
03301                     }
03302                     else if (SlavePointContainer.empty())
03303                     {
03304                         SlavePointContainer.push_back(SlaveOffsetPoint);
03305                     }
03306                 }
03307                 SlavePointsStorage.push_back(SlavePointContainer);
03308                 int start_index_slave = 0,start_array_slave=0;
03309                 CheckforLastPoint(lastPoint,start_index_slave,start_array_slave,SlavePointsStorage);
03310                 //First we have to divide the first PointCloud as it is for sure that we start
03311                 //Somewhere in the middle of it. We will then insert the points at the current start
03312                 SlavePointContainer.clear();
03313                 bool first = true;
03314                 for (unsigned int i=start_index_slave;i<SlavePointsStorage.begin()->size();i++)
03315                 {
03316                     if (i+1 == SlavePointsStorage.begin()->size())
03317                     {
03318                         first = false;
03319                         i=-1;
03320                         continue;
03321                     }
03322                     SlavePointContainer.push_back(SlavePointsStorage[0][i]);
03323                     if (!first && i == start_index_slave)
03324                         break;
03325                 }
03326                 //Now Interpolate the Slave, therefore we also have to take the curves normal directions
03327                 Handle(TColgp_HArray1OfPnt) InterpolationPoints = new TColgp_HArray1OfPnt(1, SlavePointContainer.size());
03328                 for (unsigned int t=0;t<SlavePointContainer.size();++t)
03329                     InterpolationPoints->SetValue(t+1,SlavePointContainer[t]);
03330 
03331                 m_all_offset_cuts_high.push_back(InterpolateOrderedPoints(InterpolationPoints,true));
03332                 slave_done = true;
03333             } //Slave done
03334         }//Current Curve > Last Curve
03335     }//Main for Loop which goes through all the curves
03336 
03337     return true;
03338 }
03339 
03340 bool cutting_tools::cut_Mesh(float z_level, float min_level, std::list<std::vector<Base::Vector3f> >&result, float &z_level_corrected)
03341 {
03342     //std::ofstream outfile;
03343     //outfile.open("c:/mesh_cut.out");
03344     Base::Vector3f z_level_plane,normal;
03345     z_level_plane.z=z_level;
03346     normal.x=0;
03347     normal.y=0;
03348     normal.z=1.0;
03349     bool cutok;
03350     //Die Richtung für die Korrektur wird hier festgelegt
03351     bool direction=true;
03352     float factor = 0.0;
03353     do
03354     {
03355         cutok = true;
03356         m_aMeshAlgo->CutWithPlane(z_level_plane,normal,*m_CAD_Mesh_Grid,result);
03357         //std::list<std::vector<Base::Vector3f> >::iterator it;
03358         //std::vector<Base::Vector3f>::iterator vector_it;
03359         //checken ob wirklich ein Schnitt zustande gekommen ist
03360         if (result.size()==0)
03361         {
03362             cutok = false;
03363             //Jedes Mal ein wenig mehr Abstand für die Korrektur einfügen
03364             factor = factor+float(0.05);
03365             if (factor>=1) factor = float(0.95);
03366             //Wenn wir das erste Mal eine Korrektur machen müssen gehts zunächst mal mit Minus rein
03367             if (direction)
03368             {
03369                 z_level_plane.z = (z_level-(m_pitch*factor));
03370                 z_level_corrected = z_level_plane.z;
03371                 direction=false;
03372                 continue;
03373             }
03374             else
03375             {
03376                 z_level_plane.z = (z_level+(m_pitch*factor));
03377                 z_level_corrected = z_level_plane.z;
03378                 direction=true;
03379                 continue;
03380             }
03381         }
03382     }
03383     while (cutok==false);
03384     //for(vector_it=(*(result.begin())).begin();vector_it<(*(result.begin())).end();++vector_it)
03385     //outfile << (*vector_it).x <<","<<(*vector_it).y <<","<<(*vector_it).z<< std::endl;
03386     //outfile.close();
03387     return true;
03388 }
03389 
03390 
03391 
03392 
03393 
03394 
03395 bool cutting_tools::cut(float z_level, float min_level, TopoDS_Shape &aCutShape, float &z_level_corrected)
03396 {
03397     gp_Pnt aPlanePnt(0,0,z_level);
03398     gp_Dir aPlaneDir(0,0,1);
03399     bool cutok;
03400     //Die Richtung für die Korrektur wird hier festgelegt
03401     bool correction=true;
03402     float factor = 0.0;
03403     do
03404     {
03405         cutok = true;
03406         Handle_Geom_Plane aPlane = new Geom_Plane(aPlanePnt, aPlaneDir);
03407         BRepBuilderAPI_MakeFace Face(aPlane);
03408         BRepAlgo_Section mkCut(m_Shape, Face.Face(),Standard_False);
03409         mkCut.Approximation (Standard_True);
03410         mkCut.ComputePCurveOn1(Standard_True);
03411         mkCut.Build();
03412         //Den neuen Algorithmus checken
03413         //Edgesort aSorter(mkCut.Shape());
03414         //aSorter.Init();
03415 
03416         //Jetzt checken ob auch wirlich edges vorhanden sind
03417         TopExp_Explorer exploreShape;
03418         exploreShape.Init(mkCut.Shape(),TopAbs_EDGE);
03419         //Wenn keine Edge vorhanden ist
03420         if (!exploreShape.More())
03421         {
03422             cutok = false;
03423             //Jedes Mal ein wenig mehr Abstand für die Korrektur einfügen
03424             factor = factor+float(0.05);
03425             if (factor>=1) factor = float(0.95);
03426             //Wenn wir das erste Mal eine Korrektur machen müssen gehts zunächst mal mit Minus rein
03427             if (correction)
03428             {
03429                 aPlanePnt.SetZ(z_level-(m_pitch*factor));
03430                 z_level_corrected = float(aPlanePnt.Z());
03431                 correction=false;
03432                 continue;
03433             }
03434             else
03435             {
03436                 aPlanePnt.SetZ(z_level+(m_pitch*factor));
03437                 z_level_corrected = float(aPlanePnt.Z());
03438                 correction=true;
03439                 continue;
03440             }
03441         }
03442         //Das Shape, welches per Referenz übergeben wird jetzt mit dem geordneten Schnitt füllen
03443         aCutShape = mkCut.Shape();
03444 
03445     }
03446     while (cutok==false);
03447 
03448     return true;
03449 }
03450 
03451 
03452 
03453 
03454 
03455 bool cutting_tools::classifyShape()
03456 {
03457     TopExp_Explorer Explorer;
03458     Explorer.Init(m_Shape,TopAbs_FACE);
03459     if (!Explorer.More()) return false;
03460     //checken wieviele verschiedene Faces wir haben
03461     int k=0;
03462     for (; Explorer.More(); Explorer.Next())
03463     {
03464         k++;
03465     }
03466     std::cout <<"We have " << k << "Faces" << std::endl;
03467     //Wenn mehr als ein Face vorhanden, dann eine Membervariable setzen
03468     if (k>1) m_cad = true;
03469     return true;
03470 }
03471 
03472 
03473 
03474 /* Hier ging das alte cut los
03475 
03476 
03477 
03478 
03479  bool cutok=true;
03480     //Falls wir nur ein Face haben und keine flachen Bereiche
03481     if (m_all_cuts.empty())
03482     {
03483         //Schnitte über die Bounding Box bestimmen
03484         Bnd_Box currentBBox;
03485 
03486         Standard_Real XMin, YMin, ZMin, XMax, YMax, ZMax;
03487         BRepBndLib::Add(m_Shape, currentBBox );
03488         currentBBox.SetGap(0.0);
03489         currentBBox.Get(XMin, YMin, ZMin, XMax, YMax, ZMax);
03490         double maxlevel=Max(ZMax,ZMin);
03491         double minlevel=Min(ZMax,ZMin);
03492         int cutnumber = fabs((maxlevel-minlevel)/m_pitch);//Cast um die Nachkommastellen wegzuschneiden
03493         m_pitch = fabs(maxlevel-minlevel)/cutnumber;//m_pitch leicht korrigieren um wirklich auf die letzte Ebene zu kommen
03494 
03495   //Aktuell wird die letzte Ebene bei selbst approxmierten Flächen nicht als Bahnkurve betrachtet
03496   //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
03497         for (int i=0;i<cutnumber;++i)
03498   {
03499             //Jetzt schneiden (die oberste Ebene auslassen)
03500             double z_level = maxlevel-(i*m_pitch);
03501             gp_Pnt aPlanePnt(0,0,z_level);
03502             gp_Dir aPlaneDir(0,0,1);
03503 
03504    do
03505    {
03506     cutok = true;
03507     Handle_Geom_Plane aPlane = new Geom_Plane(aPlanePnt, aPlaneDir);
03508     BRepBuilderAPI_MakeFace Face(aPlane);
03509     BRepAlgo_Section mkCut(m_Shape, Face.Face(),Standard_False);
03510     mkCut.Approximation (Standard_True);
03511     mkCut.Build();
03512     //Jetzt checken ob auch wirlich edges vorhanden sind
03513     TopExp_Explorer exploreShape;
03514     exploreShape.Init(mkCut.Shape(),TopAbs_EDGE);
03515     //Wenn keine Edge vorhanden ist
03516     if(!exploreShape.More())
03517     {
03518      cutok = false;
03519      aPlanePnt.SetZ(z_level-(m_pitch/5));
03520      if(aPlanePnt.Z()<minlevel) aPlanePnt.SetZ(minlevel+m_pitch/5);
03521      continue;
03522     }
03523     //Weil der Punkt sich ja geändert haben könnte
03524     m_zl_wire_combination.first = aPlanePnt.Z();
03525     m_zl_wire_combination.second = ordercutShape(mkCut.Shape());
03526     //Geordnete Edges in den All_Cuts-Vector stecken
03527     m_all_cuts.push_back(m_zl_wire_combination);
03528    }while (cutok==false);
03529   }
03530         return true;
03531     }
03532     //Bei mehreren flachen Bereichen
03533     else
03534     {
03535         std::vector<float> InitialPlaneLevels;
03536   std::vector<std::pair<float,TopoDS_Wire> > atemp_storage;
03537   atemp_storage.clear();
03538         std::vector<float>::iterator temp_it;
03539         for (m_it= m_all_cuts.begin();m_it<m_all_cuts.end();++m_it)
03540         {
03541             //Die Wires filtern und z.B. bei zwei Wires auf der obersten Ebene nur die innere nehmen
03542    Bnd_Box currentBBox,BBox2;
03543    Standard_Real X1Min, Y1Min, Z1Min, X1Max, Y1Max, Z1Max,X2Min, Y2Min, Z2Min, X2Max, Y2Max, Z2Max;
03544    BRepBndLib::Add((*m_it).second, currentBBox );
03545    currentBBox.SetGap(0.0);
03546    currentBBox.Get(X1Min, Y1Min, Z1Min, X1Max, Y1Max, Z1Max);
03547    if((*(m_it+1)).first == (*m_it).first) //Wenn die beiden Wires auf der gleichen Ebene liegen.....
03548    {
03549     BRepBndLib::Add((*(m_it+1)).second,BBox2);
03550     BBox2.SetGap(0.0);
03551     BBox2.Get(X2Min,Y2Min,Z2Min,X2Max,Y2Max,Z2Max);
03552    }
03553    //Jetzt checken welche kleiner ist
03554    if(X1Min<X2Min && X1Max>X2Max && Y1Min < Y2Min && Y1Max>Y2Max) //1 ist größer
03555    {
03556     if(m_it == m_all_cuts.begin())//Wenn wir auf der obersten Ebene sind....
03557     {
03558      atemp_storage.push_back(*(m_it+1));
03559      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.
03560     }
03561     else
03562     {
03563      atemp_storage.push_back(*(m_it));
03564     }
03565    }
03566    //Mal schauen ob der Wert schon in der Liste vorhanden ist
03567             temp_it = std::find(InitialPlaneLevels.begin(),InitialPlaneLevels.end(),(*m_it).first);
03568             if (temp_it == InitialPlaneLevels.end())
03569             {
03570                 InitialPlaneLevels.push_back((*m_it).first);
03571             }
03572         }
03573   //Jetzt die flachen Bereiche der Höhe nach sortieren
03574   std::sort(InitialPlaneLevels.begin(),InitialPlaneLevels.end(),FloatHuge);
03575 
03576   //Die Schnitte müssen jetzt zwischen die flachen Stücke einsortiert werden
03577   for (temp_it=InitialPlaneLevels.begin();temp_it<InitialPlaneLevels.end();++temp_it)
03578         {
03579             //Debug cout << "Bereich" <<endl;
03580    double maxlevel=*temp_it;//Maximaler aktueller Wert
03581    if(temp_it+1==InitialPlaneLevels.end()) continue;
03582    double minlevel=*(temp_it+1);
03583    int cutnumber = fabs((maxlevel-minlevel)/m_pitch);//Cast um die Nachkommastellen wegzuschneiden
03584    m_pitch = fabs(maxlevel-minlevel)/cutnumber;
03585 
03586    for (int i=1;i<cutnumber;++i)
03587    {
03588     //Jetzt schneiden (die oberste Ebene auslassen und die unterste, da dort wieder wires kommen)
03589     double z_level = maxlevel-(i*m_pitch);
03590     gp_Pnt aPlanePnt(0,0,z_level);
03591     gp_Dir aPlaneDir(0,0,1);
03592     cutok=true;
03593     do
03594     {
03595      Handle_Geom_Plane aPlane = new Geom_Plane(aPlanePnt, aPlaneDir);
03596      BRepBuilderAPI_MakeFace Face(aPlane);
03597      BRepAlgo_Section mkCut(m_Shape, Face.Face(),Standard_False);
03598      try
03599      {
03600       mkCut.Approximation (Standard_True);
03601       mkCut.Build();
03602      }
03603      catch(...)
03604      {
03605       cutok = false;
03606       aPlanePnt.SetZ(z_level-(m_pitch/5));
03607       continue;
03608      }
03609 
03610      //Weil der Punkt sich ja geändert haben könnte
03611      m_zl_wire_combination.first = aPlanePnt.Z();
03612      m_zl_wire_combination.second = ordercutShape(mkCut.Shape());
03613      //Geordnete Edges in den All_Cuts-Vector stecken
03614      m_all_cuts.push_back(m_zl_wire_combination);
03615     }while (cutok=false);
03616 
03617    }
03618   }
03619  }
03620 }
03621 */
03622 
03623 //TopoDS_Compound  cutting_tools::getCutShape()
03624 //{
03625 //  BRep_Builder builder;
03626 //  TopoDS_Compound Comp;
03627 //  builder.MakeCompound(Comp);
03632 //  return Comp;
03633 //
03634 //}
03635 
03636 
03637 
03638 
03639 double cutting_tools::GetEdgeLength(const TopoDS_Edge& anEdge)
03640 {
03641     GProp_GProps lProps;
03642     BRepGProp::LinearProperties(anEdge,lProps);
03643     double length = lProps.Mass();
03644     return length;
03645 }
03646 

Generated on Wed Nov 23 19:00:04 2011 for FreeCAD by  doxygen 1.6.1