Approx.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002  *   Copyright (c) 2007                                                    *
00003  *   Joachim Zettler <Joachim.Zettler@gmx.de>                              *
00004  *   Human Rezai <human@mytum.de>                                          *
00005  *   Mohamad Najib Muhammad Noor <najib_bean@yahoo.co.uk>                  *
00006  *                                                                         *
00007  *   This file is part of the FreeCAD CAx development system.              *
00008  *                                                                         *
00009  *   This library is free software; you can redistribute it and/or         *
00010  *   modify it under the terms of the GNU Library General Public           *
00011  *   License as published by the Free Software Foundation; either          *
00012  *   version 2 of the License, or (at your option) any later version.      *
00013  *                                                                         *
00014  *   This library  is distributed in the hope that it will be useful,      *
00015  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00016  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
00017  *   GNU Library General Public License for more details.                  *
00018  *                                                                         *
00019  *   You should have received a copy of the GNU Library General Public     *
00020  *   License along with this library; see the file COPYING.LIB. If not,    *
00021  *   write to the Free Software Foundation, Inc., 59 Temple Place,         *
00022  *   Suite 330, Boston, MA  02111-1307, USA                                *
00023  *                                                                         *
00024  ***************************************************************************/
00025 
00026 /*****************APPROX.CPP*****************
00027 * Contains implementations from Approx.h
00028 *
00029 *
00030 *********************************************/
00031 
00032 
00033 /*********MAIN INCLUDES***********/
00034 #include "PreCompiled.h"
00035 #include "Approx.h"
00036 #include <iostream>
00037 #include <algorithm>
00038 #include <Base/Exception.h>
00039 
00040 
00041 #include <TColgp_Array2OfPnt.hxx>
00042 #include <TColStd_Array1OfReal.hxx>
00043 #include <TColStd_Array1OfInteger.hxx>
00044 #include <GeomAPI_ProjectPointOnSurf.hxx>
00045 #include <Geom_BSplineSurface.hxx>
00046 #include <BRepBuilderAPI_MakeFace.hxx>
00047 
00048 /*************BOOST***************/
00049 
00050 /********UBLAS********/
00051 #include <boost/numeric/ublas/matrix_sparse.hpp>
00052 #include <boost/numeric/ublas/blas.hpp>
00053 #include <boost/numeric/ublas/operation.hpp>
00054 #include <boost/numeric/ublas/io.hpp>
00055 
00056 /*********BINDINGS********/
00057 #include <boost/numeric/bindings/traits/ublas_matrix.hpp>
00058 #include <boost/numeric/bindings/traits/ublas_sparse.hpp>
00059 #include <boost/numeric/bindings/umfpack/umfpack.hpp>
00060 #include <boost/numeric/bindings/atlas/cblas.hpp>
00061 #include <boost/numeric/bindings/atlas/clapack.hpp>
00062 
00063 /*****ADDITIONAL FOR DEBUGGING*****/
00064 //#include <fstream>
00065 /*****NAMESPACE**/
00066 using namespace boost::numeric::bindings;
00067 
00068 Approximate::Approximate(const MeshCore::MeshKernel &m,std::vector<double> &_Cntrl, std::vector<double> &_KnotU, std::vector<double> &_KnotV,
00069                          int &_OrderU, int &_OrderV, double tol)
00070 {
00071     MinX = 0, MinY = 0, MaxX = 0;
00072     MaxY = 0;
00073         tolerance = tol;
00074         int NumPnts = m.CountPoints();  //number of points to approximate
00075         Base::BoundBox3f bbox = m.GetBoundBox(); // get bounding box
00076         double x_len = bbox.LengthX();
00077         double y_len = bbox.LengthY();
00078     
00079         LocalMesh = m;  //make a copy...
00080 
00081 
00082         //Initialize the NURB
00083     MainNurb.DegreeU = 3;
00084     MainNurb.DegreeV = 3;
00085     MainNurb.MaxU = std::max<int>(MainNurb.DegreeU+1, (int)sqrt(double(NumPnts)*y_len/x_len));
00086     MainNurb.MaxV = std::max<int>(MainNurb.DegreeV+1, (int)sqrt(double(NumPnts)*x_len/y_len));
00087     
00088     GenerateUniformKnot(MainNurb.MaxU,MainNurb.DegreeU,MainNurb.KnotU);
00089     GenerateUniformKnot(MainNurb.MaxV,MainNurb.DegreeV,MainNurb.KnotV);
00090     MainNurb.MaxKnotU = MainNurb.KnotU.size();
00091     MainNurb.MaxKnotV = MainNurb.KnotV.size();
00092     
00093         //GOTO Main program
00094     ApproxMain();
00095 
00096         ofstream anOutputFile;
00097         anOutputFile.open("c:/approx_build_surface.txt");
00098         
00099         anOutputFile << "start building surface" << endl;
00100     
00101         //Copying the Output
00102     //mesh = ParameterMesh;
00103     _Cntrl = MainNurb.CntrlArray;
00104     _KnotU = MainNurb.KnotU;
00105     _KnotV = MainNurb.KnotV;
00106     _OrderU = MainNurb.DegreeU + 1;
00107     _OrderV = MainNurb.DegreeV + 1;
00108 
00109         gp_Pnt pnt;
00110     TColgp_Array2OfPnt Poles(1,MainNurb.MaxU+1, 1,MainNurb.MaxV+1);
00111 
00112     for(int j=0; j< (MainNurb.MaxV+1); ++j)
00113         {       
00114                 for(int i=0; i < (MainNurb.MaxU+1); ++i)
00115                 {
00116                         pnt.SetX(_Cntrl[3*i   + j*3*(MainNurb.MaxU+1)]);
00117                         pnt.SetY(_Cntrl[3*i+1 + j*3*(MainNurb.MaxU+1)]);
00118                         pnt.SetZ(_Cntrl[3*i+2 + j*3*(MainNurb.MaxU+1)]);
00119 
00120                         Poles.SetValue(i+1,j+1,pnt);
00121                 }
00122     }
00123 
00124         anOutputFile << "control points done" << endl;
00125 
00126     int c=1;
00127     for (unsigned int i=0; i<_KnotU.size()-1; ++i)
00128     {
00129         if (_KnotU[i+1] != _KnotU[i])
00130         {
00131             ++c;
00132         }
00133     }
00134 
00135 
00136     TColStd_Array1OfReal    UKnots(1,c);
00137     TColStd_Array1OfInteger UMults(1,c);
00138 
00139     c=1;
00140     for (unsigned int i=0; i<_KnotV.size()-1; ++i)
00141     {
00142         if (_KnotV[i+1] != _KnotV[i])
00143         {
00144             ++c;
00145         }
00146     }
00147 
00148 
00149     TColStd_Array1OfReal    VKnots(1,c);
00150     TColStd_Array1OfInteger VMults(1,c);
00151 
00152     int d=0;
00153     c=1;
00154     for (unsigned int i=0; i<_KnotU.size(); ++i)
00155     {
00156         if (_KnotU[i+1] != _KnotU[i])
00157         {
00158             UKnots.SetValue(d+1,_KnotU[i]);
00159             UMults.SetValue(d+1,c);
00160             ++d;
00161             c=1;
00162 
00163         }
00164         else
00165         {
00166             ++c;
00167         }
00168 
00169         if (i==(_KnotU.size()-2))
00170         {
00171             UKnots.SetValue(d+1,_KnotU[i+1]);
00172             UMults.SetValue(d+1,c);
00173             break;
00174         }
00175     }
00176 
00177     d=0;
00178     c=1;
00179     for (unsigned int i=0; i<_KnotV.size(); ++i)
00180     {
00181         if (_KnotV[i+1] != _KnotV[i])
00182         {
00183             VKnots.SetValue(d+1,_KnotV[i]);
00184             VMults.SetValue(d+1,c);
00185             ++d;
00186             c=1;
00187 
00188         }
00189         else
00190         {
00191             ++c;
00192         }
00193 
00194         if (i==(_KnotV.size()-2))
00195         {
00196             VKnots.SetValue(d+1,_KnotV[i+1]);
00197             VMults.SetValue(d+1,c);
00198             break;
00199         }
00200     }
00201 
00202     /*cout << "UKnots: " << endl;
00203     for(int i=0; i<UKnots.Upper(); ++i)
00204      cout << UKnots.Value(i+1) << ", ";
00205     cout << endl;
00206 
00207 
00208     cout << "UMults: " << endl;
00209     for(int i=0; i<UMults.Upper(); ++i)
00210      cout << UMults.Value(i+1) << ", ";
00211     cout << endl;
00212 
00213 
00214     cout << "VKnots: " << endl;
00215     for(int i=0; i<VKnots.Upper(); ++i)
00216      cout << VKnots.Value(i+1) << ", ";
00217     cout << endl;
00218 
00219 
00220     cout << "VMults: " << endl;
00221     for(int i=0; i<VMults.Upper(); ++i)
00222      cout << VMults.Value(i+1) << ", ";
00223     cout << endl;*/
00224 
00225 
00226 
00227 
00228     const Handle(Geom_BSplineSurface) surface = new Geom_BSplineSurface(
00229         Poles,        // const TColgp_Array2OfPnt &    Poles,
00230         UKnots,       // const TColStd_Array1OfReal &   UKnots,
00231         VKnots,       // const TColStd_Array1OfReal &   VKnots,
00232         UMults,       // const TColStd_Array1OfInteger &   UMults,
00233         VMults,       // const TColStd_Array1OfInteger &   VMults,
00234         3,            // const Standard_Integer   UDegree,
00235         3             // const Standard_Integer   VDegree,
00236         // const Standard_Boolean   UPeriodic = Standard_False,
00237         // const Standard_Boolean   VPeriodic = Standard_False
00238     );
00239 
00240     aAdaptorSurface.Load(surface);
00241 
00242         
00243         
00244 }
00245 
00246 Approximate::~Approximate()
00247 {
00248 }
00251 void Approximate::ApproxMain()
00252 {
00253     std::cout << "BEGIN COMPUTE NURB" << std::endl;  
00254     ParameterBoundary();
00255     ParameterInnerPoints();
00256 
00257     ErrorApprox();
00258     std::cout << "END COMPUTE NURB" << std::endl;
00259 }
00260 
00261 
00269 void Approximate::ParameterBoundary()
00270 {
00271     std::cout << "Computing the parameter for the outer boundary..." << std::endl;
00272 
00273     ParameterMesh = LocalMesh;
00274     MeshCore::MeshAlgorithm algo(ParameterMesh);
00275     MeshCore::MeshPointIterator p_it(ParameterMesh);
00276     NumOfPoints = LocalMesh.CountPoints();
00277     NumOfOuterPoints = 0;
00278     double distance = 0;
00279     unsigned int a;
00280     std::vector<unsigned long> CornerIndex;
00281     std::vector<double> Pointdistance;
00282     std::vector<unsigned long>::iterator vec_it;
00283     std::vector <Base::Vector3f>::iterator pnt_it;
00284 
00285     //Get BoundariesIndex and BoundariesPoints and extract it to v_neighbour
00286     algo.GetMeshBorders(BoundariesIndex);
00287     algo.GetMeshBorders(BoundariesPoints);
00288     std::list< std::vector <unsigned long> >::iterator bInd = BoundariesIndex.begin();
00289     std::list< std::vector <Base::Vector3f> >::iterator bPnt = BoundariesPoints.begin();
00290     std::vector <unsigned long> v_neighbour = *bInd;
00291     std::vector <Base::Vector3f> v_pnts = *bPnt;
00292 
00293     Base::BoundBox3f BoundBox = ParameterMesh.GetBoundBox();
00294 
00295     //Resize the needed arrays
00296     NumOfOuterPoints = v_neighbour.size()-1;
00297     BoundariesX.resize(NumOfOuterPoints);
00298     BoundariesY.resize(NumOfOuterPoints);
00299     UnparamBoundariesX.resize(NumOfOuterPoints);
00300     UnparamBoundariesY.resize(NumOfOuterPoints);
00301     UnparamBoundariesZ.resize(NumOfOuterPoints);
00302     std::vector <unsigned long> nei_tmp(NumOfOuterPoints);
00303     std::vector <Base::Vector3f> pnts_tmp(NumOfOuterPoints);
00304 
00305 
00306     //Look for corner points
00307     std::cout << "Looking for corners..." << std::endl;
00308     CornerIndex.push_back(FindCorner(BoundBox.MinX,BoundBox.MinY,v_neighbour,v_pnts));  //FindCorner(Parameter1, Parameter2, neighbour_list, mesh)
00309     CornerIndex.push_back(FindCorner(BoundBox.MaxX,BoundBox.MinY,v_neighbour,v_pnts));
00310     CornerIndex.push_back(FindCorner(BoundBox.MaxX,BoundBox.MaxY,v_neighbour,v_pnts));
00311     CornerIndex.push_back(FindCorner(BoundBox.MinX,BoundBox.MaxY,v_neighbour,v_pnts));
00312 
00313     //Redo the list, start from (0,0), we are using the arrays in nei_tmp and pnts_tmp
00314     vec_it = find(v_neighbour.begin(),v_neighbour.end(),CornerIndex[0]);
00315     pnt_it = find(v_pnts.begin(), v_pnts.end(), LocalMesh.GetPoint(CornerIndex[0]));
00316     for (unsigned int i = 0; i < v_neighbour.size()-1; i++)
00317     {
00318         nei_tmp[i] = *vec_it;
00319         pnts_tmp[i] = *pnt_it;
00320         UnparamBoundariesX[i] = (*pnt_it).x;
00321         UnparamBoundariesY[i] = (*pnt_it).y;
00322         UnparamBoundariesZ[i] = (*pnt_it).z;
00323         ++vec_it;
00324         ++pnt_it;
00325         if (vec_it == v_neighbour.end()-1)
00326         {
00327             vec_it = v_neighbour.begin();
00328             pnt_it = v_pnts.begin();
00329             a = i;
00330         }
00331 
00332 
00333     }
00334     v_pnts.clear();
00335     v_pnts = pnts_tmp;
00336 
00337     std::cout << "Parametirizing..." << std::endl;
00338     //Parameter the boundaries
00339 
00340     //Parameter the _ Boundaries
00341     //v_handle = CornerIndex[0];
00342     double totaldistance = 0;
00343     unsigned int g = 0;
00344     unsigned int temp1 = g;
00345     unsigned int temp2 = g;
00346     do  //Get distance first
00347     {
00348         distance = sqrt(((v_pnts[g+1][0] - v_pnts[g][0])*(v_pnts[g+1][0] - v_pnts[g][0]))
00349                         + ((v_pnts[g+1][1] - v_pnts[g][1])*(v_pnts[g+1][1] - v_pnts[g][1])));
00350         Pointdistance.push_back(distance);
00351         totaldistance += distance;
00352         g++;
00353     }
00354     while ((vec_it = find(CornerIndex.begin(), CornerIndex.end(), nei_tmp[g])) == CornerIndex.end());
00355 
00356     //Secure current g-counter and reinitialize g-counter to initial value
00357     temp1 = g;
00358     g = temp2;
00359 
00360     //Parameter the first point, fill up the list we are using
00361     pnts_tmp[g][0] = 0.0f, pnts_tmp[g][1] = 0.0f;
00362     BoundariesX[g] = pnts_tmp[g][0], BoundariesY[g] = pnts_tmp[g][1];
00363     g++;
00364     for (unsigned int i = 0; i < Pointdistance.size() - 1;i++)
00365     {
00366         //Parametirizing
00367         //0 < X < 1, Y = 0.0, Z = don't care lalalala
00368         pnts_tmp[g][0] = (Pointdistance[i]/totaldistance)+pnts_tmp[g-1][0], pnts_tmp[g][1] = 0.0f;
00369         BoundariesX[g] = pnts_tmp[g][0], BoundariesY[g] = pnts_tmp[g][1];
00370         g++;
00371     }
00372 
00373     //Secure the counters and reinitialize the things we needed
00374     g = temp1;
00375     temp2 = g;
00376     Pointdistance.clear();
00377     totaldistance = 0;
00378 
00379     //Parameter the -| boundary
00380     do  //Get distance first
00381     {
00382         distance = sqrt(((v_pnts[g+1][0] - v_pnts[g][0])*(v_pnts[g+1][0] - v_pnts[g][0]))
00383                         + ((v_pnts[g+1][1] - v_pnts[g][1])*(v_pnts[g+1][1] - v_pnts[g][1])));
00384         Pointdistance.push_back(distance);
00385         totaldistance += distance;
00386         g++;
00387     }
00388     while ((vec_it = find(CornerIndex.begin(), CornerIndex.end(), nei_tmp[g])) == CornerIndex.end());
00389 
00390     //Secure current g-counter and reinitialize g-counter to initial value
00391     temp1 = g;
00392     g = temp2;
00393     pnts_tmp[g][0] = 1.0f, pnts_tmp[g][1] = 0.0f;
00394     BoundariesX[g] = pnts_tmp[g][0], BoundariesY[g] = pnts_tmp[g][1];
00395     g++;
00396     for (unsigned int i = 0; i < Pointdistance.size() - 1;i++)
00397     {
00398         //Parametirizing
00399         //X = 1, 0 < Y < 1, Z = don't care lalalala
00400         pnts_tmp[g][0] = 1.0f, pnts_tmp[g][1] = (Pointdistance[i]/totaldistance)+pnts_tmp[g-1][1];
00401         BoundariesX[g] = pnts_tmp[g][0], BoundariesY[g] = pnts_tmp[g][1];
00402         g++;
00403     }
00404 
00405     //Secure the counters and reinitialize´the things we needed
00406     g = temp1;
00407     temp2 = g;
00408     Pointdistance.clear();
00409     totaldistance = 0;
00410 
00411     //Parameter the - boundary
00412     do  //Get distance first
00413     {
00414         distance = sqrt(((v_pnts[g+1][0] - v_pnts[g][0])*(v_pnts[g+1][0] - v_pnts[g][0]))
00415                         + ((v_pnts[g+1][1] - v_pnts[g][1])*(v_pnts[g+1][1] - v_pnts[g][1])));
00416         Pointdistance.push_back(distance);
00417         totaldistance += distance;
00418         g++;
00419     }
00420     while ((vec_it = find(CornerIndex.begin(), CornerIndex.end(), nei_tmp[g])) == CornerIndex.end());
00421 
00422     //Secure current g-counter and reinitialize g-counter to initial value
00423     temp1 = g;
00424     g = temp2;
00425     pnts_tmp[g][0] = 1.0f, pnts_tmp[g][1] = 1.0f;
00426     float prev = pnts_tmp[g][0];
00427     BoundariesX[g] = pnts_tmp[g][0], BoundariesY[g] = pnts_tmp[g][1];
00428     g++;
00429     for (unsigned int i = 0; i < Pointdistance.size() - 1;i++)
00430     {
00431         //Parametirizing
00432         //0 < X < 1,Y = 1, Z = don't care lalalala
00433         pnts_tmp[g][0] = (Pointdistance[i]/totaldistance)+prev, pnts_tmp[g][1] = 1.0f;
00434         prev = pnts_tmp[g][0];
00435         pnts_tmp[g][0] = 2.0f - pnts_tmp[g][0];
00436         BoundariesX[g] = pnts_tmp[g][0], BoundariesY[g] = pnts_tmp[g][1];
00437         g++;
00438     }
00439 
00440     //Secure the counters and reinitialize´the things we needed
00441     g = temp1;
00442     temp2 = g;
00443     Pointdistance.clear();
00444     totaldistance = 0;
00445 
00446     //Parameter the |- boundary
00447     do  //Get distance first
00448     {
00449         distance = sqrt(((v_pnts[g+1][0] - v_pnts[g][0])*(v_pnts[g+1][0] - v_pnts[g][0]))
00450                         + ((v_pnts[g+1][1] - v_pnts[g][1])*(v_pnts[g+1][1] - v_pnts[g][1])));
00451         Pointdistance.push_back(distance);
00452         totaldistance += distance;
00453         g++;
00454         if (g+1 == v_pnts.size())
00455         {
00456             distance = sqrt(((v_pnts[0][0] - v_pnts[g][0])*(v_pnts[0][0] - v_pnts[g][0]))
00457                             + ((v_pnts[0][1] - v_pnts[g][1])*(v_pnts[0][1] - v_pnts[g][1])));
00458             Pointdistance.push_back(distance);
00459             totaldistance += distance;
00460             break;
00461         }
00462     }
00463     while ((vec_it = find(CornerIndex.begin(), CornerIndex.end(), nei_tmp[g])) == CornerIndex.end());
00464 
00465     //Secure current g-counter and reinitialize g-counter to initial value
00466     temp1 = g;
00467     g = temp2;
00468     pnts_tmp[g][0] = 0.0f, pnts_tmp[g][1] = 1.0f;
00469     prev = pnts_tmp[g][1];
00470     BoundariesX[g] = pnts_tmp[g][0], BoundariesY[g] = pnts_tmp[g][1];
00471     g++;
00472     for (unsigned int i = 0; i < Pointdistance.size() - 1;i++)
00473     {
00474         //Parametirizing
00475         //0 < X < 1, Y = 0, Z = don't care lalalala
00476         pnts_tmp[g][0] = 0.0, pnts_tmp[g][1] = (Pointdistance[i]/totaldistance)+prev;
00477         prev = pnts_tmp[g][1];
00478         pnts_tmp[g][1] = 2.0f - pnts_tmp[g][1];
00479         BoundariesX[g] = pnts_tmp[g][0], BoundariesY[g] = pnts_tmp[g][1];
00480         g++;
00481     }
00482 
00483     //Secure the counters and reinitialize´the things we needed
00484     g = temp1;
00485     temp2 = g;
00486     Pointdistance.clear();
00487     totaldistance = 0;
00488 
00489     ParameterX.resize(NumOfOuterPoints);
00490     ParameterY.resize(NumOfOuterPoints);
00491     int count = 0;
00492     NumOfInnerPoints = NumOfPoints - NumOfOuterPoints;
00493     mapper.resize(NumOfPoints);
00494     MeshCore::MeshPointIterator v_it(LocalMesh);
00495     a = 0;
00496     int b = 0;
00497     for (v_it.Begin(); !v_it.EndReached(); ++v_it) //For all points...
00498     {
00499         if ((vec_it = find(nei_tmp.begin(), nei_tmp.end(), v_it.Position())) != nei_tmp.end()) //...is it boundary?
00500         {
00501             //Yes
00502             ParameterX[count] = pnts_tmp[int(vec_it-nei_tmp.begin())][0];
00503             ParameterY[count] = pnts_tmp[int(vec_it-nei_tmp.begin())][1];
00504             mapper[v_it.Position()] = a+NumOfInnerPoints;
00505             a++, count++;
00506         }
00507         else
00508         {
00509             //No
00510             mapper[v_it.Position()] = b;
00511             b++;
00512         }
00513     }
00514 }
00521 void Approximate::ParameterInnerPoints()
00522 {
00523     std::cout << "Computing the parameter for the inner points..." << std::endl;
00524     MeshCore::MeshPointIterator v_it(LocalMesh);
00525     MeshCore::MeshAlgorithm algo(LocalMesh);
00526     MeshCore::MeshRefPointToPoints vv_it(LocalMesh);
00527     MeshCore::MeshRefPointToFacets vf_it(LocalMesh);
00528     std::set<unsigned long> PntNei;
00529     std::set<unsigned long> FacetNei;
00530     ublas::compressed_matrix<double> Lambda(NumOfInnerPoints, NumOfPoints);
00531     int count = 0;
00532 
00533     std::cout << "Prepping the Lambda" << std::endl;
00534     std::list< std::vector <unsigned long> >::iterator bInd = BoundariesIndex.begin();
00535     std::vector <unsigned long> neiIndexes = *bInd;
00536     std::vector <unsigned long>::iterator vec_it;
00537     for (v_it.Begin(); !v_it.EndReached(); ++v_it)
00538     {
00539         if ((vec_it = find(neiIndexes.begin(), neiIndexes.end(), v_it.Position())) == neiIndexes.end())
00540         {
00541 
00542             std::vector<Base::Vector3f> NeiPnts;
00543             std::vector<unsigned long> nei;
00544             std::vector<unsigned int>::iterator nei_it;
00545             PntNei = vv_it[v_it.Position()];
00546             FacetNei = vf_it[v_it.Position()];
00547             ReorderNeighbourList(PntNei,FacetNei,nei,v_it.Position());
00548             std::vector<double> Angle;
00549             std::vector<double> Magnitude;
00550             Base::Vector3f CurrentPoint(*v_it);
00551             double TotAngle = 0;
00552             unsigned int NumOfNeighbour = PntNei.size();
00553             unsigned int i = 0;
00554             //Angle and magnitude calculations for projection.
00555             //With respect to CurrentPoint
00556             while (i < NumOfNeighbour)
00557             {
00558                 if (i+1 != NumOfNeighbour)
00559                 {
00560                     Base::Vector3f CurrentNeighbour(LocalMesh.GetPoint(nei[i]));
00561                     Base::Vector3f NextNeighbour(LocalMesh.GetPoint(nei[i+1]));
00562                     double ang = CalcAngle(CurrentNeighbour, CurrentPoint, NextNeighbour);
00563                     double magn = sqrt((CurrentNeighbour - CurrentPoint) * (CurrentNeighbour - CurrentPoint));
00564                     Angle.push_back(ang);
00565                     Magnitude.push_back(magn);
00566                     TotAngle += ang;
00567                     i++;
00568                 }
00569                 else
00570                 {
00571                     Base::Vector3f CurrentNeighbour(LocalMesh.GetPoint(nei[i]));
00572                     Base::Vector3f NextNeighbour(LocalMesh.GetPoint(nei[0]));
00573                     double ang = CalcAngle(CurrentNeighbour, CurrentPoint, NextNeighbour);
00574                     double magn = sqrt((CurrentNeighbour - CurrentPoint) * (CurrentNeighbour - CurrentPoint));
00575                     Angle.push_back(ang);
00576                     Magnitude.push_back(magn);
00577                     TotAngle += ang;
00578                     i++;
00579                 }
00580 
00581             }
00582             //Projection
00583             //Current point is (0,0), First neighbour is on the X-Axis (y = 0), all other are projected
00584             //depending on angle and magnitude
00585             Base::Vector3f CurrentNeighbour(Magnitude[0],0.0,0.0);
00586             NeiPnts.push_back(CurrentNeighbour);
00587             double alpha = 0;
00588             unsigned int k = 0;
00589             for (unsigned int i = 1; i < NumOfNeighbour; i++)
00590             {
00591                 alpha = alpha + ((2 * D_PI * Angle[i-1]) / TotAngle);
00592                 double x_pnt = Magnitude[i] * cos(alpha), y_pnt = Magnitude[i] * sin(alpha);
00593                 Base::Vector3f NewPoint(x_pnt,y_pnt,0.0);
00594                 NeiPnts.push_back(NewPoint);
00595                 ++k;
00596 
00597             }
00598             k = 0;
00599             //Preparing the needed matrix for iterating
00600             std::vector< std::vector<double> > Mu(NumOfNeighbour, std::vector<double>(NumOfNeighbour, 0.0));  //Mu Matrix
00601             std::vector< std::vector<double> > MMatrix(2, std::vector<double>(2,0.0));  //for the solver
00602             std::vector<double> bMatrix(2,0.0);
00603             std::vector<double> lMatrix(2,0.0);
00604             if (NumOfNeighbour > 3) //if NumOfNeighbour > 3...
00605             {
00606                 for (k = 0; k < NumOfNeighbour;k++)  //...for all neighbours...
00607                 {
00608                     for (unsigned int l = k+1; l < NumOfNeighbour+k; l++) //...another iterator iterate through other neighbour
00609                     {
00610                         MMatrix[0][0] = NeiPnts[(unsigned int)fmod((double)l,(double)NumOfNeighbour)][0] -
00611                                         NeiPnts[(unsigned int)fmod((double)l-1,(double)NumOfNeighbour)][0];
00612                         MMatrix[1][0] =  NeiPnts[(unsigned int)fmod((double)l,(double)NumOfNeighbour)][1] -
00613                                          NeiPnts[(unsigned int)fmod((double)l-1,(double)NumOfNeighbour)][1];
00614                         MMatrix[0][1] = NeiPnts[k][0];
00615                         MMatrix[1][1] = NeiPnts[k][1];
00616 
00617                         bMatrix[0] = -NeiPnts[(unsigned int)fmod((double)l-1,(double)NumOfNeighbour)][0];
00618                         bMatrix[1] = -NeiPnts[(unsigned int)fmod((double)l-1,(double)NumOfNeighbour)][1];
00619 
00620                         if (det2(MMatrix) != 0)
00621                         {
00622                             CramerSolve(MMatrix, bMatrix, lMatrix);  //Solve it
00623                             if (lMatrix[0] <= 1.00001f && lMatrix[0] >= 0.0f && lMatrix[1] > 0.0f) //Condition for a solution
00624                             {
00625                                 unsigned int r = (unsigned int)fmod((double)l-1,(double)NumOfNeighbour);
00626                                 MMatrix[0][0] = NeiPnts[k][0] -
00627                                                 NeiPnts[(unsigned int)fmod((double)l,(double)NumOfNeighbour)][0];
00628                                 MMatrix[1][0] = NeiPnts[k][1] -
00629                                                 NeiPnts[(unsigned int)fmod((double)l,(double)NumOfNeighbour)][1];
00630                                 MMatrix[0][1] = NeiPnts[(unsigned int)fmod((double)l-1,(double)NumOfNeighbour)][0] -
00631                                                 NeiPnts[(unsigned int)fmod((double)l,(double)NumOfNeighbour)][0];
00632                                 MMatrix[1][1] = NeiPnts[(unsigned int)fmod((double)l-1,(double)NumOfNeighbour)][1] -
00633                                                 NeiPnts[(unsigned int)fmod((double)l,(double)NumOfNeighbour)][1];
00634 
00635                                 bMatrix[0] = -NeiPnts[(unsigned int)fmod((double)l,(double)NumOfNeighbour)][0];
00636                                 bMatrix[1] = -NeiPnts[(unsigned int)fmod((double)l,(double)NumOfNeighbour)][1];
00637                                 CramerSolve(MMatrix, bMatrix, lMatrix);  //Solve it
00638 
00639                                 Mu[k][k] = fabs(lMatrix[0]);  //Solution found, fill up the Mu
00640                                 Mu[r][k] = fabs(lMatrix[1]);
00641                                 if ((unsigned int)fmod((double)r,(double)NumOfNeighbour)+1 == NumOfNeighbour)
00642                                     Mu[0][k] = 1 -lMatrix[0] - lMatrix[1];
00643                                 else
00644                                     Mu[(unsigned int)fmod((double)r,(double)NumOfNeighbour)+1][k] = 1 -lMatrix[0] - lMatrix[1];
00645                                 break;
00646 
00647                             }
00648                         }
00649                     }
00650                 }
00651                 //Fill in the lambda
00652                 /*for(int j = 0; j < NumOfNeighbour; j++)  //quick checker, if any bug comes out, one of
00653                 {             //possible bugspawn is here
00654                  double sum = 0;
00655                  for(int k = 0; k < NumOfNeighbour; k++)
00656                   sum += Mu[k][j];
00657 
00658                  if(sum < 0.9999 || sum > 1.0001)
00659                  {
00660                   std::cout << "Mu is not correct.\nSum: " << sum <<
00661                   "\nCount: " << count << "\nNumOfNeighbour: " << NumOfNeighbour << std::endl;
00662                   getchar();
00663                  }
00664 
00665                 }*/
00666                 for (unsigned int j = 0; j < NumOfNeighbour; j++)
00667                 {
00668                     double sum = 0;
00669                     for (unsigned int k = 0; k < NumOfNeighbour; k++)
00670                         sum += Mu[j][k];
00671 
00672                     Lambda(count,mapper[nei[j]]) = sum/NumOfNeighbour;
00673                 }
00674                 count++;
00675             }
00676             else if (NumOfNeighbour == 3) //If NumOfNeighbour == 3...
00677             {
00678                 Base::Vector3f Point1(NeiPnts[0]);
00679                 Base::Vector3f Point2(NeiPnts[1]);
00680                 Base::Vector3f Point3(NeiPnts[2]);
00681                 Base::Vector3f Zeroes(0,0,0);
00682                 double A = AreaTriangle(Point1,Point2,Point3);
00683 
00684                 Lambda(count,mapper[nei[0]]) =
00685                     AreaTriangle(Zeroes,Point2,Point3) / A;
00686 
00687                 Lambda(count,mapper[nei[1]]) =
00688                     AreaTriangle(Point1,Zeroes,Point3) / A;
00689 
00690                 Lambda(count,mapper[nei[2]]) =
00691                     AreaTriangle(Point1,Point2,Zeroes) / A;
00692 
00693                 count++;
00694             }
00695             else   //Can an inside point have less than 3 neighbours...?
00696             {
00697                 throw Base::Exception("Something's wrong here. Less than 3 Neighbour");
00698             }
00699         }
00700     }
00701 
00702     //Now, we split the lambda matrix
00703     //Using the compressed matrix class from boost
00704     std::cout << "Splitting the lambdas..." << std::endl;
00705     ublas::compressed_matrix<double, ublas::column_major, 0, ublas::unbounded_array<int>, ublas::unbounded_array<double> >
00706     UpperTerm(NumOfInnerPoints, NumOfInnerPoints);
00707     ublas::compressed_matrix<double, ublas::column_major> OutLambda(NumOfInnerPoints, NumOfOuterPoints);
00708     //We need to extract this columnwise, and (i,j) is a row-major style of numbering...
00709     //Also, later we need to I - Upperterm, I := IdentityMatrix, this will also be done in this step
00710     for (int i = 0; i < NumOfInnerPoints; i++)
00711     {
00712         for (int j = 0; j < NumOfInnerPoints; j++)
00713         {
00714             if (Lambda(i,j) != 0)
00715                 UpperTerm(i,j) = -Lambda(i,j);
00716             else if (i == j)
00717                 UpperTerm(i,j) = 1.0 - Lambda(i,j);
00718         }
00719     }
00720 
00721     for (int j = NumOfInnerPoints, k = 0; j < NumOfPoints; j++, k++)
00722     {
00723         for (int i = 0; i < NumOfInnerPoints; i++)
00724         {
00725             if (Lambda(i,j) != 0)
00726                 OutLambda(i,k) = Lambda(i,j);
00727         }
00728     }
00729 
00730     //Result Storage
00731     ublas::vector<double> xResult(NumOfInnerPoints);
00732     ublas::vector<double> MultResult(NumOfInnerPoints);
00733     ublas::vector<double> yResult(NumOfInnerPoints);
00734 
00735         ofstream anOutputFile;
00736         anOutputFile.open("c:/approx_param_log.txt");
00737         anOutputFile << 1 << endl;
00738     //Solving the X Term
00739     std::cout << "Solving the X Term..." << std::endl;
00740     //atlas::gemm and atlas::gemv can't work with sparse matrices it seems, therefore using axpy_prod
00741     ublas::axpy_prod(OutLambda, ParameterX, MultResult);
00742         anOutputFile << 2 << endl;
00743     bindings::umfpack::umf_solve (UpperTerm, xResult,MultResult );  //umfpack to solve sparse matrices equations
00744         anOutputFile << 3 << endl;
00745     //Solving the Y Term
00746     std::cout << "Solving the Y Term..." << std::endl;
00747     ublas::axpy_prod(OutLambda, ParameterY, MultResult);
00748         anOutputFile << 4 << endl;
00749     bindings::umfpack::umf_solve (UpperTerm, yResult, MultResult);
00750         anOutputFile << 5 << endl;
00751     std::cout << "Replacing the results.." << std::endl;
00752 
00753         
00754 
00755     //Another counter, temporary storage for old ParameterX and ParameterY, and resizing to include ALL points now
00756     unsigned int s = 0;
00757     unsigned int b = 0;
00758 
00759     ublas::vector<double> tempox = ParameterX;
00760     ublas::vector<double> tempoy = ParameterY;
00761     ParameterX.clear(), ParameterX.resize(NumOfPoints);
00762     ParameterY.clear(), ParameterY.resize(NumOfPoints);
00763     UnparamX.resize(NumOfPoints), UnparamY.resize(NumOfPoints),UnparamZ.resize(NumOfPoints);
00764     //Reextract the boundaries list
00765         anOutputFile << 6 << endl;
00766     std::vector <unsigned long> boundarieslist = *bInd;
00767 
00768         anOutputFile << 7 << endl;
00769 
00770 
00771 
00772         /**************************/
00773         MeshParam = LocalMesh;
00774         MeshCore::MeshPointArray pntArr= MeshParam.GetPoints();
00775         MeshCore::MeshFacetArray fctArr= MeshParam.GetFacets();
00776         /**************************/
00777     
00778         
00779         for (v_it.Begin(); !v_it.EndReached(); ++v_it)
00780     {
00781                 anOutputFile << 0 << endl;
00782         //Inner Points goes into the beginning of the list
00783         if ((vec_it = find(boundarieslist.begin(), boundarieslist.end(), v_it.Position())) == boundarieslist.end())
00784         {
00785             ParameterX[s] = xResult[s];
00786             ParameterY[s] = yResult[s];
00787 
00788                         pntArr[v_it.Position()].x = ParameterX[s];
00789                         pntArr[v_it.Position()].y = ParameterY[s];
00790                         pntArr[v_it.Position()].z = 0;
00791 
00792             UnparamX[s] = LocalMesh.GetPoint(v_it.Position())[0];
00793             UnparamY[s] = LocalMesh.GetPoint(v_it.Position())[1];
00794             UnparamZ[s] = LocalMesh.GetPoint(v_it.Position())[2];
00795             s++;
00796         }
00797         //Boundaries goes into the end of the list
00798         else
00799         {
00800             ParameterX[NumOfInnerPoints+b] = tempox[b];
00801             ParameterY[NumOfInnerPoints+b] = tempoy[b];
00802 
00803                         pntArr[v_it.Position()].x = ParameterX[NumOfInnerPoints+b];
00804                         pntArr[v_it.Position()].y = ParameterY[NumOfInnerPoints+b];
00805                         pntArr[v_it.Position()].z = 0;
00806 
00807             UnparamX[NumOfInnerPoints+b] = LocalMesh.GetPoint(v_it.Position())[0];
00808             UnparamY[NumOfInnerPoints+b] = LocalMesh.GetPoint(v_it.Position())[1];
00809             UnparamZ[NumOfInnerPoints+b] = LocalMesh.GetPoint(v_it.Position())[2];
00810             b++;
00811         }
00812     }
00813 
00814         anOutputFile << 8 << endl;
00815         MeshParam.Assign(pntArr,fctArr);
00816     anOutputFile << 9 << endl;
00817 
00818     std::cout << "DONE" << std::endl;
00819     std::cout << "Information about the meshes:-" << std::endl;
00820     std::cout << "Number of Points: " << NumOfPoints << std::endl;
00821     std::cout << "Number of Inner Points: " << NumOfInnerPoints << std::endl;
00822     std::cout << "Number of Outer Points: " << NumOfOuterPoints << std::endl;
00823     //clear the mesh, we will continue working with the lists we have made
00824     ParameterMesh.Clear();
00825         anOutputFile << 10 << endl;
00826     LocalMesh.Clear();
00827         anOutputFile << 11 << endl;
00828         anOutputFile.close();
00829 
00830 }
00831 
00832 
00837 void Approximate::ErrorApprox()
00838 {
00839         ofstream anOutputFile;
00840         anOutputFile.open("c:/approx_param_log.txt");
00841 
00842     anOutputFile << "Begin constructing NURB for first pass" << std::endl;
00843     double max_err = 0;
00844     bool ErrThere = true;  //for breaking the while
00845     int h = 0;
00846         int cnt = 0;
00847     double av = 0, c2 = 0;
00848         double lam;
00849     
00850         anOutputFile << "Constructing" << std::endl;
00851     ublas::matrix<double> C_Temp(NumOfPoints,3);
00852     anOutputFile << "C_Temp succesfully constructed" << std::endl;
00853     //Time saving... C_Temp matrix is constant for all time
00854 
00855         anOutputFile << "number of points: " << NumOfPoints << std::endl;
00856     std::vector <double> err_w(NumOfPoints);
00857         anOutputFile << "checkpoint 1 " << std::endl;
00858     for (int i=1; i<NumOfPoints; i++)
00859         err_w[i] = 1;
00860 
00861         anOutputFile << "checkpoint 2 " << std::endl;
00862         int g = 1;
00863 
00864     while(ErrThere)
00865     {
00866                 anOutputFile << "checkpoint 3 " << std::endl;
00867                 anOutputFile << "checkpoint 3 " << std::endl;
00868                 anOutputFile << "size(B_Matrix): " <<  NumOfPoints << " x " << (MainNurb.MaxU+1)*(MainNurb.MaxV+1) << std::endl;
00869         ublas::matrix<double> B_Matrix(NumOfPoints,(MainNurb.MaxU+1)*(MainNurb.MaxV+1));
00870                 anOutputFile << "********************************" << endl;
00871         anOutputFile << "B_Matrix succesfully constructed" << std::endl;
00872         anOutputFile << "Preparing B-Matrix..." << std::endl;
00873 
00874         std::vector<double> N_u(MainNurb.MaxU+1, 0.0);
00875         std::vector<double> N_v(MainNurb.MaxV+1, 0.0);
00876         std::vector<double> TempU(MainNurb.DegreeU+1, 0.0);
00877         std::vector<double> TempV(MainNurb.DegreeV+1, 0.0);
00878         std::vector<double> swapDegreeU(MainNurb.DegreeU+1, 0.0);
00879         std::vector<double> swapDegreeV(MainNurb.DegreeV+1, 0.0);
00880         std::vector<double> swapV(MainNurb.MaxV+1, 0.0);
00881         std::vector<double> swapU(MainNurb.MaxU+1, 0.0);
00882 
00883         for (int i = 0; i < NumOfPoints; i++)
00884         {
00885             std::vector<double> N_u(MainNurb.MaxU+1, 0.0);
00886             std::vector<double> N_v(MainNurb.MaxV+1, 0.0);
00887             std::vector<double> TempU(MainNurb.DegreeU+1, 0.0);
00888             std::vector<double> TempV(MainNurb.DegreeV+1, 0.0);
00889 
00890             int j1 = FindSpan(MainNurb.MaxU, MainNurb.DegreeU, ParameterX[i], MainNurb.KnotU);
00891             int j2 = FindSpan(MainNurb.MaxV, MainNurb.DegreeV, ParameterY[i], MainNurb.KnotV);
00892 
00893 
00894             Basisfun(j1,ParameterX[i], MainNurb.DegreeU, MainNurb.KnotU, TempU);
00895             Basisfun(j2,ParameterY[i], MainNurb.DegreeV, MainNurb.KnotV, TempV);
00896 
00897             for (int k = j1 - MainNurb.DegreeU, s = 0; k < j1+1; k++, s++)
00898                   N_u[k] = TempU[s];
00899             for (int k = j2 - MainNurb.DegreeV, s = 0; k < j2+1; k++, s++)
00900                 N_v[k] = TempV[s];
00901 
00902             for (int j = 0; j <= MainNurb.MaxV; j++)
00903             {
00904                 for (int h = 0; h <= MainNurb.MaxU; h++)
00905                 {
00906                     //double result = N_u[h] * N_v[j];
00907                     B_Matrix(i,(j*(MainNurb.MaxU+1))+h) =  sqrt(err_w[i]) * N_u[h] * N_v[j];
00908                 }
00909             }
00910         }
00911 
00912         for (unsigned int i = 0; i < UnparamX.size(); ++i)
00913         {
00914             C_Temp(i,0) = sqrt(err_w[i])*UnparamX[i];
00915             C_Temp(i,1) = sqrt(err_w[i])*UnparamY[i];
00916             C_Temp(i,2) = sqrt(err_w[i])*UnparamZ[i];
00917         }
00918 
00919         ublas::matrix<double> G_Matrix((MainNurb.MaxU+1)*(MainNurb.MaxV+1),(MainNurb.MaxU+1)*(MainNurb.MaxV+1));
00920         ublas::matrix<double> C_Tempo((MainNurb.MaxU+1)*(MainNurb.MaxV+1),3);
00921         atlas::gemm(CblasTrans, CblasNoTrans, 1.0, B_Matrix,C_Temp,0.0,C_Tempo);
00922         atlas::gemm(CblasTrans,CblasNoTrans,1.0,B_Matrix,B_Matrix,0.0,G_Matrix);  //Multiplication with Boost bindings
00923         //to ATLAS's bindings to LAPACK
00924         B_Matrix.resize(1,1,false);
00925         B_Matrix.clear();
00926 
00927         anOutputFile << "Preparing the A_Matrix" << std::endl;
00928         //ublas::matrix<double> G_Matrix((MainNurb.MaxU+1)*(MainNurb.MaxV+1),(MainNurb.MaxU+1)*(MainNurb.MaxV+1));
00929         ublas::compressed_matrix<double, ublas::column_major, 0, ublas::unbounded_array<int>, ublas::unbounded_array<double> >
00930         A_Matrix((MainNurb.MaxU+1)*(MainNurb.MaxV+1),(MainNurb.MaxU+1)*(MainNurb.MaxV+1));
00931         anOutputFile << "Multiply..." << std::endl;
00932 
00933         anOutputFile << "Euclidean Norm" << std::endl;
00934         A_Matrix = G_Matrix;
00935 
00936                 if(cnt == 0)
00937                         lam = 10*ublas::norm_frobenius(G_Matrix);
00938                 else
00939                         lam /= 2;
00940                 
00941         G_Matrix.resize(1,1, false);
00942         G_Matrix.clear();
00943         ublas::compressed_matrix<double> E_Matrix((MainNurb.MaxU+1)*(MainNurb.MaxV+1), (MainNurb.MaxU+1)*(MainNurb.MaxV+1));
00944         anOutputFile << "E_Matrix succesfully constructed" << std::endl;
00945         anOutputFile << "Smoothing..." << std::endl;
00946         eFair2(E_Matrix);
00947                 
00948                 if(cnt == 0){
00949                         lam = lam / ublas::norm_frobenius(E_Matrix);
00950                 }
00951 
00952         ++cnt;
00953 
00954                 anOutputFile << "lam: " << lam << std::endl;
00955         A_Matrix = A_Matrix + (E_Matrix*lam);
00956         
00957                 //Destroying the unneeded matrix
00958         E_Matrix.resize(1,1,false);
00959         E_Matrix.clear();
00960         anOutputFile << "Preparing the C_Matrix" << std::endl;
00961         std::vector< std::vector<double> > Solver;
00962         std::vector<double> TempoSolv((MainNurb.MaxU+1)*(MainNurb.MaxV+1));
00963         std::vector<double> TempoB;
00964 
00965         anOutputFile << "Solving" << std::endl;
00966         for (unsigned int i = 0; i < 3; i++) //Since umfpack can only solve Ax = B, where x and B are vectors
00967                                              //instead of matrices...
00968         {
00969             //We will solve it column wise
00970             for (int j = 0; j < (MainNurb.MaxU+1)*(MainNurb.MaxV+1); j++)
00971                 TempoB.push_back(C_Tempo(j,i));  //push back a column
00972 
00973             umfpack::umf_solve(A_Matrix,TempoSolv,TempoB);  //solve
00974             Solver.push_back(TempoSolv);  //push back the solution
00975             TempoB.clear();
00976         }
00977         MainNurb.CntrlArray.clear();
00978         anOutputFile << "Loading the Control Points" << std::endl;
00979         for (int i = 0; i < (MainNurb.MaxU+1)*(MainNurb.MaxV+1); i++) //now load the control points
00980         {
00981             MainNurb.CntrlArray.push_back(Solver[0][i]); //X
00982             MainNurb.CntrlArray.push_back(Solver[1][i]); //Y
00983             MainNurb.CntrlArray.push_back(Solver[2][i]); //Z
00984         }
00985 
00986                 std::vector<double> ContrArr = MainNurb.CntrlArray;
00987 
00988         anOutputFile << "Cntrl Count" << std::endl;
00989         anOutputFile << "U: " << MainNurb.MaxU + 1 << std::endl;
00990         anOutputFile << "V: " << MainNurb.MaxV + 1 << std::endl;
00991 
00992         //ComputeError(h, 0.1, 0.1, max_err,av, c2, err_w);
00993 
00994         //anOutputFile << "Maximum error is " << max_err <<std::endl;
00995         //
00996         //anOutputFile << "Average points in error: " << c2 << std::endl;
00997 
00998 
00999                 //Reparameterize & error-measurement
01000                 anOutputFile << "Reparameterize ..." <<  std::endl;
01001         av = Reparam();  
01002                 anOutputFile << "End Reparameterize" <<  std::endl;
01003                 anOutputFile << "Average error: " << av << std::endl;
01004         
01005                 if (av <= tolerance)   //Error still bigger than our tolerance?
01006                         ErrThere = false;
01007     }
01008 
01009         anOutputFile.close();
01010 }
01011 
01014 void Approximate::eFair2(ublas::compressed_matrix<double> &E_Matrix)
01015 {
01016         ofstream anOutputFile;
01017         anOutputFile.open("c:/approx_param_log_efair.txt");
01018 
01019     int precision = 100;
01020     std::vector<double> U(precision+1, 0);
01021     std::vector<double> V(precision+1, 0);
01022     for (int i = 1; i <= precision; i++) //Load U and V vectors uniformly, according to precision
01023     {
01024         U[i] = (1.0/(double)precision) + U[i-1];
01025         V[i] = (1.0/(double)precision) + V[i-1];
01026     }
01027     U[precision] = 1.0;
01028     V[precision] = 1.0;
01029     precision = precision + 1;
01030 
01031     int mu = MainNurb.MaxKnotU;
01032     int mv = MainNurb.MaxKnotV;
01033     int k = mu-MainNurb.MaxU-2;
01034     int l = mv-MainNurb.MaxV-2;
01035     //Preparing the needed matrices
01036     std::vector< std::vector<double> > N_u0(precision, std::vector<double>(mu-1-k,0.0));
01037     std::vector< std::vector<double> > N_u1(precision, std::vector<double>(mu-1-k,0.0));
01038     std::vector< std::vector<double> > N_u2(precision, std::vector<double>(mu-1-k,0.0));
01039     std::vector< std::vector<double> > N_v0(precision, std::vector<double>(mu-1-l,0.0));
01040     std::vector< std::vector<double> > N_v1(precision, std::vector<double>(mu-1-l,0.0));
01041     std::vector< std::vector<double> > N_v2(precision, std::vector<double>(mu-1-l,0.0));
01042 
01043     std::vector<double> A_1(precision,0.0);
01044     std::vector<double> B_1(precision,0.0);
01045     std::vector<double> C_1(precision,0.0);
01046     std::vector<double> A_2(precision,0.0);
01047     std::vector<double> B_2(precision,0.0);
01048     std::vector<double> C_2(precision,0.0);
01049 
01050     //Filling up the first six matrices
01051     for (int i = 0; i < precision; i++)
01052     {
01053         std::vector< std::vector<double> > dersU(2+1, std::vector<double>(k+1));
01054         std::vector< std::vector<double> > dersV(2+1, std::vector<double>(k+1));
01055         int s = FindSpan(MainNurb.MaxU, k, U[i], MainNurb.KnotU);
01056         DersBasisFuns(s, U[i], k, 2, MainNurb.KnotU, dersU);
01057         for (int a = s-k, b = 0; a < s+1; a++, b++)
01058         {
01059             N_u0[i][a] = dersU[0][b];
01060             N_u1[i][a] = dersU[1][b];
01061             N_u2[i][a] = dersU[2][b];
01062         }
01063 
01064         s = FindSpan(MainNurb.MaxV, l, V[i], MainNurb.KnotV);
01065         DersBasisFuns(s, V[i], l, 2, MainNurb.KnotV, dersV);
01066         for (int a = s-l, b = 0; a < s+1; a++, b++)
01067         {
01068             N_v0[i][a] = dersV[0][b];
01069             N_v1[i][a] = dersV[1][b];
01070             N_v2[i][a] = dersV[2][b];
01071         }
01072 
01073     }
01074 
01075     double A,B,C; //Needed Variables for the Trapezoid-Integration
01076     //Now lets fill up the E
01077     for (int a = 0; a < MainNurb.MaxV+1; a++)
01078     {
01079 
01080         //anOutputFile << "\r" << ceil(100.0*((double) a/(double) MainNurb.MaxV)) << "%" << " ";
01081         for (int b = 0; b < MainNurb.MaxU+1; b++)
01082         {
01083             for (int c = 0; c < MainNurb.MaxV+1; c++)
01084             {
01085 
01086                 for (int d = 0; d < MainNurb.MaxU+1; d++)
01087                 {
01088                     for (int w = 0; w < precision; w++)  //Fill up the last 6 Matrices from the first matrix
01089                     {
01090                         A_1[w] = (N_u2[w][b]*N_u2[w][d]);
01091                         A_2[w] = (N_v0[w][a]*N_v0[w][c]);
01092 
01093                         B_1[w] = (N_u1[w][b]*N_u1[w][d]);
01094                         B_2[w] = (N_v1[w][a]*N_v1[w][c]);
01095 
01096                         C_1[w] = (N_u0[w][b]*N_u0[w][d]);
01097                         C_2[w] = (N_v2[w][a]*N_v2[w][c]);
01098                     }
01099 
01100 
01101 
01102                     //SehnenTrapezRegel
01103                     A = TrapezoidIntergration(U, A_1);
01104                     A *= TrapezoidIntergration(U, A_2);
01105 
01106                     B = TrapezoidIntergration(U, B_1);
01107                     B *= TrapezoidIntergration(U, B_2);
01108 
01109                     C = TrapezoidIntergration(U, C_1);
01110                     C *= TrapezoidIntergration(U, C_2);
01111 
01112                     //result = A + 2*B + C;
01113                     E_Matrix((a*(MainNurb.MaxU+1))+b,(c*(MainNurb.MaxV+1))+d) = A + 2*B + C;
01114                 }
01115             }
01116         }
01117     }
01118     anOutputFile << std::endl;
01119         anOutputFile.close();
01120 }
01121 
01124 void Approximate::ComputeError(int &h, double eps_1, double eps_2, double &max_error,
01125                                double &av, double &c2, std::vector <double> &err_w)
01126 {
01127     std::cout << "Computing Error..." << std::endl;
01128     av = 0;
01129     c2 = 0;
01130     max_error = 0;
01131     for (int i = 0; i < NumOfPoints; i++)  //For all points
01132     {
01133 
01134         std::vector<NURBS> DerivNurb;
01135         std::vector<NURBS> DerivUNurb;
01136         std::vector<NURBS> DerivVNurb;
01137         std::vector<std::vector<double> > Jac;
01138         std::vector<double> CurPoint;
01139         CurPoint.push_back(ParameterX[i]);
01140         CurPoint.push_back(ParameterY[i]);
01141         std::vector<double> V(2,0.0);
01142         V[0] = CurPoint[0];
01143         V[1] = CurPoint[1];
01144         unsigned int j = 0;
01145         PointNrbDerivate(MainNurb, DerivNurb);
01146         PointNrbDerivate(DerivNurb[0], DerivUNurb);
01147         PointNrbDerivate(DerivNurb[1], DerivVNurb);
01148         int c = 0;
01149         std::vector<double> error;
01150         std::vector<double> EvalPoint;
01151 
01152         NrbDEval(MainNurb, DerivNurb, CurPoint, EvalPoint, Jac);
01153         EvalPoint[0] = EvalPoint[0] - UnparamX[i];
01154         EvalPoint[1] = EvalPoint[1] - UnparamY[i];
01155         EvalPoint[2] = EvalPoint[2] - UnparamZ[i];
01156         ublas::matrix<double> EvalMat(1, EvalPoint.size());
01157         for (j = 0; j < 3; j++)
01158             EvalMat(0,j) = EvalPoint[j];
01159         for (j = 0; j < 2; j++)
01160         {
01161             ublas::matrix<double> Holder(1, 1);
01162             ublas::matrix<double> JacPoint(Jac[j].size(), 1);
01163             for (unsigned int k = 0; k < Jac[j].size(); k++)
01164                 JacPoint(k,0) = Jac[j][k];
01165 
01166             atlas::gemm(CblasTrans, CblasTrans, 1.0, JacPoint,EvalMat,0.0,Holder);
01167             double lam = ublas::norm_frobenius(JacPoint) * ublas::norm_frobenius(EvalMat);
01168             if (lam == 0)
01169                 throw "Division by Zero in ComputeError function";
01170             lam = fabs(Holder(0,0) / lam);
01171             error.push_back(lam);
01172         }
01173         //recheck the... thingy here...
01174         while (((norm_frobenius(EvalMat) > eps_1) && ((error[0] > eps_2) || (error[1] > eps_2))) && c < 1000) //If somehow the eps is not reached...
01175         {
01176             c += 1;
01177             std::vector<double> p_uu;
01178             std::vector<double> p_uv;
01179             std::vector<double> p_vu;
01180             std::vector<double> p_vv;
01181             ublas::matrix<double> P_UU(3, 1);
01182             ublas::matrix<double> P_UV(3, 1);
01183             ublas::matrix<double> P_VU(3, 1);
01184             ublas::matrix<double> P_VV(3, 1);
01185             ublas::matrix<double> JacPoint1(Jac[0].size(), 1);
01186             ublas::matrix<double> JacPoint2(Jac[0].size(), 1);
01187             PointNrbEval(p_uu,CurPoint,DerivUNurb[0]);
01188             PointNrbEval(p_uv,CurPoint,DerivUNurb[1]);
01189             PointNrbEval(p_vu,CurPoint,DerivVNurb[0]);
01190             PointNrbEval(p_vv,CurPoint,DerivVNurb[1]);
01191 
01192             //Prepping the needed matrix
01193 
01194             for (unsigned int a = 0; a < Jac[0].size();a++)
01195                 JacPoint1(a,0) = Jac[0][a];
01196             for (unsigned int a = 0; a < Jac[1].size();a++)
01197                 JacPoint2(a,0) = Jac[1][a];
01198             for (unsigned int a = 0; a < 3; a++)
01199             {
01200                 P_UU(a,0) = p_uu[a];
01201                 P_UV(a,0) = p_uv[a];
01202                 P_VU(a,0) = p_vu[a];
01203                 P_VV(a,0) = p_vv[a];
01204             }
01205 
01206             std::vector< std::vector<double> > J(2, std::vector<double>(2,0.0));
01207             std::vector<double> K(2,0.0);
01208             //Newton iterate
01209             //J[0][0]
01210             ublas::matrix<double> MultResult(1,1);
01211             atlas::gemm(CblasTrans, CblasNoTrans, 1.0, JacPoint1,JacPoint1,0.0,MultResult);
01212             J[0][0] += MultResult(0,0);
01213             atlas::gemm(CblasNoTrans, CblasNoTrans, 1.0, EvalMat,P_UU,0.0,MultResult);
01214             J[0][0] += MultResult(0,0);
01215 
01216             //J[0][1]
01217             atlas::gemm(CblasTrans, CblasNoTrans, 1.0, JacPoint1,JacPoint2,0.0,MultResult);
01218             J[0][1] += MultResult(0,0);
01219             atlas::gemm(CblasNoTrans, CblasNoTrans, 1.0, EvalMat,P_UV,0.0,MultResult);
01220             J[0][1] += MultResult(0,0);
01221 
01222             //J[1][0]
01223             atlas::gemm(CblasTrans, CblasNoTrans, 1.0, JacPoint1,JacPoint2,0.0,MultResult);
01224             J[1][0] += MultResult(0,0);
01225             atlas::gemm(CblasNoTrans, CblasNoTrans, 1.0, EvalMat,P_VU,0.0,MultResult);
01226             J[1][0] += MultResult(0,0);
01227 
01228             //J[1][1]
01229             atlas::gemm(CblasTrans, CblasNoTrans, 1.0, JacPoint2,JacPoint2,0.0,MultResult);
01230             J[1][1] += MultResult(0,0);
01231             atlas::gemm(CblasNoTrans, CblasNoTrans, 1.0, EvalMat,P_VV,0.0,MultResult);
01232             J[1][1] += MultResult(0,0);
01233 
01234             //K[0]
01235             atlas::gemm(CblasNoTrans, CblasNoTrans, 1.0, EvalMat,JacPoint1,0.0,MultResult);
01236             K[0] = (J[0][0]*V[0]) + (J[0][1]*V[1]) - MultResult(0,0);
01237 
01238             //K[1]
01239             atlas::gemm(CblasNoTrans, CblasNoTrans, 1.0, EvalMat,JacPoint2,0.0,MultResult);
01240             K[1] = (J[1][0]*V[0]) + (J[1][1]*V[1]) - MultResult(0,0);
01241 
01242             CramerSolve(J,K,V);
01243 
01244             if (V[0] < 0)
01245                 V[0] = 0;
01246             else if (V[0] > 1)
01247                 V[0] = 1;
01248 
01249             if (V[1] < 0)
01250                 V[1] = 0;
01251             else if (V[1] > 1)
01252                 V[1] = 1;
01253 
01254             if (c == 500)
01255             {
01256                 V[0] = 0.5;
01257                 V[1] = 0.5;
01258             }
01259             //Reevaluate
01260             error.clear();
01261             CurPoint[0] = V[0];
01262             CurPoint[1] = V[1];
01263             EvalPoint.clear();
01264             Jac.clear();
01265             NrbDEval(MainNurb, DerivNurb, CurPoint, EvalPoint, Jac);
01266             EvalPoint[0] = EvalPoint[0] - UnparamX[i];
01267             EvalPoint[1] = EvalPoint[1] - UnparamY[i];
01268             EvalPoint[2] = EvalPoint[2] - UnparamZ[i];
01269             for (j = 0; j < 3; j++)
01270                 EvalMat(0,j) = EvalPoint[j];
01271             for (j = 0; j < 2; j++)
01272             {
01273                 ublas::matrix<double> Holder(1, 1);
01274                 ublas::matrix<double> JacPoint(Jac[j].size(), 1);
01275                 for (unsigned int k = 0; k < Jac[j].size(); k++)
01276                     JacPoint(k,0) = Jac[j][k];
01277 
01278                 atlas::gemm(CblasTrans, CblasTrans, 1.0, JacPoint,EvalMat,0.0,Holder);
01279                 double lam = ublas::norm_frobenius(JacPoint) * ublas::norm_frobenius(EvalMat);
01280                 if (lam == 0)
01281                     throw "Division by Zero in ComputeError function";
01282                 else
01283                     lam = fabs(Holder(0,0) / lam);
01284                 error.push_back(lam);
01285             }
01286         }
01287         ParameterX[i] = V[0];
01288         ParameterY[i] = V[1];
01289         av += norm_frobenius(EvalMat);  //Average Error
01290 
01291         err_w[i] = norm_frobenius(EvalMat);
01292 
01293         if (norm_frobenius(EvalMat) > max_error && c < 1000)
01294         {
01295             max_error = norm_frobenius(EvalMat);
01296             h = i;
01297             //if(max_error > (3*tolerance))
01298             // break;
01299 
01300         }
01301         if (norm_frobenius(EvalMat) > tolerance)
01302             c2++;    //% of point's error still above tolerance
01303     }
01304     c2 /= NumOfPoints;
01305     av /= NumOfPoints;
01306 
01307     std::cout << " DONE" << std::endl;
01308 }
01309 
01312 double Approximate::Reparam()
01313 {
01314         MeshCore::MeshPointArray pntArr = MeshParam.GetPoints();
01315         MeshCore::MeshFacetArray fctArr = MeshParam.GetFacets();
01316 
01317         double error = 0.0;
01318 
01319     std::cout << "Reparameterization...";
01320     for (int i = 0; i < NumOfPoints; i++)
01321     {
01322         std::vector<NURBS> DerivNurb;
01323         std::vector<double> p;
01324         std::vector<double> EvalPoint;
01325         std::vector< std::vector<double> > T;
01326         std::vector< std::vector<double> > A(2,std::vector<double>(2,0.0));
01327         std::vector<double> bt(2,0.0);
01328 
01329         p.push_back(ParameterX[i]);
01330         p.push_back(ParameterY[i]);
01331         PointNrbDerivate(MainNurb, DerivNurb);
01332         NrbDEval(MainNurb, DerivNurb, p, EvalPoint, T);
01333         
01334                 EvalPoint[0] = UnparamX[i] - EvalPoint[0];
01335         EvalPoint[1] = UnparamY[i] - EvalPoint[1];
01336         EvalPoint[2] = UnparamZ[i] - EvalPoint[2];
01337 
01338                 error += sqrt(EvalPoint[0]*EvalPoint[0] + EvalPoint[1]*EvalPoint[1] + EvalPoint[2]*EvalPoint[2]);
01339 
01340         for (int j = 0; j < 2; j++)
01341         {
01342             for (int k = 0; k < 2; k++)
01343             {
01344                 std::vector<double> JacHolder1(3, 0.0);
01345                 std::vector<double> JacHolder2(3, 0.0);
01346                 std::vector<double> Result(1, 0.0);
01347                 if (j == 0 && k == 0)
01348                 {
01349                     for (int l = 0; l < 3; l++)
01350                     {
01351                         JacHolder1[l] = T[0][l];
01352                         JacHolder2[l] = T[0][l];
01353                     }
01354                     cblas_dgemm(CblasRowMajor, CblasNoTrans, CblasNoTrans,1,1,3,1.0,
01355                                 &JacHolder1[0],3,&JacHolder2[0],1,0.0,&Result[0], 1);
01356 
01357                     A[j][k] = Result[0];
01358                 }
01359                 else if (j == 1 && k == 1)
01360                 {
01361                     for (int l = 0; l < 3; l++)
01362                     {
01363                         JacHolder1[l] = T[1][l];
01364                         JacHolder2[l] = T[1][l];
01365                     }
01366                     cblas_dgemm(CblasRowMajor, CblasNoTrans, CblasNoTrans,1,1,3,1.0,
01367                                 &JacHolder1[0],3,&JacHolder2[0],1,0.0,&Result[0], 1);
01368 
01369                     A[j][k] = Result[0];
01370                 }
01371                 else
01372                 {
01373                     for (int l = 0; l < 3; l++)
01374                     {
01375                         JacHolder1[l] = T[0][l];
01376                         JacHolder2[l] = T[1][l];
01377                     }
01378                     cblas_dgemm(CblasRowMajor, CblasNoTrans, CblasNoTrans,1,1,3,1.0,
01379                                 &JacHolder1[0],3,&JacHolder2[0],1,0.0,&Result[0], 1);
01380 
01381                     A[j][k] = Result[0];
01382                 }
01383             }
01384             std::vector<double> Resultant(1, 0.0);
01385             std::vector<double> BJacHolder(3, 0.0);
01386             for (int l = 0; l < 3; l++)
01387                 BJacHolder[l] = T[j][l];
01388             cblas_dgemm(CblasRowMajor, CblasNoTrans, CblasNoTrans,1,1,3,1.0,
01389                         &EvalPoint[0],3,&BJacHolder[0],1,0.0,&Resultant[0], 1);
01390 
01391             bt[j] = Resultant[0];
01392 
01393         }
01394         
01395                 std::vector<double> delt(2,0.0);
01396         CramerSolve(A,bt,delt);
01397 
01398         //Reparam
01399         if (ParameterX[i] + delt[0] <= 0)
01400             ParameterX[i] = 0;
01401         else if (ParameterX[i] + delt[0] >= 1)
01402             ParameterX[i] = 1;
01403         else ParameterX[i] += delt[0];
01404 
01405         if (ParameterY[i] + delt[1] <= 0)
01406             ParameterY[i] = 0;
01407         else if (ParameterY[i] + delt[1] >= 1)
01408             ParameterY[i] = 1;
01409         else ParameterY[i] += delt[1];
01410 
01411         }
01412 
01413         error /= NumOfPoints;
01414 
01415         MeshCore::MeshPointIterator v_it(MeshParam);
01416         std::list< std::vector <unsigned long> >::iterator bInd = BoundariesIndex.begin();
01417         std::vector <unsigned long> boundarieslist = *bInd;
01418     std::vector <unsigned long>::iterator vec_it;
01419         int s=0;
01420         int b=0;
01421         for (v_it.Begin(); !v_it.EndReached(); ++v_it)
01422     {
01423         //Inner Points goes into the beginning of the list
01424         if ((vec_it = find(boundarieslist.begin(), boundarieslist.end(), v_it.Position())) == boundarieslist.end())
01425         {
01426 
01427                         pntArr[v_it.Position()].x = ParameterX[s];
01428                         pntArr[v_it.Position()].y = ParameterY[s];
01429             s++;
01430         }
01431         //Boundaries goes into the end of the list
01432         else
01433         {
01434 
01435                         pntArr[v_it.Position()].x = ParameterX[NumOfInnerPoints+b];
01436                         pntArr[v_it.Position()].y = ParameterY[NumOfInnerPoints+b];
01437 
01438             b++;
01439         }
01440     }
01441 
01442 
01443         MeshParam.Assign(pntArr,fctArr);
01444     std::cout << "DONE" << std::endl;
01445         return error;
01446 }
01447 
01453 void Approximate::ExtendNurb(double c2, int h)
01454 {
01455     std::cout << "Extending Knot Vector" << std::endl;
01456     std::cout << "Two knot extension" << std::endl;
01457     MainNurb.MaxU += 2;
01458     MainNurb.MaxV += 2;
01459     MainNurb.MaxKnotU += 2;
01460     MainNurb.MaxKnotV += 2;
01461     //U-V Knot Extension
01462     ExtendKnot(ParameterX[h], MainNurb.DegreeU, MainNurb.MaxU, MainNurb.KnotU);
01463     ExtendKnot(ParameterY[h], MainNurb.DegreeV, MainNurb.MaxV, MainNurb.KnotV);
01464 
01465 }
01466 
01473 void Approximate::ReorderNeighbourList(std::set<unsigned long> &pnt,
01474                                        std::set<unsigned long> &face, std::vector<unsigned long> &nei, unsigned long CurInd)
01475 {
01476     MeshCore::MeshPointArray::_TConstIterator v_beg = LocalMesh.GetPoints().begin();
01477     MeshCore::MeshFacetArray::_TConstIterator f_beg = LocalMesh.GetFacets().begin();
01478     std::set<unsigned long>::iterator pnt_it;
01479     std::set<unsigned long>::iterator face_it;
01480     std::vector<unsigned long>::iterator vec_it;
01481     std::vector<unsigned long>::iterator ulong_it;
01482     unsigned long PrevIndex;
01483     pnt_it = pnt.begin();
01484     face_it = face.begin();
01485     nei.push_back(v_beg[*pnt_it]._ulProp);  //push back first neighbour
01486     vec_it = nei.begin();
01487     PrevIndex = nei[0];  //Initialize PrevIndex
01488     for (unsigned int i = 1; i < pnt.size(); i++) //Start
01489     {
01490         while (true)
01491         {
01492             std::vector<unsigned long> facetpnt;
01493             facetpnt.push_back(f_beg[*face_it]._aulPoints[0]); //push back into a vector for easier iteration
01494             facetpnt.push_back(f_beg[*face_it]._aulPoints[1]);
01495             facetpnt.push_back(f_beg[*face_it]._aulPoints[2]);
01496             if ((ulong_it = find(facetpnt.begin(), facetpnt.end(), PrevIndex)) == facetpnt.end())  //if PrevIndex not found
01497             {
01498                 //in current facet
01499                 ++face_it; //next face please
01500                 continue;
01501             }
01502             else
01503             {
01504                 for (unsigned int k = 0 ; k < 3; k++)
01505                 {
01506                     //If current facetpnt[k] is not yet in nei_list AND it is not the CurIndex
01507                     if (((vec_it = find(nei.begin(), nei.end(), facetpnt[k])) == nei.end()) && facetpnt[k] != CurInd)
01508                     {
01509                         face.erase(face_it);   //erase this face
01510                         nei.push_back(facetpnt[k]);  //push back the index
01511                         PrevIndex = facetpnt[k];   //this index is now PrevIndex
01512                         face_it = face.begin(); //reassign the iterator
01513                         break;   //end this for-loop
01514                     }
01515                 }
01516                 break;  //end this while loop
01517             }
01518         }
01519     }
01520 }

Generated on Wed Nov 23 18:59:56 2011 for FreeCAD by  doxygen 1.6.1