void LapVectorField::compute( std::vector<std::vector<CvPoint>> curves_pix, CvSize imgsize, int res ){ // smooth input curves void getBernsteinCoefficient( std::vector<double> &bc, int n ) ; std::vector<std::vector<double2>> bezierCurves ; for( int cid=0; cid<curves_pix.size(); ++cid ){ std::vector<double2> curve ; for( int i=0; i<curves_pix[cid].size(); ++i) curve.push_back( double2( curves_pix[cid][i].x,curves_pix[cid][i].y ) ) ; int n = curve.size(); std::vector<double> bc ; getBernsteinCoefficient(bc, n ) ; // store the Bezier curve std::vector<double2> bezierCurve ; double step = 1.0 / curves_pix[cid].size(); for( double u=0; u<=1.0; u+=step){ double2 p ; for( int k = 0; k<n; ++k ){ p.x += bc[k] * pow(u, k) * pow( 1-u, n-1-k) * curve[k].x ; p.y += bc[k] * pow(u, k) * pow( 1-u, n-1-k) * curve[k].y ; } bezierCurve.push_back( p ) ; } bezierCurves.push_back( bezierCurve ); } #define _use_bezier 0 if( !_use_bezier ){ for( int cid=0; cid<curves_pix.size(); ++cid ){ std::vector<double2> curve ; for( int i=0; i<curves_pix[cid].size(); ++i) curve.push_back( double2( curves_pix[cid][i].x,curves_pix[cid][i].y ) ) ; bezierCurves[cid] = curve ; } } // store the config resolution = res ; LapVectorField::imgsize = imgsize ; // treat the image as square int majorSide = std::max( imgsize.height, imgsize.width ) ; if(imgsize.height> imgsize.width ){ for( int i=0; i<bezierCurves.size(); ++i ) for( int j=0; j<bezierCurves[i].size(); ++j ) bezierCurves[i][j].x += (imgsize.height - imgsize.width)/2 ; }else{ for( int i=0; i<bezierCurves.size(); ++i ) for( int j=0; j<bezierCurves[i].size(); ++j ) bezierCurves[i][j].y += (-imgsize.height + imgsize.width)/2 ; } std::vector<std::vector<double2>> curves_flt ; for( int i=0; i<bezierCurves.size(); ++i ){ std::vector<double2> cur ; for( int j=0; j<bezierCurves[i].size(); ++j ){ cur.push_back( bezierCurves[i][j] / majorSide ) ; } curves_flt.push_back(cur) ; } // calculate the vector field computeVectorField( vector_field, curves_flt, resolution ) ; }
double tele2d::energy_function( std::vector<double> X ){ std::vector<std::vector<double2> > curves_backup = curves ; // transform the curve(s) specified by curve_group[] for( int gid =0; gid<curves_group.size(); ++gid ){ std::vector<int> curves_id = curves_group[gid] ; // translation for( int i = 0; i<curves_id.size(); ++i ){ int cvid = curves_id[i] ; for (int j=0; j<curves[cvid].size(); ++j){ curves[cvid][j].x = curves_backup[cvid][j].x + X[gid*3] ; curves[cvid][j].y = curves_backup[cvid][j].y + X[gid*3+1] ; } } // rotation double2 rotation_center = curves[curves_id[0]].back() ; for( int i = 0; i<curves_id.size(); ++i ){ int cvid = curves_id[i] ; for( int j=0; j<curves[cvid].size(); ++j){ curves[cvid][j].x -= rotation_center.x ; curves[cvid][j].y -= rotation_center.y ; double2 temp = curves[cvid][j] ; curves[cvid][j].x = cos(X[gid*3+2]) * temp.x + sin( X[gid*3+2]) * temp.y ; curves[cvid][j].y = -sin(X[gid*3+2]) * temp.x + cos( X[gid*3+2]) * temp.y ; curves[cvid][j].x += rotation_center.x ; curves[cvid][j].y += rotation_center.y ; } } } // compute penalties for each bridging curve if( updateVectorFieldWhenComputingEnegergy ) computeVectorField() ; computeOsculatingCircle() ; interpolateBetweenPairedCurves() ; double penalty = 0; for( int fcid = 0; fcid<bridging_curves.size(); ++fcid) penalty += get_penalty( bridging_curves[fcid], bridging_curves_endpoints[fcid].first, bridging_curves_endpoints[fcid].second ) ; curves = curves_backup ; return penalty ; }