OSGNurbsPatchSurface.cpp

Go to the documentation of this file.
00001 /*---------------------------------------------------------------------------*\
00002  *                           OpenSG NURBS Library                            *
00003  *                                                                           *
00004  *                                                                           *
00005  * Copyright (C) 2001-2006 by the University of Bonn, Computer Graphics Group*
00006  *                                                                           *
00007  *                         http://cg.cs.uni-bonn.de/                         *
00008  *                                                                           *
00009  * contact: edhellon@cs.uni-bonn.de, guthe@cs.uni-bonn.de, rk@cs.uni-bonn.de *
00010  *                                                                           *
00011 \*---------------------------------------------------------------------------*/
00012 /*---------------------------------------------------------------------------*\
00013  *                                License                                    *
00014  *                                                                           *
00015  * This library is free software; you can redistribute it and/or modify it   *
00016  * under the terms of the GNU Library General Public License as published    *
00017  * by the Free Software Foundation, version 2.                               *
00018  *                                                                           *
00019  * This library is distributed in the hope that it will be useful, but       *
00020  * WITHOUT ANY WARRANTY; without even the implied warranty of                *
00021  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU         *
00022  * Library General Public License for more details.                          *
00023  *                                                                           *
00024  * You should have received a copy of the GNU Library General Public         *
00025  * License along with this library; if not, write to the Free Software       *
00026  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.                 *
00027  *                                                                           *
00028 \*---------------------------------------------------------------------------*/
00029 /*---------------------------------------------------------------------------*\
00030  *                                Changes                                    *
00031  *                                                                           *
00032  *                                                                           *
00033  *                                                                           *
00034  *                                                                           *
00035  *                                                                           *
00036  *                                                                           *
00037 \*---------------------------------------------------------------------------*/
00038 #include "OSGLog.h"
00039
00040 #include "OSGQuadTreeCreator.h"
00041 #include "OSGParSpaceTrimmer.h"
00042 #include "OSGNurbsPatchSurface.h"
00043 //#include <DCTPBoundary.h>
00044 #include "OSGpredicates.h"   // for exactinit
00045 //#include "rounding.h" // for FPU_ROUND_DOUBLE
00046 #include "OSGSurface.h"
00047
00048 #include <map>
00049
00050 //#include "BoundarySimplifier/BoundaryObject.h"
00051
00052 OSG_USING_NAMESPACE
00053
00054 //put miniball inside OSG namespace
00055 //#include "miniball/miniball.H"
00056
00057 #ifdef WIN32
00058 #pragma warning (disable : 985)
00059 #endif
00060 
00061 //#define DRAW_LINES
00062 #define OSG_VEC_COMPUTE
00063 
00064 //static unsigned int g_uiColor = 0;
00065
00066 #ifdef WRITE_STAT
00067 static double    g_dTrimmingConversionTime    = 0.0;
00068 static double    g_dTrimmingApproximationTime = 0.0;
00069 static OSG::Time g_clTrimmingApproximationStart;
00070 static double    g_dTotalTime = 0.0;
00071 static OSG::Time g_clTotalStart;
00072 static OSG::Time g_clActTime;
00073 #endif
00074 
00075 #define OSG_3D_LOOPS
00076 
00077 CNurbsPatchSurface::CNurbsPatchSurface()
00078 {
00079     m_pclGraph        = NULL;
00080     m_bErrorTreeValid = false;
00081     m_pclQuadTree     = NULL;
00082 }
00083
00084
00085 CNurbsPatchSurface::~CNurbsPatchSurface()
00086 {
00087 //    unsigned int ui_idx;
00088
00089     if(m_pclGraph)
00090     {
00091         delete m_pclGraph;
00092     }
00093
00094     for(unsigned int ui_number = 0; ui_number < m_vtSurfaces.size(); ++ui_number)
00095     {
00096         delete m_vtSurfaces[ui_number].pclErrorTree;
00097     }
00098
00099     m_vclBSplineSurfaces.clear();
00100     m_vvvclBezierSurfaces.clear();
00101     m_vvdUParams.clear();
00102     m_vvdVParams.clear();
00103     m_vtSurfaces.clear();
00104 //  m_vpclNodes.clear( );
00105     if(m_pclQuadTree != NULL)
00106     {
00107         delete m_pclQuadTree;
00108         m_pclQuadTree = NULL;
00109     }
00110 }
00111
00112
00113 // add surface patch
00114 void CNurbsPatchSurface::AddSurface(BSplineTrimmedSurface *clSurface)
00115 {
00116 #ifdef WRITE_STAT
00117     g_clTotalStart = OSG::getSystemTime();
00118 #endif
00119 
00120     unsigned int ui_number = m_vclBSplineSurfaces.size();
00121
00122 //  std::cerr << "\rreading surface " << ui_number + 1;
00123
00124     // resize vectors
00125     m_vclBSplineSurfaces.resize(ui_number + 1);
00126     m_vvvclBezierSurfaces.resize(ui_number + 1);
00127     m_vvdUParams.resize(ui_number + 1);
00128     m_vvdVParams.resize(ui_number + 1);
00129 //  m_vclSeperateMeshes.resize( ui_number + 1 );
00130 //  m_vclSewedMeshes.resize( ui_number + 1 );
00131     m_vtSurfaces.resize(ui_number + 1);
00132 //  m_vtTrimmingCurves.resize( ui_number + 1 );
00133 //  m_vpclNodes.resize( ui_number + 1 );
00134
00135
00136     // copy and init values
00137     m_vclBSplineSurfaces[ui_number]       = *clSurface;
00138     m_vtSurfaces[ui_number].dError        = 10.0;
00139     m_vtSurfaces[ui_number].ucStatus      = 0;
00140     m_vtSurfaces[ui_number].pclErrorTree  = new CErrorQuadTree();
00141     m_bErrorTreeValid                     = true;
00142     m_vtSurfaces[ui_number].uiTriangleCnt = 0;
00143
00144     // calculate initial values
00145     ConvertToBezier(ui_number);
00146
00147 #ifdef WRITE_STAT
00148     g_clActTime                = OSG::getSystemTime();
00149     g_dTotalTime              += g_clActTime - g_clTotalStart;
00150     g_dTrimmingConversionTime += g_clActTime - g_clTotalStart;
00151 #endif
00152 }
00153
00154 //FIXME: quick hack
00155 void CNurbsPatchSurface::setSurface(BSplineTrimmedSurface *clSurface,
00156                                     std::vector<Pnt2f> &   texturecps,
00157                                     bool                   bUseTextures)
00158 {
00159     //FIXME: I'm not sure how much of these reinits is actually needed
00160     if(m_pclGraph)
00161     {
00162         delete m_pclGraph;
00163         m_pclGraph = NULL;
00164     }
00165
00166     for(unsigned int ui_number = 0; ui_number < m_vtSurfaces.size(); ++ui_number)
00167     {
00168         delete m_vtSurfaces[ui_number].pclErrorTree;
00169         m_vtSurfaces[ui_number].pclErrorTree = NULL;
00170     }
00171
00172     m_vclBSplineSurfaces.clear();
00173     m_vvvclBezierSurfaces.clear();
00174     m_vvdUParams.clear();
00175     m_vvdVParams.clear();
00176     m_vtSurfaces.clear();
00177     //FIXME END
00178
00179 //    std::cerr<<"setSurface: m_vtSurfaces.size(): " << m_vtSurfaces.size() <<
00180 //            std::endl;
00181     AddSurface(clSurface);
00182
00183     m_bUseTextures = bUseTextures;
00184     if(m_bUseTextures)
00185     {
00186         UInt32                k = 0;
00187         UInt32                i, j;
00188         BSplineTensorSurface &tensor_surface = clSurface->getSurface();
00189         DCTPVec4dmatrix &     surf_cps       = tensor_surface.getControlPointMatrix();
00190         UInt32                u_size         = surf_cps.size();
00191         UInt32                v_size         = surf_cps[0].size();
00192         Vec2d                 tempv2d;
00193         if( (u_size * v_size) != texturecps.size() )
00194         {
00195             std::cerr << "setSurface: wrong number of texture control points, texturing disabled" << std::endl;
00196             m_bUseTextures = false;
00197             return;
00198         }
00199         m_vvTextureControlPoints.resize(u_size);
00200
00201         for(i = 0; i < u_size; ++i)
00202         {
00203             m_vvTextureControlPoints[i].resize(v_size);
00204         }
00205
00206         for(i = 0; i < u_size; ++i)
00207         {
00208             for(j = 0; j < v_size; ++j)
00209             {
00210                 tempv2d[0]                     = texturecps[k][0];
00211                 tempv2d[1]                     = texturecps[k][1];
00212                 m_vvTextureControlPoints[i][j] = tempv2d;
00213                 k++;
00214             }
00215         }
00216
00217     }
00218 }
00219
00220 void CNurbsPatchSurface::setupErrorTree(double dError)
00221 {
00222     double d_old_err = m_vtSurfaces[0].dError;
00223
00224     m_vtSurfaces[0].dError = dError;
00225     CalculateQuadTree(0, false);
00226     m_clMesh.reinit();
00227     m_vtSurfaces[0].dError = d_old_err;
00228 }
00229
00230 void CNurbsPatchSurface::setError(double dError)
00231 {
00232     if(m_pclGraph)
00233     {
00234         delete m_pclGraph;
00235         m_pclGraph = NULL;
00236     }
00237     m_vtSurfaces[0].vvclEdgeLoops.clear();
00238     m_vtSurfaces[0].vvclEdgeLoops3D.clear();
00239     m_vtSurfaces[0].vvclEdgeLoopsNorm.clear();
00240     m_vtSurfaces[0].vvclEdgeLoopsTex.clear();
00241     SetError(0, dError);
00242 }
00243
00244 //less hack...
00245 //normal tessellation, no texture
00246 void CNurbsPatchSurface::getTessellation(std::vector<Pnt3f> &        gverts,
00247                                          std::vector<Vec3f> &        norms,
00248                                          std::vector<SimplePolygon> &tris,
00249                                          bool                        usedelaunay)
00250 {
00251 #ifdef WRITE_STAT
00252     g_clTotalStart = OSG::getSystemTime();
00253 #endif
00254 
00255     if( (m_vtSurfaces[0].ucStatus & BEZIER_SURFACES_VALID) &&
00256         ( (m_vtSurfaces[0].ucStatus & TRIM_SEGS_VALID) == 0) )
00257     {
00258 #ifdef WRITE_STAT
00259         g_clTrimmingApproximationStart = OSG::getSystemTime();
00260 #endif
00261         CalculateQuadTree(0, true);
00262         CalculateTrimmingLoops(0);
00263 #ifdef WRITE_STAT
00264         g_clActTime                   = OSG::getSystemTime();
00265         g_dTrimmingApproximationTime += g_clActTime - g_clTrimmingApproximationStart;
00266 #endif
00267         CalculateQuadTree(0, false);
00268 //      std::cerr << "\rtesselating surface " << ui_surface + 1;
00269         CalculateActualTrimming(0);
00270         CalculateGraph(0, usedelaunay);
00271 //      ConvertPoints( 0 );
00273         if(m_pclGraph)
00274         {
00275             delete m_pclGraph;
00276             m_pclGraph = NULL;
00277         }
00278 //      BuildNode( ui_surface );
00280         calculatePointsAndNormals(gverts, tris, norms);
00281         ComputeNormalCone(0, norms);
00282         m_vclParameterVertices.clear();
00283         m_vclGlobalVertices.clear();
00284         m_vclTriangles.clear();
00285     }
00286     else
00287     {
00288         std::cerr << "shouldn't be here..." << std::endl;
00289     }
00290 //      std::cerr << std::endl;
00291 #ifdef WRITE_STAT
00292     g_clActTime   = OSG::getSystemTime();
00293     g_dTotalTime += g_clActTime - g_clTotalStart;
00294 //  std::cerr << "conversion " << g_dTrimmingConversionTime << " sec" << std::endl;
00295 //  std::cerr << "trimming   " << g_dTrimmingApproximationTime << " sec " << std::endl;
00296 //  std::cerr << "total      " << g_dTotalTime << " sec" << std::endl;
00297 #endif
00298 }
00299
00300 //normal tessellation, texturemapping: both normals and texturecoords
00301 void CNurbsPatchSurface::getTessellation(std::vector<Pnt3f> &        gverts,
00302                                          std::vector<Vec3f> &        norms,
00303                                          std::vector<Pnt2f> &        texturecoords,
00304                                          std::vector<SimplePolygon> &tris,
00305                                          bool                        usedelaunay)
00306 {
00307
00308     if( (m_vtSurfaces[0].ucStatus & BEZIER_SURFACES_VALID) &&
00309         ( (m_vtSurfaces[0].ucStatus & TRIM_SEGS_VALID) == 0) )
00310     {
00311         CalculateQuadTree(0, true);
00312         CalculateTrimmingLoops(0);
00313         CalculateQuadTree(0, false);
00314 //          std::cerr << "\rtesselating surface " << ui_surface + 1;
00315         CalculateActualTrimming(0);
00316         CalculateGraph(0, usedelaunay);
00317         if(m_pclGraph)
00318         {
00319             delete m_pclGraph;
00320             m_pclGraph = NULL;
00321         }
00322 //          BuildNode( ui_surface );
00324         calculatePointsNormalsAndTextureCoords(gverts,
00325                                                tris,
00326                                                norms,
00327                                                texturecoords);
00328         ComputeNormalCone(0, norms);
00329         m_vclParameterVertices.clear();
00330         m_vclGlobalVertices.clear();
00331         m_vclTriangles.clear();
00332     }
00333     else
00334     {
00335         std::cerr << "shouldn't be here..." << std::endl;
00336     }
00337 //      std::cerr << std::endl;
00338
00339 }
00340
00341 // get tessellation, using normalmaps (texcoords, but not normals!)
00342 void CNurbsPatchSurface::getTessellation(std::vector<Pnt3f> &        gverts,
00343                                          std::vector<Pnt2f> &        texturecoords,
00344                                          std::vector<SimplePolygon> &tris,
00345                                          bool                        usedelaunay)
00346 {
00347 //  Real64 d_time, d_last_time;
00348 //  d_last_time = getSystemTime();
00349
00350     if( (m_vtSurfaces[0].ucStatus & BEZIER_SURFACES_VALID) &&
00351         ( (m_vtSurfaces[0].ucStatus & TRIM_SEGS_VALID) == 0) )
00352     {
00353 //      std::cerr << "CalculateQuadTree";// << std::endl;
00354         CalculateQuadTree(0, true);
00355 /*      d_time = getSystemTime();
00356         std::cerr << " " << d_time - d_last_time << std::endl;
00357         d_last_time = d_time;
00358         std::cerr << "CalculateTrimmingLoops";// << std::endl;*/
00359         CalculateTrimmingLoops(0);
00360 /*      d_time = getSystemTime();
00361         std::cerr << " " << d_time - d_last_time << std::endl;
00362         d_last_time = d_time;
00363         std::cerr << "CalculateQuadTree";// << std::endl;*/
00364         CalculateQuadTree(0, false);
00365 /*      d_time = getSystemTime();
00366         std::cerr << " " << d_time - d_last_time << std::endl;
00367         d_last_time = d_time;
00368 //      std::cerr << "\rtesselating surface " << ui_surface + 1;
00369         std::cerr << "CalculateActualTrimming";// << std::endl;*/
00370         CalculateActualTrimming(0);
00371 /*      d_time = getSystemTime();
00372         std::cerr << " " << d_time - d_last_time << std::endl;
00373         d_last_time = d_time;
00374         std::cerr << "CalculateGraph";// << std::endl;*/
00375         CalculateGraph(0, usedelaunay);
00376 /*      d_time = getSystemTime();
00377         std::cerr << " " << d_time - d_last_time << std::endl;
00378         d_last_time = d_time;*/
00379 //      ConvertPoints( 0 );
00381         if(m_pclGraph)
00382         {
00383             delete m_pclGraph;
00384             m_pclGraph = NULL;
00385         }
00386 //      BuildNode( ui_surface );
00388 //                        calculatePointsAndNormals( gverts, tris, norms );
00389 //      std::cerr << "calculatePointsAndTextureCoords";// << std::endl;
00390         calculatePointsAndTextureCoords(gverts, tris, texturecoords);
00391 /*      d_time = getSystemTime();
00392         std::cerr << " " << d_time - d_last_time << std::endl;
00393         d_last_time = d_time;
00394 //                       ComputeNormalCone( 0, norms );
00395         std::cerr << "clearing" << std::endl;*/
00396         m_vclParameterVertices.clear();
00397         m_vclGlobalVertices.clear();
00398         m_vclTriangles.clear();
00399     }
00400     else
00401     {
00402         std::cerr << "shouldn't be here..." << std::endl;
00403     }
00404 //      std::cerr << std::endl;
00405
00406
00407 }
00408
00409
00410
00411 void CNurbsPatchSurface::calculatePointsAndNormals(
00412     std::vector<Pnt3f> &        gverts,
00413     std::vector<SimplePolygon> &tris,
00414     std::vector<Vec3f> &        norms)
00415 {
00416     BSplineTensorSurface cl_surf;
00417
00418 //  std::cerr << "c" << std::endl;
00419
00420     cl_surf = m_vclBSplineSurfaces[0].getSurface();
00421     // NOTE: also computes 3D vertex info in the gverts array
00422 #ifdef OSG_VEC_COMPUTE
00423     cl_surf.computeNormal(m_vclParameterVertices,
00424                           gverts,
00425                           norms);
00426 #else
00427     gverts.resize(m_vclParameterVertices.size() );
00428     norms.resize(m_vclParameterVertices.size() );
00429
00430     for(unsigned int i = 0; i < m_vclParameterVertices.size(); ++i)
00431     {
00432         int i_err = 0;
00433         norms[i] = cl_surf.computeNormal(m_vclParameterVertices[i], i_err, gverts[i]);
00434     }
00435
00436 #endif
00437 /*
00438     std::cerr<<"haho"<< m_vclParameterVertices.size() << " " << gverts.size() << " " << norms.size() << std::endl;
00439     for ( UInt32 i = 0; i < gverts.size(); ++i )
00440     {
00441         std::cerr << gverts[i] << " " << norms[i] << std::endl;
00442     }
00443 */
00444 /*
00445     std::cerr<<"m_vclParameterVertices.size(): " << m_vclParameterVertices.size() << std::endl;
00446     for ( UInt32 i = 0; i < m_vclParameterVertices.size(); ++i )
00447     {
00448         std::cerr<< m_vclParameterVertices[i] << std::endl;
00449         if (osgabs(m_vclParameterVertices[i][1] - 8271.61) < 1.0f)
00450         {
00451             std::cerr<<"zeroing norm: " << i << std::endl;
00452             norms[i][0] = norms[i][1] = norms[i][2] = 0.f;
00453         }
00454     }
00455 */
00456     tris.clear();
00457     tris = m_vclTriangles;
00458
00459     //copy the normals into the vvclEdgeLoopsNorm structure
00460     unsigned int numloops = m_vtSurfaces[0].vvclEdgeLoops.size();
00461     unsigned int actlooplength;
00462 #ifdef OSG_KEEP_2D_POINTS
00463     unsigned int ui_actvertidx = 0;
00464 #endif
00465 
00466     Vec3d cl_norm;
00467 //    Int32 i_err;
00468     m_vtSurfaces[0].vvclEdgeLoopsNorm.resize(numloops);
00469 #ifndef OSG_FORCE_NO_T_VERTICES
00470     m_vtSurfaces[0].vvclEdgeLoops3D.resize(numloops);
00471 #endif
00472 
00473     for(unsigned int ui_actloop = 0; ui_actloop < numloops; ++ui_actloop)
00474     {
00475         actlooplength = m_vtSurfaces[0].vvclEdgeLoops[ui_actloop].size();
00476         m_vtSurfaces[0].vvclEdgeLoopsNorm[ui_actloop].resize(actlooplength);
00477 #ifdef OSG_KEEP_2D_POINTS
00478 
00479         for(unsigned int ui_act = 0; ui_act < actlooplength; ++ui_act)
00480         {
00481             m_vtSurfaces[0].vvclEdgeLoopsNorm[ui_actloop][ui_act] =
00482                 Vec3d(norms[ui_actvertidx][0],
00483                       norms[ui_actvertidx][1],
00484                       norms[ui_actvertidx][2]);
00485
00486 /*          std::cerr << norms[ ui_actvertidx ][0] << " ";
00487             std::cerr << norms[ ui_actvertidx ][1] << " ";
00488             std::cerr << norms[ ui_actvertidx ][2] << std::endl;*/
00489
00490             ui_actvertidx++;
00491         }
00492
00493 #else
00494  #ifdef OSG_FORCE_NO_T_VERTICES
00495         cl_surf.computeNormalforTrimming(
00496             m_vtSurfaces[0].vvclEdgeLoops[ui_actloop],
00497             m_vtSurfaces[0].vvclEdgeLoopsNorm[ui_actloop]);
00498  #else
00499         cl_surf.computeNormalforTrimming(
00500             m_vtSurfaces[0].vvclEdgeLoops[ui_actloop],
00501             m_vtSurfaces[0].vvclEdgeLoopsNorm[ui_actloop],
00502             &m_vtSurfaces[0].vvclEdgeLoops3D[ui_actloop]);
00503  #endif
00504 #endif
00505     }
00506
00507
00508
00509 }
00510
00511
00512 void CNurbsPatchSurface::calculatePointsNormalsAndTextureCoords(
00513     std::vector<Pnt3f> &        gverts,
00514     std::vector<SimplePolygon> &tris,
00515     std::vector<Vec3f> &        norms,
00516     std::vector<Pnt2f> &        texturecoords)
00517 {
00518     BSplineTensorSurface cl_surf;
00519
00520
00521     cl_surf = m_vclBSplineSurfaces[0].getSurface();
00522     // NOTE: also computes 3D vertex info in the gverts array
00523     cl_surf.computeNormal(m_vclParameterVertices,
00524                           gverts,
00525                           norms);
00526     // FIXME: this is a hack just to try out if it works.
00527     // FIXME: will need to modify OSGBSplineTensorSurface.cpp to have
00528     // FIXME: a fucnction that combines these two.
00529     std::vector<Pnt3f> dummyverts;
00530     cl_surf.computeTex(m_vclParameterVertices,
00531                        dummyverts,
00532                        texturecoords,
00533                        &m_vvTextureControlPoints);
00534
00535
00536
00537 /*
00538     std::cerr<<"haho"<< m_vclParameterVertices.size() << " " << gverts.size() << " " << norms.size() << std::endl;
00539     for ( UInt32 i = 0; i < gverts.size(); ++i )
00540     {
00541         std::cerr << gverts[i] << " " << norms[i] << std::endl;
00542     }
00543 */
00544     tris.clear();
00545     tris = m_vclTriangles;
00546
00547     //copy the normals into the vvclEdgeLoopsNorm structure
00548     unsigned int numloops = m_vtSurfaces[0].vvclEdgeLoops.size();
00549     unsigned int actlooplength;
00550     unsigned int ui_actloop;
00551 #ifdef OSG_KEEP_2D_POINTS
00552     unsigned int ui_actvertidx = 0;
00553 #endif
00554 
00555     Vec3d cl_norm;
00556 //    Int32 i_err;
00557     m_vtSurfaces[0].vvclEdgeLoopsNorm.resize(numloops);
00558 #ifndef OSG_FORCE_NO_T_VERTICES
00559     m_vtSurfaces[0].vvclEdgeLoops3D.resize(numloops);
00560 #endif
00561 
00562     for(ui_actloop = 0; ui_actloop < numloops; ++ui_actloop)
00563     {
00564         actlooplength = m_vtSurfaces[0].vvclEdgeLoops[ui_actloop].size();
00565         m_vtSurfaces[0].vvclEdgeLoopsNorm[ui_actloop].resize(actlooplength);
00566 #ifdef OSG_KEEP_2D_POINTS
00567 
00568         for(unsigned int ui_act = 0; ui_act < actlooplength; ++ui_act)
00569         {
00570             m_vtSurfaces[0].vvclEdgeLoopsNorm[ui_actloop][ui_act] =
00571                 Vec3d(norms[ui_actvertidx][0],
00572                       norms[ui_actvertidx][1],
00573                       norms[ui_actvertidx][2]);
00574             ui_actvertidx++;
00575         }
00576
00577 #else
00578  #ifdef OSG_FORCE_NO_T_VERTICES
00579         cl_surf.computeNormalforTrimming(
00580             m_vtSurfaces[0].vvclEdgeLoops[ui_actloop],
00581             m_vtSurfaces[0].vvclEdgeLoopsNorm[ui_actloop]);
00582  #else
00583         cl_surf.computeNormalforTrimming(
00584             m_vtSurfaces[0].vvclEdgeLoops[ui_actloop],
00585             m_vtSurfaces[0].vvclEdgeLoopsNorm[ui_actloop],
00586             &m_vtSurfaces[0].vvclEdgeLoops3D[ui_actloop]);
00587  #endif
00588 #endif
00589     }
00590
00591
00592     //copy the texturecoords into the vvclEdgeLoopsTex structure
00593     numloops = m_vtSurfaces[0].vvclEdgeLoops.size();
00594 #ifdef OSG_KEEP_2D_POINTS
00595     ui_actvertidx = 0;
00596 #endif
00597 
00598     m_vtSurfaces[0].vvclEdgeLoopsTex.resize(numloops);
00599
00600     for(ui_actloop = 0; ui_actloop < numloops; ++ui_actloop)
00601     {
00602         actlooplength = m_vtSurfaces[0].vvclEdgeLoops[ui_actloop].size();
00603         m_vtSurfaces[0].vvclEdgeLoopsTex[ui_actloop].resize(actlooplength);
00604 #ifdef OSG_KEEP_2D_POINTS
00605 
00606         for(unsigned int ui_act = 0; ui_act < actlooplength; ++ui_act)
00607         {
00608             m_vtSurfaces[0].vvclEdgeLoopsTex[ui_actloop][ui_act] =
00609                 Vec3d(texturecoords[ui_actvertidx][0],
00610                       texturecoords[ui_actvertidx][1],
00611                       texturecoords[ui_actvertidx][2]);
00612             ui_actvertidx++;
00613         }
00614
00615 #else
00616         cl_surf.computeTexforTrimming(
00617             m_vtSurfaces[0].vvclEdgeLoops[ui_actloop],
00618             m_vtSurfaces[0].vvclEdgeLoopsTex[ui_actloop],
00619             &m_vvTextureControlPoints);
00620 #endif
00621     }
00622
00623
00624
00625
00626
00627 }
00628
00629
00630 void CNurbsPatchSurface::calculatePointsAndTextureCoords(
00631     std::vector<Pnt3f> &        gverts,
00632     std::vector<SimplePolygon> &tris,
00633     std::vector<Pnt2f> &        texturecoords)
00634 {
00635     BSplineTensorSurface cl_surf;
00636
00637
00638     cl_surf = m_vclBSplineSurfaces[0].getSurface();
00639     cl_surf.computeTex(m_vclParameterVertices,
00640                        gverts,
00641                        texturecoords,
00642                        &m_vvTextureControlPoints);
00643 /*
00644     std::cerr<<"haho"<< m_vclParameterVertices.size() << " " << gverts.size() << " " << norms.size() << std::endl;
00645     for ( UInt32 i = 0; i < gverts.size(); ++i )
00646     {
00647         std::cerr << gverts[i] << " " << norms[i] << std::endl;
00648     }
00649 */
00650     tris.clear();
00651     tris = m_vclTriangles;
00652
00653     //copy the normals into the vvclEdgeLoopsNorm structure
00654     unsigned int numloops = m_vtSurfaces[0].vvclEdgeLoops.size();
00655     unsigned int actlooplength;
00656 #ifdef OSG_KEEP_2D_POINTS
00657     unsigned int ui_actvertidx = 0;
00658 #endif
00659 
00660     Vec3d cl_norm;
00661 //    Int32 i_err;
00662     m_vtSurfaces[0].vvclEdgeLoopsTex.resize(numloops);
00663
00664     for(unsigned int ui_actloop = 0; ui_actloop < numloops; ++ui_actloop)
00665     {
00666         actlooplength = m_vtSurfaces[0].vvclEdgeLoops[ui_actloop].size();
00667         m_vtSurfaces[0].vvclEdgeLoopsTex[ui_actloop].resize(actlooplength);
00668 #ifdef OSG_KEEP_2D_POINTS
00669 
00670         for(unsigned int ui_act = 0; ui_act < actlooplength; ++ui_act)
00671         {
00672             m_vtSurfaces[0].vvclEdgeLoopsTex[ui_actloop][ui_act] =
00673                 Vec3d(texturecoords[ui_actvertidx][0],
00674                       texturecoords[ui_actvertidx][1],
00675                       texturecoords[ui_actvertidx][2]);
00676             ui_actvertidx++;
00677         }
00678
00679 #else
00680         cl_surf.computeTexforTrimming(
00681             m_vtSurfaces[0].vvclEdgeLoops[ui_actloop],
00682             m_vtSurfaces[0].vvclEdgeLoopsTex[ui_actloop],
00683             &m_vvTextureControlPoints);
00684 #endif
00685     }
00686
00687
00688
00689 }
00690
00691
00692
00693 // set error for given surface patch
00694 void CNurbsPatchSurface::SetError(const unsigned int cuiSurface, double dError)
00695 {
00696     if(cuiSurface >= m_vtSurfaces.size() )
00697     {
00698         return;
00699     }
00700
00701 //  std::cerr << "Setting error = " << dError << " for surface " << cuiSurface + 1 << "." << std::endl << std::endl;
00702
00703     m_vtSurfaces[cuiSurface].dError = dError;
00704 //  m_vtSurfaces[ cuiSurface ].ucStatus &= QUAD_TREE_INVALID_MASK;
00705     m_vtSurfaces[cuiSurface].ucStatus &= BEZIER_SURFACES_VALID;
00706 }
00707
00708
00709 // convert surface to piecewise bezier form
00710 void CNurbsPatchSurface::ConvertToBezier(unsigned int uiSurface)
00711 {
00712     BSplineTensorSurface&     rcl_bspline_surface  = m_vclBSplineSurfaces[uiSurface].getSurface();
00713     trimmingloop&             rvvcl_trimming_loops = m_vclBSplineSurfaces[uiSurface].getTrimmingLoops();
00714     bezier2dvector            vcl_beziertrimmingcurves;
00715     std::vector<unsigned int> vui_curves_per_loop(0);
00716     unsigned int              ui_tloops = rvvcl_trimming_loops.size();
00717     unsigned int              ui_curve;
00718
00719 //  std::cerr << "Converting surface " << uiSurface + 1 << " to bezier form." << std::endl;
00720
00721     vui_curves_per_loop.resize(ui_tloops);
00722     m_vtSurfaces[uiSurface].vvclBezierCurves.resize(ui_tloops);
00723
00724 //        std::cerr << "ConvertToBezier: numofloops: " << ui_tloops << std::endl;
00725     for(unsigned int ui_loop = 0; ui_loop < ui_tloops; ++ui_loop)
00726     {
00727         unsigned int ui_curves = rvvcl_trimming_loops[ui_loop].size();
00728         unsigned int ui_prev   = ui_curves - 1;
00729
00730         vui_curves_per_loop[ui_loop] = 0;
00731         vcl_beziertrimmingcurves.clear();
00732
00733         for(ui_curve = 0; ui_curve < ui_curves; ++ui_curve)
00734         {
00735 //          std::cerr << "processing curve " << ui_curve + 1 << std::endl;
00736             bezier2dvector vcl_converted_tmp;
00737             DCTPdvector    vd_pars;
00738
00739             DCTPVec3dvector vcl_cp =
00740                 rvvcl_trimming_loops[ui_loop][ui_prev].getControlPointVector();
00741             Vec3d cl_prev = vcl_cp[vcl_cp.size() - 1];
00742             vcl_cp = rvvcl_trimming_loops[ui_loop][ui_curve].getControlPointVector();
00743             if(DCTPVecIsNotEqual(cl_prev, vcl_cp[0]) )
00744             {
00745                 BezierCurve2D   cl_temp;
00746                 DCTPVec3dvector vcl_temp(2);
00747
00748                 vcl_temp[0] = cl_prev;
00749                 vcl_temp[1] = vcl_cp[0];
00750                 cl_temp.setControlPointVector(vcl_temp);
00751                 cl_temp.optimizeDegree();
00752 //              std::cerr << "inserting linear trimming curve to close gap." << std::endl;
00753 //              std::cerr << vcl_temp[ 0 ] << " -> " << vcl_temp[ 1 ] << std::endl;
00754                 vcl_beziertrimmingcurves.insert(vcl_beziertrimmingcurves.end(), cl_temp);
00755                 ++vui_curves_per_loop[ui_loop];
00756             }
00757             ui_prev = ui_curve;
00758
00759             if(rvvcl_trimming_loops[ui_loop][ui_curve].makeBezier(vcl_converted_tmp, vd_pars) )
00760             {
00761 //              SWARNING << "Conversion of trimming loop " << ui_loop + 1;
00762 //              SWARNING << " curve " << ui_curve + 1;
00763 //              SWARNING << " surface " << uiSurface + 1 << " to bezier form failed!" << endLog;
00764             }
00765             else
00766             {
00767                 vcl_beziertrimmingcurves.insert(
00768                     vcl_beziertrimmingcurves.end(), vcl_converted_tmp.begin(), vcl_converted_tmp.end() );
00769                 vui_curves_per_loop[ui_loop] += vcl_converted_tmp.size();
00770             }
00771         }
00772
00773         // check for colinear trimming
00774         for(ui_curve = 0; ui_curve < vcl_beziertrimmingcurves.size(); ++ui_curve)
00775         {
00776             unsigned int ui_next = (ui_curve + 1) % vcl_beziertrimmingcurves.size();
00777
00778             // check if both linear
00779             if( (vcl_beziertrimmingcurves[ui_curve].getControlPointVector().size() == 2) &&
00780                 (vcl_beziertrimmingcurves[ui_next].getControlPointVector().size() == 2) &&
00781                 (DCTPVecIsEqual(vcl_beziertrimmingcurves[ui_curve].getControlPointVector()[1],
00782                                 vcl_beziertrimmingcurves[ui_next].getControlPointVector()[0]) ) )
00783             {
00784                 // check if colinear
00785                 Vec2d cl_s0, cl_e0, cl_s1, cl_e1;
00786                 Vec2d cl_tmp;
00787
00788                 cl_s0[0] = vcl_beziertrimmingcurves[ui_curve].getControlPointVector()[0][0]
00789                            / vcl_beziertrimmingcurves[ui_curve].getControlPointVector()[0][2];
00790                 cl_s0[1] = vcl_beziertrimmingcurves[ui_curve].getControlPointVector()[0][1]
00791                            / vcl_beziertrimmingcurves[ui_curve].getControlPointVector()[0][2];
00792
00793                 cl_e0[0] = vcl_beziertrimmingcurves[ui_curve].getControlPointVector()[1][0]
00794                            / vcl_beziertrimmingcurves[ui_curve].getControlPointVector()[1][2];
00795                 cl_e0[1] = vcl_beziertrimmingcurves[ui_curve].getControlPointVector()[1][1]
00796                            / vcl_beziertrimmingcurves[ui_curve].getControlPointVector()[1][2];
00797
00798                 cl_s1[0] = vcl_beziertrimmingcurves[ui_next].getControlPointVector()[0][0]
00799                            / vcl_beziertrimmingcurves[ui_next].getControlPointVector()[0][2];
00800                 cl_s1[1] = vcl_beziertrimmingcurves[ui_next].getControlPointVector()[0][1]
00801                            / vcl_beziertrimmingcurves[ui_next].getControlPointVector()[0][2];
00802
00803                 cl_e1[0] = vcl_beziertrimmingcurves[ui_next].getControlPointVector()[1][0]
00804                            / vcl_beziertrimmingcurves[ui_next].getControlPointVector()[1][2];
00805                 cl_e1[1] = vcl_beziertrimmingcurves[ui_next].getControlPointVector()[1][1]
00806                            / vcl_beziertrimmingcurves[ui_next].getControlPointVector()[1][2];
00807
00808                 cl_tmp = cl_e1 - cl_s0;
00809
00810                 cl_tmp *= 1.0 / sqrt(cl_tmp.squareLength() );
00811                 cl_tmp *= cl_tmp.dot(cl_e0 - cl_s0);
00812                 cl_tmp -= cl_e0 - cl_s0;
00813
00814                 if(cl_tmp.squareLength() < DCTP_EPS * DCTP_EPS)
00815                 {
00816                     if(ui_next == 0)
00817                     {
00818                         vcl_beziertrimmingcurves[ui_next].getControlPointVector()[0] =
00819                             vcl_beziertrimmingcurves[ui_curve].getControlPointVector()[0];
00820                     }
00821                     else
00822                     {
00823                         vcl_beziertrimmingcurves[ui_curve].getControlPointVector()[1] =
00824                             vcl_beziertrimmingcurves[ui_next].getControlPointVector()[1];
00825
00826                         for( ; ui_next < vcl_beziertrimmingcurves.size() - 1; ++ui_next)
00827                         {
00828                             vcl_beziertrimmingcurves[ui_next] = vcl_beziertrimmingcurves[ui_next + 1];
00829                         }
00830                     }
00831                     vcl_beziertrimmingcurves.pop_back();
00832                     --ui_curve;
00833                 }
00834             }
00835         }
00836
00837         vui_curves_per_loop[ui_loop] = vcl_beziertrimmingcurves.size();
00838
00839 //      std::cerr << "loop " << ui_loop + 1 << " contains " << vui_curves_per_loop[ ui_loop ] << " curves." << std::endl;
00840         for(ui_curve = 0; ui_curve < vui_curves_per_loop[ui_loop]; ++ui_curve)
00841         {
00842 /*          Vec2dvector vcl_cp = vcl_beziertrimmingcurves[ ui_curve ].getControlPointVector( );
00843 
00844             std::cerr << vcl_cp[ 0 ] << " -> " << vcl_cp[ vcl_cp.size( ) - 1 ] << std::endl;*/
00845             m_vtSurfaces[uiSurface].vvclBezierCurves[ui_loop].push_back(vcl_beziertrimmingcurves[ui_curve]);
00846         }
00847     }
00848
00849     if(rcl_bspline_surface.makeBezier(m_vvvclBezierSurfaces[uiSurface],
00850                                       m_vvdUParams[uiSurface],
00851                                       m_vvdVParams[uiSurface]) )
00852     {
00853 //      SWARNING << "Conversion of surface " << uiSurface + 1 << " to bezier form failed!" << endLog;
00854     }
00855
00856 #ifdef OSG_3D_LOOPS
00857     Gen3DLoops(uiSurface);
00858     m_vvvclBezierSurfaces[uiSurface].clear();
00859 #endif
00860 
00861 //  std::cerr <<"numofbeziers: " << m_vvvclBezierSurfaces[ uiSurface ].size() << " " <<
00862 //                                   m_vvvclBezierSurfaces[ uiSurface ][0].size() << std::endl;
00863     m_vtSurfaces[uiSurface].ucStatus |= BEZIER_SURFACES_VALID;
00864 }
00865
00866
00867 //this is a new one, that has to be called twice because of the direct
00868 //NURBS usage
00869
00870 // set up quad tree with saved error
00871 void CNurbsPatchSurface::CalculateQuadTree(unsigned int uiSurface, bool bForEdges)
00872 {
00873     if(!(m_vtSurfaces[uiSurface].ucStatus & BEZIER_SURFACES_VALID) )
00874     {
00875         std::cerr << "Bezier surfaces invalid for surface " << uiSurface + 1 << std::endl;
00876         return;
00877     }
00878
00879 //  std::cerr << "Building QuadTree for surface " << uiSurface + 1 << "." << std::endl;
00880
00881 //  m_vclSeperateMeshes[ uiSurface ].reinit( );
00882     if(bForEdges)
00883     {
00884         if(m_vtSurfaces[uiSurface].vvcl3DCurves.size() != 0)
00885         {
00886             // no quadtree required when 3d loops are present
00887             m_vtSurfaces[uiSurface].ucStatus |= QUAD_TREE_VALID;
00888             return;
00889         }
00890 //      std::cerr << "q";
00891         m_clMesh.reinit();
00892
00893         m_pclQuadTree = new QuadTreeCreator(&m_clMesh /*, bForEdges*/);
00894 //      m_pclQuadTree = new QuadTreeCreator( &m_vclSeperateMeshes[ uiSurface ] );
00895         m_pclQuadTree->setErrorTolerance(m_vtSurfaces[uiSurface].dError / 3.0);
00896         if(m_pclQuadTree->setInitialLeaves(m_vvvclBezierSurfaces[uiSurface],
00897                                            m_vvdUParams[uiSurface],
00898                                            m_vvdVParams[uiSurface]) )
00899         {
00900             std::cerr << "QuadTree setup of surface " << uiSurface + 1 << " failed." << std::endl;
00901             m_vtSurfaces[uiSurface].ucStatus |= QUAD_TREE_ERROR;
00902             delete m_pclQuadTree;
00903             return;
00904         }
00905 #ifndef OSG_ADAPTIVE_QUAD_TREE
00906         if(m_pclQuadTree->createQuadTree() )
00907         {
00908             std::cerr << "QuadTree creation of surface " << uiSurface + 1 << " failed." << std::endl;
00909             m_vtSurfaces[uiSurface].ucStatus |= QUAD_TREE_ERROR;
00910             delete m_pclQuadTree;
00911             return;
00912         }
00913         delete m_pclQuadTree;
00914 #endif
00915     }
00916     else //2nd round...
00917     {
00918 //      std::cerr << "b";
00919         m_clMesh.reinit();
00920
00921 #ifdef OSG_USE_NURBS_PATCH
00922         m_vtSurfaces[uiSurface].pclErrorTree->BuildMesh(&m_clMesh,
00923                                                         &(m_vclBSplineSurfaces[uiSurface].getSurface() ),
00924  #ifdef OSG_ARBITRARY_SPLIT
00925                                                         m_vtSurfaces[uiSurface].clMinParam,
00926                                                         m_vtSurfaces[uiSurface].clMaxParam,
00927  #endif
00928                                                         m_vtSurfaces[uiSurface].dError,
00929                                                         m_vtSurfaces[uiSurface].fMinError,
00930                                                         m_vtSurfaces[uiSurface].fMaxError);
00931 #else
00932         m_vtSurfaces[uiSurface].pclErrorTree->BuildMesh(&m_clMesh,
00933                                                         &m_vvvclBezierSurfaces[uiSurface],
00934                                                         &m_vvdUParams[uiSurface],
00935                                                         &m_vvdVParams[uiSurface],
00936                                                         m_vtSurfaces[uiSurface].dError,
00937                                                         m_vtSurfaces[uiSurface].fMinError,
00938                                                         m_vtSurfaces[uiSurface].fMaxError);
00939 #endif
00940 //      std::cerr << "min error = " << m_vtSurfaces[ uiSurface ].fMinError << std::endl;
00941 //      std::cerr << "max error = " << m_vtSurfaces[ uiSurface ].fMaxError << std::endl;
00942 //#endif
00943     }
00944     m_vtSurfaces[uiSurface].ucStatus |= QUAD_TREE_VALID;
00945 }
00946
00947
00948
00949
00950
00951
00952 // calculate finest trimming curve
00953 void CNurbsPatchSurface::CalculateTrimmingLoops(unsigned int uiSurface)
00954 {
00955     bezier2ddequevector vvcl_curves = m_vtSurfaces[uiSurface].vvclBezierCurves;
00956
00957     if(!(m_vtSurfaces[uiSurface].ucStatus & QUAD_TREE_VALID) )
00958     {
00959         std::cerr << "Quad tree invalid for surface " << uiSurface + 1 << std::endl;
00960         m_vtSurfaces[uiSurface].clMin = Vec3d(m_vtSurfaces[uiSurface].dError * 100, m_vtSurfaces[uiSurface].dError * 100, m_vtSurfaces[uiSurface].dError * 100);
00961         m_vtSurfaces[uiSurface].clMax = Vec3d(0, 0, 0);     // this is invalid and will always fail BB test
00962         return;
00963     }
00964
00965 //  std::cerr << "t";
00966
00967     ParSpaceTrimmer cl_trimmer;
00968
00969     if(m_vtSurfaces[uiSurface].vvcl3DCurves.size() != 0)
00970     {
00971  #ifdef OSG_USE_SIMPLIFIER
00972         cl_trimmer.Initialize(m_clMesh, vvcl_curves,
00973                               m_vtSurfaces[uiSurface].vvcl3DCurves,
00974                               m_vtSurfaces[uiSurface].vvclEdgeLoops,
00975                               m_vtSurfaces[uiSurface].dError,
00976                               &m_vclBSplineSurfaces[uiSurface].getSurface() );
00977  #else
00978         cl_trimmer.Initialize(m_clMesh, vvcl_curves,
00979                               m_vtSurfaces[uiSurface].vvcl3DCurves,
00980                               m_vtSurfaces[uiSurface].vvclEdgeLoops,
00981                               m_vtSurfaces[uiSurface].dError);
00982  #endif
00983     }
00984     else
00985     {
00986 #ifdef OSG_ADAPTIVE_QUAD_TREE
00987  #ifdef OSG_USE_SIMPLIFIER
00988         cl_trimmer.Initialize(m_clMesh, vvcl_curves,
00989                               m_vtSurfaces[uiSurface].vvclEdgeLoops, m_pclQuadTree,
00990                               &m_vclBSplineSurfaces[uiSurface].getSurface() );
00991  #else
00992         cl_trimmer.Initialize(m_clMesh, vvcl_curves, m_vtSurfaces[uiSurface].vvclEdgeLoops, m_pclQuadTree);
00993  #endif
00994 #else
00995         cl_trimmer.Initialize(m_clMesh, vvcl_curves, m_vtSurfaces[uiSurface].vvclEdgeLoops);
00996 #endif
00997     }
00998     try
00999     {
01000         if(cl_trimmer.PerformTrimming() )
01001         {
01002             std::cerr << "Par space trimmer failed (surface " << uiSurface + 1 << ")." << std::endl;
01003             m_vtSurfaces[uiSurface].clMin = Vec3d(m_vtSurfaces[uiSurface].dError * 100, m_vtSurfaces[uiSurface].dError * 100, m_vtSurfaces[uiSurface].dError * 100);
01004             m_vtSurfaces[uiSurface].clMax = Vec3d(0, 0, 0);     // this is invalid and will always fail BB test
01005 #ifndef OSG_ADAPTIVE_QUAD_TREE
01006             if(m_pclQuadTree != NULL)
01007             {
01008                 delete m_pclQuadTree;
01009                 m_pclQuadTree = NULL;
01010             }
01011 #endif
01012             return;
01013         }
01014     }
01015     catch(ParSpaceTrimmerError cl_err)
01016     {
01017         std::cerr << "Par space trimmer exception caught: " << cl_err.errtype << " (surface " << uiSurface + 1 << ")" << std::endl;
01018         m_vtSurfaces[uiSurface].clMin = Vec3d(m_vtSurfaces[uiSurface].dError * 100, m_vtSurfaces[uiSurface].dError * 100, m_vtSurfaces[uiSurface].dError * 100);
01019         m_vtSurfaces[uiSurface].clMax = Vec3d(0, 0, 0);     // this is invalid and will always fail BB test
01020 #ifndef OSG_ADAPTIVE_QUAD_TREE
01021         if(m_pclQuadTree != NULL)
01022         {
01023             delete m_pclQuadTree;
01024             m_pclQuadTree = NULL;
01025         }
01026 #endif
01027         return;
01028     }
01029
01030
01031 //    int                i_err;
01032     const unsigned int cui_size =
01033         m_vtSurfaces[uiSurface].vvclEdgeLoops.size();
01034
01035     m_vtSurfaces[uiSurface].vvclEdgeLoops3D.resize(cui_size);
01036     m_vtSurfaces[uiSurface].vbReversed.resize(cui_size);
01037     m_vtSurfaces[uiSurface].vbUsed.resize(cui_size);
01038
01039 //        std::cerr <<"edgeloops.size(): " << cui_size << std::endl;
01040     unsigned int ui_vertex;
01041
01042     for(unsigned int ui_loop = 0; ui_loop < cui_size; ++ui_loop)
01043     {
01044 //      std::cerr << "edge loop " << ui_loop + 1 << " of " << cui_size << std::endl;
01045         const unsigned int cui_size2 = m_vtSurfaces[uiSurface].vvclEdgeLoops[ui_loop].size();
01046         std::vector<Pnt3f> vcl_temp3d;
01047
01048         m_vtSurfaces[uiSurface].vvclEdgeLoops3D[ui_loop].resize(cui_size2);
01049         vcl_temp3d.resize(cui_size2);
01050         m_vclBSplineSurfaces[uiSurface].getSurface().compute(
01051             m_vtSurfaces[uiSurface].vvclEdgeLoops[ui_loop],
01052             vcl_temp3d);
01053
01054         for(ui_vertex = 0; ui_vertex < cui_size2; ++ui_vertex)
01055         {
01056 //          std::cerr << "vertex " << ui_vertex + 1 << " of " << cui_size2 << std::endl;
01057 /*          const Vec3d ccl_vec = m_vclBSplineSurfaces[ uiSurface ].getSurface( ).compute(
01058                 m_vtSurfaces[ uiSurface ].vvclEdgeLoops[ ui_loop ][ ui_vertex ],
01059                 i_err );*/
01060             Vec3d ccl_vec;
01061             ccl_vec[0] = vcl_temp3d[ui_vertex][0];
01062             ccl_vec[1] = vcl_temp3d[ui_vertex][1];
01063             ccl_vec[2] = vcl_temp3d[ui_vertex][2];
01064 //          std::cerr << "pos: " << ccl_vec << std::endl;
01065
01066             m_vtSurfaces[uiSurface].vvclEdgeLoops3D[ui_loop][ui_vertex] = ccl_vec;
01067
01068             if( (ui_loop == 0) && (ui_vertex == 0) )
01069             {
01070                 m_vtSurfaces[uiSurface].clMin     =
01071                     m_vtSurfaces[uiSurface].clMax = ccl_vec;
01072 #ifdef OSG_ARBITRARY_SPLIT
01073                 m_vtSurfaces[uiSurface].clMinParam = m_vtSurfaces[uiSurface].clMaxParam =
01074                                                          m_vtSurfaces[uiSurface].vvclEdgeLoops[ui_loop][ui_vertex];
01075 #endif
01076             }
01077             else
01078             {
01079                 if(ccl_vec[0] < m_vtSurfaces[uiSurface].clMin[0])
01080                     m_vtSurfaces[uiSurface].clMin[0] = ccl_vec[0];
01081                 else if(ccl_vec[0] > m_vtSurfaces[uiSurface].clMax[0])
01082                     m_vtSurfaces[uiSurface].clMax[0] = ccl_vec[0];
01083                 if(ccl_vec[1] < m_vtSurfaces[uiSurface].clMin[1])
01084                     m_vtSurfaces[uiSurface].clMin[1] = ccl_vec[1];
01085                 else if(ccl_vec[1] > m_vtSurfaces[uiSurface].clMax[1])
01086                     m_vtSurfaces[uiSurface].clMax[1] = ccl_vec[1];
01087                 if(ccl_vec[2] < m_vtSurfaces[uiSurface].clMin[2])
01088                     m_vtSurfaces[uiSurface].clMin[2] = ccl_vec[2];
01089                 else if(ccl_vec[2] > m_vtSurfaces[uiSurface].clMax[2])
01090                     m_vtSurfaces[uiSurface].clMax[2] = ccl_vec[2];
01091 #ifdef OSG_ARBITRARY_SPLIT
01092                 if(m_vtSurfaces[uiSurface].vvclEdgeLoops[ui_loop][ui_vertex][0] < m_vtSurfaces[uiSurface].clMinParam[0])
01093                     m_vtSurfaces[uiSurface].clMinParam[0] = m_vtSurfaces[uiSurface].vvclEdgeLoops[ui_loop][ui_vertex][0];
01094                 else if(m_vtSurfaces[uiSurface].vvclEdgeLoops[ui_loop][ui_vertex][0] > m_vtSurfaces[uiSurface].clMaxParam[0])
01095                     m_vtSurfaces[uiSurface].clMaxParam[0] = m_vtSurfaces[uiSurface].vvclEdgeLoops[ui_loop][ui_vertex][0];
01096                 if(m_vtSurfaces[uiSurface].vvclEdgeLoops[ui_loop][ui_vertex][1] < m_vtSurfaces[uiSurface].clMinParam[1])
01097                     m_vtSurfaces[uiSurface].clMinParam[1] = m_vtSurfaces[uiSurface].vvclEdgeLoops[ui_loop][ui_vertex][1];
01098                 else if(m_vtSurfaces[uiSurface].vvclEdgeLoops[ui_loop][ui_vertex][1] > m_vtSurfaces[uiSurface].clMaxParam[1])
01099                     m_vtSurfaces[uiSurface].clMaxParam[1] = m_vtSurfaces[uiSurface].vvclEdgeLoops[ui_loop][ui_vertex][1];
01100 #endif
01101             }
01102         }
01103
01104         //check direction
01105         SimplePolygon cl_check;
01106 //                std::cerr <<"baszom1: " << cui_size2 << std::endl;
01107         cl_check.vertices.resize(cui_size2 - 1);
01108
01109         for(ui_vertex = 0; ui_vertex < cui_size2 - 1; ++ui_vertex)
01110         {
01111             cl_check.vertices[ui_vertex] = ui_vertex;
01112         }
01113
01114 //                std::cerr <<"baszom2" << std::endl;
01115 //                std::cerr <<"checked vector: " << std::endl;
01116 //                unsigned int kk = m_vtSurfaces[ uiSurface ].vvclEdgeLoops[ ui_loop ].size();
01117 //                for (unsigned int iii = 0; iii < kk; ++iii)
01118 //                    std::cerr << m_vtSurfaces[ uiSurface ].vvclEdgeLoops[ ui_loop
01119 //                            ][iii] << std::endl;
01120
01121
01122
01123         if(cl_check.isReversed(m_vtSurfaces[uiSurface].vvclEdgeLoops[ui_loop]) )
01124         {
01125 //          std::cerr << "loop is reversed" << std::endl;
01126             m_vtSurfaces[uiSurface].vbReversed[ui_loop] = true;
01127 //                        std::cerr <<"baszom2.5" << std::endl;
01128
01129         }
01130         else
01131         {
01132 //          std::cerr << "loop is normal" << std::endl;
01133             m_vtSurfaces[uiSurface].vbReversed[ui_loop] = false;
01134 //                        std::cerr <<"baszom2.6"<<std::endl;
01135         }
01136 //                std::cerr <<"baszom3"<<std::endl;
01137         m_vtSurfaces[uiSurface].vbUsed[ui_loop] = true;
01138
01139     }
01140
01141     m_vtSurfaces[uiSurface].clMin -= Vec3d(m_vtSurfaces[uiSurface].dError, m_vtSurfaces[uiSurface].dError, m_vtSurfaces[uiSurface].dError);
01142     m_vtSurfaces[uiSurface].clMax += Vec3d(m_vtSurfaces[uiSurface].dError, m_vtSurfaces[uiSurface].dError, m_vtSurfaces[uiSurface].dError);
01143 #ifdef OSG_ADAPTIVE_QUAD_TREE
01144     if(m_pclQuadTree != NULL)
01145     {
01146         delete m_pclQuadTree;
01147         m_pclQuadTree = NULL;
01148     }
01149 #endif
01150     m_vtSurfaces[uiSurface].ucStatus |= TRIMMING_VALID;
01151 }
01152
01153
01154
01155
01156
01157 // calculate actual trimming curve
01158 void CNurbsPatchSurface::CalculateActualTrimming(unsigned int uiSurface)
01159 {
01160     ParSpaceTrimmer cl_trimmer;
01161
01162 //  std::cerr << "g";
01163
01165
01166 #ifdef OSG_FORCE_NO_T_VERTICES
01167     cl_trimmer.Initialize2(m_clMesh,
01168                            m_vtSurfaces[uiSurface].vvclEdgeLoops,
01169                            m_vtSurfaces[uiSurface].vvclEdgeLoops3D,
01170 //                m_vtSurfaces[ uiSurface ].vvclEdgeLoopsNorm,
01171                            m_vtSurfaces[uiSurface].vbReversed,
01172                            m_vtSurfaces[uiSurface].vbUsed);
01173
01174 #else
01175     cl_trimmer.Initialize2(m_clMesh, m_vtSurfaces[uiSurface].vvclEdgeLoops, m_vtSurfaces[uiSurface].vvclEdgeLoops3D, m_vtSurfaces[uiSurface].vbReversed, m_vtSurfaces[uiSurface].vbUsed);
01176 #endif /* OSG_FORCE_NO_T_VERTICES */
01177 //  cl_trimmer.Initialize2( m_vclSeperateMeshes[ uiSurface ], m_vtSurfaces[ uiSurface ].vvclEdgeLoops );
01178     try
01179     {
01180         if(cl_trimmer.PerformTrimming2() )
01181         {
01182             std::cerr << "Par space trimmer2 failed (surface " << uiSurface + 1 << ")." << std::endl;
01183             return;
01184         }
01185     }
01186     catch(ParSpaceTrimmerError cl_err)
01187     {
01188         std::cerr << "Par space trimmer2 exception caught: " << cl_err.errtype << " (surface " << uiSurface + 1 << ")" << std::endl;
01189         return;
01190     }
01191
01192 #ifndef OSG_FORCE_NO_T_VERTICES
01193     // get new trimming loops
01194     cl_trimmer.getTrimmingLoops(m_vtSurfaces[uiSurface].vvclEdgeLoops);
01195 #endif
01196 
01197     try
01198     {
01199         if(m_pclGraph)
01200         {
01201             delete m_pclGraph;
01202         }
01203         m_pclGraph = new DirectedGraph<Vec2d, unsigned char>;
01204 #ifdef OSG_KEEP_2D_POINTS
01205         if(cl_trimmer.buildSurfaceGraph(m_pclGraph, &m_vclGlobalVertices, NULL, &m_vuiIndex) )
01206 #else
01207         if(cl_trimmer.buildSurfaceGraph(m_pclGraph, &m_vclGlobalVertices) )
01208 #endif
01209         {
01210             std::cerr << "Build surface graph failed (surface " << uiSurface + 1 << ")." << std::endl;
01211             return;
01212         }
01213     }
01214     catch(ParSpaceTrimmerError cl_err)
01215     {
01216         std::cerr << "Par space trimmer exception caught: " << cl_err.errtype << " (surface " << uiSurface + 1 << ")" << std::endl;
01217 //      m_vtSurfaces[ uiSurface ].ucStatus |= TRIMMING_ERROR;
01218         return;
01219     }
01220
01221     m_vtSurfaces[uiSurface].ucStatus |= TRIMMING_VALID;
01222 }
01223
01224
01225 // perform graph traversal
01226 void CNurbsPatchSurface::CalculateGraph(unsigned int uiSurface, bool usedelaunay)
01227 {
01228     GraphTraverser cl_traverser;
01229
01230     if(!(m_vtSurfaces[uiSurface].ucStatus & TRIMMING_VALID) )
01231     {
01232         std::cerr << "Trimming invalid for surface " << uiSurface + 1 << std::endl;
01233         return;
01234     }
01235
01236 //  std::cerr << "t";
01237 //  std::cerr << "Traversing graph of surface " << uiSurface + 1 << "." << std::endl;
01238
01239     cl_traverser.Initialize(*m_pclGraph, usedelaunay);
01240     try
01241     {
01242         if(cl_traverser.Traverse() )
01243         {
01244             std::cerr << "Graph traverser failed (surface " << uiSurface + 1 << ")." << std::endl;
01245 //          m_vtSurfaces[ uiSurface ].ucStatus |= TRIANGULATION_ERROR;
01246 //          return;
01247         }
01248     }
01249     catch(GraphTraverserError cl_err)
01250     {
01251         std::cerr << "Graph traverser exception caught: " << cl_err.errtype << " (surface " << uiSurface + 1 << ")" << std::endl;
01252 //      m_vtSurfaces[ uiSurface ].ucStatus |= TRIANGULATION_ERROR;
01253 //      return;
01254     }
01255
01256     m_vclTriangles                    = *(cl_traverser.getPolys() );
01257     m_vclParameterVertices            = *(cl_traverser.getVertices() );
01258     m_vtSurfaces[uiSurface].ucStatus |= TRIANGULATION_VALID;
01259
01260 #ifdef OSG_KEEP_2D_POINTS
01261     // change triangle vertices to indices of trimming loop vertex
01262     const unsigned int cui_size = m_vclTriangles.size();
01263     unsigned int       ui_idx;
01264
01265     for(ui_idx = 0; ui_idx < cui_size; ++ui_idx)
01266     {
01267         std::vector<int> & rvi_verts    = m_vclTriangles[ui_idx].vertices;
01268         const unsigned int cui_vert_cnt = rvi_verts.size();
01269         unsigned int       ui_vert;
01270
01271         for(ui_vert = 0; ui_vert < cui_vert_cnt; ++ui_vert)
01272         {
01273             // change triangle indices
01274             if(rvi_verts[ui_vert] < ( int ) m_vuiIndex.size() )
01275                 rvi_verts[ui_vert] = ( int ) m_vuiIndex[rvi_verts[ui_vert]];
01276         }
01277     }
01278
01279     // copy trimming loops to global vertices
01280     const unsigned int cui_loop_cnt = m_vtSurfaces[0].vvclEdgeLoops3D.size();
01281     unsigned int       ui_loop;
01282
01283     ui_idx = 0;
01284
01285     for(ui_loop = 0; ui_loop < cui_loop_cnt; ++ui_loop)
01286     {
01287         if(m_vtSurfaces[0].vbUsed[ui_loop])
01288         {
01289             const unsigned int cui_vert_cnt = m_vtSurfaces[0].vvclEdgeLoops[ui_loop].size();
01290             unsigned int       ui_vert;
01291
01292             for(ui_vert = 0; ui_vert < cui_vert_cnt; ++ui_vert)
01293             {
01294                 m_vclParameterVertices[ui_idx] = m_vtSurfaces[0].vvclEdgeLoops[ui_loop][ui_vert];
01295                 ++ui_idx;
01296             }
01297         }
01298     }
01299
01300 /*  if( m_vclGlobalVertices.size( ) > ui_idx )
01301     {
01302         m_vclGlobalVertices.resize( ui_idx );
01303     }*/
01304 #endif
01305 }
01306
01307
01308
01309
01310 void CNurbsPatchSurface::ComputeNormalCone(const unsigned int  cuiSurface,
01311                                            std::vector<Vec3f>& normals)
01312 {
01313 /*  unsigned int    ui_cnt = 0;
01314 
01315     Miniball<3> cl_miniball;
01316     for ( unsigned int ui_normal= 0; ui_normal < normals.size(); ++ui_normal )
01317     {
01318         double  d_len = normals[ ui_normal ].length( );
01319         if( d_len > DCTP_EPS )
01320         {
01321             normals[ ui_normal ] *= 1.0 / d_len;
01322 //          std::cerr << normals[ ui_normal ] << std::endl;
01323             Miniball<3>::Point cl_point;
01324             cl_point[ 0 ]=  normals[ ui_normal ].x();
01325             cl_point[ 1 ]=  normals[ ui_normal ].y();
01326             cl_point[ 2 ]=  normals[ ui_normal ].z();
01327             cl_miniball.check_in( cl_point );
01328             ++ui_cnt;
01329         }
01330     }
01331 //  std::cerr << "-----" << std::endl;
01332 
01333     cl_miniball.build();
01334 
01335     Vec3d cl_center;
01336     cl_center[0]= cl_miniball.center()[0];
01337     cl_center[1]= cl_miniball.center()[1];
01338     cl_center[2]= cl_miniball.center()[2];
01339 
01340     // compute intersection of sphere bounding the normals with unit sphere
01341     // => formula from http://astronomy.swin.edu.au/~pbourke/geometry/spheresphere/
01342 double d_distance_squared= cl_center.squareLength();
01343 
01344     if ( (d_distance_squared < 0.001) || ( ui_cnt < 3 ) )
01345     {
01346         // arbitrary direction
01347         m_vtSurfaces[ cuiSurface ].tNormalCone.clDirection= Vec3d(1.0, 0.0, 0.0);
01348 
01349         // angle > 180 degrees
01350         m_vtSurfaces[ cuiSurface ].tNormalCone.dThreshold = 1.0;
01351         return;
01352     }
01353 
01354     double d_nominator_root= ( d_distance_squared - cl_miniball.squared_radius( ) + 1.0 ) * 0.5;
01355     double d_height= sqrt( 1.0 - ( d_nominator_root * d_nominator_root ) / d_distance_squared );
01356     cl_center *= 1.0 / sqrt( d_distance_squared );//.normalize();
01357 
01358     m_vtSurfaces[ cuiSurface ].tNormalCone.clDirection= cl_center;
01359     m_vtSurfaces[ cuiSurface ].tNormalCone.dThreshold = d_height;
01360 
01361 //  std::cerr << cl_center << std::endl;
01362 //  std::cerr << d_height << std::endl;*/
01363 }
01364
01365 void CNurbsPatchSurface::Gen3DLoops(const unsigned int cuiSurface)
01366 {
01367     const unsigned int        cui_loop_cnt = m_vtSurfaces[cuiSurface].vvclBezierCurves.size();
01368     unsigned int              ui_loop;
01369     unsigned int              ui_curve_cnt;
01370     unsigned int              ui_curve;
01371     bezier2ddeque             vcl_new_curves;
01372     std::vector<unsigned int> vui_u_seg;
01373     std::vector<unsigned int> vui_v_seg;
01374     unsigned int              ui_dim;
01375     unsigned int              ui_pos;
01376     Vec2d                     cl_param;
01377     std::vector<Vec4d>        vcl_points;
01378     int                       i_err;
01379
01380     m_vtSurfaces[cuiSurface].vvcl3DCurves.resize(cui_loop_cnt);
01381
01382     for(ui_loop = 0; ui_loop < cui_loop_cnt; ++ui_loop)
01383     {
01384         // first cut the curves with the bezier patches
01385         vcl_new_curves.clear();
01386         vui_u_seg.clear();
01387         vui_v_seg.clear();
01388         ui_curve_cnt = m_vtSurfaces[cuiSurface].vvclBezierCurves[ui_loop].size();
01389
01390         for(ui_curve = 0; ui_curve < ui_curve_cnt; ++ui_curve)
01391         {
01392             CutCurve(cuiSurface, m_vtSurfaces[cuiSurface].vvclBezierCurves[ui_loop][ui_curve],
01393                      vcl_new_curves, vui_u_seg, vui_v_seg);
01394         }
01395
01396         m_vtSurfaces[cuiSurface].vvclBezierCurves[ui_loop] = vcl_new_curves;
01397
01398         // then elevate the trimming curves into 3d space
01399         ui_curve_cnt = m_vtSurfaces[cuiSurface].vvclBezierCurves[ui_loop].size();
01400         m_vtSurfaces[cuiSurface].vvcl3DCurves[ui_loop].resize(ui_curve_cnt);
01401
01402         for(ui_curve = 0; ui_curve < ui_curve_cnt; ++ui_curve)
01403         {
01404             const unsigned int   cui_u_seg   = vui_u_seg[ui_curve];
01405             const unsigned int   cui_v_seg   = vui_v_seg[ui_curve];
01406             BezierTensorSurface &rcl_surf    = m_vvvclBezierSurfaces[cuiSurface][cui_u_seg][cui_v_seg];
01407             BezierCurve2D &      rcl_curve2d = m_vtSurfaces[cuiSurface].vvclBezierCurves[ui_loop][ui_curve];
01408
01409             rcl_curve2d.optimizeDegree();
01410
01411             // REMARK:
01412             // Even though there exists a closed formula which
01413             // gives the degree of a rational Bezier curve elevated by
01414             // a rational Bezier patch, here we don't take into account
01415             // the weights of the elevating Bezier patch and therefore
01416             // this degree approximation is necessary for rational
01417             // trimming curves. The closed formula is also quite
01418             // expensive to calculate, our method is a bit cheaper.
01419             // Although it usually overestimates the degree, it doesn't
01420             // really matter in practice since the approximated 3D
01421             // Bezier curve will be degree reduced as much as possible.
01422             // And this method was easier to implement anyway. :-)
01423             unsigned int approxdegree = rcl_curve2d.computeNonratApproximationDegree(1e-4);
01424             ui_dim = ( (rcl_surf.getControlPointMatrix().size() - 1)
01425                        + (rcl_surf.getControlPointMatrix()[0].size() - 1) )
01426                      * approxdegree;
01427 #ifdef OSG_NURBS_DEBUG
01428             if(approxdegree != rcl_curve2d.getControlPointVector().size() - 1)
01429             {
01430                 std::cerr << "approxdegree: " << approxdegree << " dim: " << ui_dim << std::endl;
01431             }
01432 #endif /* OSG_NURBS_DEBUG */
01433
01434             if(ui_dim > 40)
01435                 ui_dim = 40;
01436
01437             vcl_points.clear();
01438
01439             for(ui_pos = 0; ui_pos <= ui_dim; ++ui_pos)
01440             {
01441                 i_err    = 0;
01442                 cl_param = rcl_curve2d.computewdeCasteljau( (double(ui_pos) ) / ui_dim, i_err);
01443 //              vcl_points.push_back( rcl_surf.computewdeCasteljau( cl_param, i_err ) );
01444                 vcl_points.push_back(m_vclBSplineSurfaces[cuiSurface].getSurface().compute4D(cl_param, i_err) );
01445             }
01446
01447             if(m_vtSurfaces[cuiSurface].vvcl3DCurves[ui_loop][ui_curve].createCurve(vcl_points) == 0)
01448             {
01449                 m_vtSurfaces[cuiSurface].vvcl3DCurves[ui_loop][ui_curve].optimizeDegree();
01450             }
01451 #ifdef OSG_NURBS_DEBUG
01452             if(approxdegree != rcl_curve2d.getControlPointVector().size() - 1)
01453             {
01454                 std::cerr << "optimdegree: " << m_vtSurfaces[cuiSurface].vvcl3DCurves[ui_loop][ui_curve].getControlPointVector().size() - 1 << std::endl;
01455             }
01456 #endif /* OSG_NURBS_DEBUG */
01457 //          rcl_curve2d.write( );
01458 //          m_vtSurfaces[ cuiSurface ].vvcl3DCurves[ ui_loop ][ ui_curve ].write( );
01459         }
01460     }
01461 }
01462
01463 void CNurbsPatchSurface::CutCurve(const unsigned int cuiSurface, BezierCurve2D &rclCurve, bezier2ddeque &rclCut, std::vector<unsigned int> &rvuiUSeg, std::vector<unsigned int> &rvuiVSeg)
01464 {
01465     const int                           ci_u_seg_cnt = m_vvdUParams[cuiSurface].size();
01466     const int                           ci_v_seg_cnt = m_vvdVParams[cuiSurface].size();
01467     int                                 i_u_seg;
01468     int                                 i_v_seg;
01469     unsigned int                        ui_curve;
01470     unsigned int                        ui_curve_cnt = 1;
01471     std::vector<BezierCurve2D>          vcl_curves;
01472     std::vector<double>                 vd_curvestart;
01473     std::vector<double>                 vd_curveend;
01474     std::vector<double>                 vd_int;
01475     unsigned int                        ui_int;
01476     BezierCurve2D                       cl_new_curve;
01477     std::multimap<double, unsigned int> mm_curve_sort;
01478     std::multimap<double, unsigned int>::iterator
01479                  itmm_curve_it;
01480     int          i_err;
01481 //    unsigned int ui_idx;
01482     bool         b_cut;
01483
01484     vcl_curves.push_back(rclCurve);
01485     vd_curvestart.push_back(0.0);
01486     vd_curveend.push_back(1.0);
01487     mm_curve_sort.insert(std::make_pair<const double, unsigned int>(0.0, 0u));
01488
01489     for(ui_curve = 0; ui_curve < ui_curve_cnt; ++ui_curve)
01490     {
01491         b_cut = false;
01492
01493         // cut in u-direction
01494         for(i_u_seg = 0; i_u_seg < ci_u_seg_cnt; ++i_u_seg)
01495         {
01496             vd_int.clear();
01497             vcl_curves[ui_curve].intersection(vd_int, m_vvdUParams[cuiSurface][i_u_seg], false);
01498
01499             for(ui_int = 0; ui_int < vd_int.size(); ++ui_int)
01500             {
01501                 if( (vd_int[ui_int] > 1e-7) &&
01502                     (1.0 - vd_int[ui_int] > 1e-7) )
01503                 {
01504                     vcl_curves[ui_curve].subDivision(vd_int[ui_int], cl_new_curve);
01505                     vcl_curves.push_back(cl_new_curve);
01506                     vd_curvestart.push_back( (vd_curvestart[ui_curve] + vd_curveend[ui_curve]) * 0.5);
01507                     vd_curveend.push_back(vd_curveend[ui_curve]);
01508                     vd_curveend[ui_curve] = vd_curvestart[ui_curve_cnt];
01509                     mm_curve_sort.insert(std::make_pair<const double, unsigned int>(vd_curvestart[ui_curve_cnt], ui_curve_cnt) );
01510                     ++ui_curve_cnt;
01511                     b_cut = true;
01512                     break;
01513                 }
01514             }
01515         }
01516
01517         if(!b_cut)
01518         {
01519             // cut in v-direction
01520             for(i_v_seg = 0; i_v_seg < ci_v_seg_cnt; ++i_v_seg)
01521             {
01522                 vd_int.clear();
01523                 vcl_curves[ui_curve].intersection(vd_int, m_vvdVParams[cuiSurface][i_v_seg], true);
01524
01525                 for(ui_int = 0; ui_int < vd_int.size(); ++ui_int)
01526                 {
01527                     if( (vd_int[ui_int] > 1e-7) &&
01528                         (1.0 - vd_int[ui_int] > 1e-7) )
01529                     {
01530                         vcl_curves[ui_curve].subDivision(vd_int[ui_int], cl_new_curve);
01531                         vcl_curves.push_back(cl_new_curve);
01532                         vd_curvestart.push_back( (vd_curvestart[ui_curve] + vd_curveend[ui_curve]) * 0.5);
01533                         vd_curveend.push_back(vd_curveend[ui_curve]);
01534                         vd_curveend[ui_curve] = vd_curvestart[ui_curve_cnt];
01535                         mm_curve_sort.insert(std::make_pair<const double, unsigned int>(vd_curvestart[ui_curve_cnt], ui_curve_cnt) );
01536                         ++ui_curve_cnt;
01537                         b_cut = true;
01538                         break;
01539                     }
01540                 }
01541             }
01542         }
01543         if(b_cut)
01544         {
01545             --ui_curve;
01546         }
01547     }
01548
01549     // sort and append new curves
01550     const unsigned int cui_offset = rclCut.size();
01551
01552     rclCut.resize(ui_curve_cnt + cui_offset);
01553     ui_curve = 0;
01554
01555     for(itmm_curve_it = mm_curve_sort.begin(); itmm_curve_it != mm_curve_sort.end(); ++itmm_curve_it)
01556     {
01557 //      std::cerr << itmm_curve_it->second << " ";
01558         rclCut[ui_curve + cui_offset] = vcl_curves[itmm_curve_it->second];
01559         ++ui_curve;
01560     }
01561
01562 //  std::cerr << std::endl;
01563
01564     // ok, now we know that all curve midpoints are INSIDE a cell (or the whole curve is on the edge)
01565     for(ui_curve = 0; ui_curve < ui_curve_cnt; ++ui_curve)
01566     {
01567         const Vec2d ccl_mid = rclCut[ui_curve + cui_offset].computewdeCasteljau(0.5, i_err);
01568
01569         // check if curve lies outside the surface
01570         if(ccl_mid[0] <= m_vvdUParams[cuiSurface][0])
01571         {
01572             std::vector<Vec3d> &rcl_cp = rclCut[ui_curve + cui_offset].getControlPointVector();
01573
01574             rcl_cp[1]    = rcl_cp[rcl_cp.size() - 1];
01575             rcl_cp[0][0] = m_vvdUParams[cuiSurface][0] * rcl_cp[0][2];
01576             rcl_cp[1][0] = m_vvdUParams[cuiSurface][0] * rcl_cp[1][2];
01577             rcl_cp.resize(2);
01578             rvuiUSeg.push_back(0);
01579         }
01580         else if(ccl_mid[0] >= m_vvdUParams[cuiSurface][ci_u_seg_cnt - 1])
01581         {
01582             std::vector<Vec3d> &rcl_cp = rclCut[ui_curve + cui_offset].getControlPointVector();
01583
01584             rcl_cp[1]    = rcl_cp[rcl_cp.size() - 1];
01585             rcl_cp[0][0] = m_vvdUParams[cuiSurface][ci_u_seg_cnt - 1] * rcl_cp[0][2];
01586             rcl_cp[1][0] = m_vvdUParams[cuiSurface][ci_u_seg_cnt - 1] * rcl_cp[1][2];
01587             rcl_cp.resize(2);
01588             rvuiUSeg.push_back(ci_u_seg_cnt - 2);
01589         }
01590         else
01591         {
01592             for(i_u_seg = 1; i_u_seg < ci_u_seg_cnt; ++i_u_seg)
01593             {
01594                 if(ccl_mid[0] <= m_vvdUParams[cuiSurface][i_u_seg])
01595                 {
01596                     rvuiUSeg.push_back(i_u_seg - 1);
01597                     break;
01598                 }
01599             }
01600         }
01601
01602         // check if curve lies outside the surface
01603         if(ccl_mid[1] <= m_vvdVParams[cuiSurface][0])
01604         {
01605             std::vector<Vec3d> &rcl_cp = rclCut[ui_curve + cui_offset].getControlPointVector();
01606
01607             rcl_cp[1]    = rcl_cp[rcl_cp.size() - 1];
01608             rcl_cp[0][1] = m_vvdVParams[cuiSurface][0] * rcl_cp[0][2];
01609             rcl_cp[1][1] = m_vvdVParams[cuiSurface][0] * rcl_cp[1][2];
01610             rcl_cp.resize(2);
01611             rvuiVSeg.push_back(0);
01612         }
01613         else if(ccl_mid[1] >= m_vvdVParams[cuiSurface][ci_v_seg_cnt - 1])
01614         {
01615             std::vector<Vec3d> &rcl_cp = rclCut[ui_curve + cui_offset].getControlPointVector();
01616
01617             rcl_cp[1]    = rcl_cp[rcl_cp.size() - 1];
01618             rcl_cp[0][1] = m_vvdVParams[cuiSurface][ci_v_seg_cnt - 1] * rcl_cp[0][2];
01619             rcl_cp[1][1] = m_vvdVParams[cuiSurface][ci_v_seg_cnt - 1] * rcl_cp[1][2];
01620             rcl_cp.resize(2);
01621             rvuiVSeg.push_back(ci_v_seg_cnt - 2);
01622         }
01623         else
01624         {
01625             for(i_v_seg = 1; i_v_seg < ci_v_seg_cnt; ++i_v_seg)
01626             {
01627                 if(ccl_mid[1] <= m_vvdVParams[cuiSurface][i_v_seg])
01628                 {
01629                     rvuiVSeg.push_back(i_v_seg - 1);
01630                     break;
01631                 }
01632             }
01633         }
01634     }
01635 }