00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #include "voreen/modules/base/processors/image/labelingmath.h"
00029
00030
00031 #include "jama/include/jama_qr.h"
00032
00033 using namespace labeling;
00034 using namespace tgt;
00035 using namespace std;
00036
00037 inline float faculty(int a) {
00038 if (a > 1)
00039 return a*faculty(a-1);
00040 else
00041 return 1.f;
00042 }
00043
00044
00045
00046
00047
00048
00049
00050
00051 float bernstein(float u, int comp, int deg) {
00052 float factor = faculty(deg) / ( faculty(comp)*faculty(deg - comp) );
00053 return factor*pow(u, static_cast<float>(comp))*pow(1-u, static_cast<float>(deg-comp));
00054 }
00055
00056
00057
00058
00059
00060 float bernsteinDerivative(float u, int comp, int deg) {
00061 float factor = faculty(deg) / ( faculty(comp)*faculty(deg - comp) );
00062 if (comp == 0)
00063 return -factor*deg*pow(1-u, static_cast<float>(deg-1));
00064 else if (deg == comp)
00065 return factor*comp*pow(u,static_cast<float>(comp-1));
00066 else
00067 return factor*( comp*pow(u,static_cast<float>(comp-1))*pow(1-u, static_cast<float>(deg-comp))
00068 - pow(u, static_cast<float>(comp))*(deg-comp)*pow(1-u, static_cast<float>(deg-comp-1)) );
00069 }
00070
00071
00072
00073
00074
00075 float evalPolynomial(float t, void* params) {
00076 int degree = (static_cast<Polynomial*>(params))->degree;
00077 float* coeff = (static_cast<Polynomial*>(params))->coeff;
00078 float result = 0;
00079 for (int i=0; i<=degree; i++)
00080 result += coeff[i]*pow(t,i);
00081 return result;
00082 }
00083
00084 float evalPolynomialDerivative(float t, void* params) {
00085 int degree = (static_cast<Polynomial*>(params))->degree;
00086 float* coeff = (static_cast<Polynomial*>(params))->coeff;
00087 float result = 0;
00088 for (int i=0; i<degree; i++)
00089 result += coeff[i+1]*(i+1)*pow(t,i);
00090 return result;
00091 }
00092
00093 float evalPolynomialCurve2DTangentMagnitude(float t, void* params) {
00094 Polynomial xpoly = (static_cast<Polynomial*>(params))[0];
00095 Polynomial ypoly = (static_cast<Polynomial*>(params))[1];
00096 return sqrt( pow(evalPolynomialDerivative(t, &xpoly), 2) +
00097 pow(evalPolynomialDerivative(t, &ypoly), 2) );
00098 }
00099
00100 float evalPolynomialCurve3DTangentMagnitude(float t, void* params) {
00101 Polynomial xpoly = (static_cast<Polynomial*>(params))[0];
00102 Polynomial ypoly = (static_cast<Polynomial*>(params))[1];
00103 Polynomial zpoly = (static_cast<Polynomial*>(params))[2];
00104 return sqrt( pow(evalPolynomialDerivative(t, &xpoly), 2) +
00105 pow(evalPolynomialDerivative(t, &ypoly), 2) +
00106 pow(evalPolynomialDerivative(t, &zpoly), 2) );
00107 }
00108
00109
00110
00111 Curve3D::Curve3D() {
00112 }
00113
00114 bool Curve3D::setCtrlPoints(vector<tgt::vec3> &ctrlPoints, float curveLength) {
00115 ctrlPoints_ = ctrlPoints;
00116 return calcFunction(curveLength);
00117 }
00118
00119
00120
00121 Curve2D::Curve2D() {
00122 }
00123
00124 bool Curve2D::setCtrlPoints(vector<tgt::vec2> &ctrlPoints, float curveLength) {
00125 ctrlPoints_ = ctrlPoints;
00126 return calcFunction(curveLength);
00127 }
00128
00129
00130
00131 Curve3DPolynomial::Curve3DPolynomial(int degree) {
00132 degree_ = degree;
00133 numCoeff_ = degree+1;
00134 xfunc_.degree = degree;
00135 xfunc_.coeff = 0;
00136 yfunc_.degree = degree;
00137 yfunc_.coeff = 0;
00138 zfunc_.degree = degree;
00139 zfunc_.coeff = 0;
00140 }
00141
00142
00143 bool Curve3DPolynomial::calcFunction(float curveLength) {
00144 if (ctrlPoints_.size() < (size_t)numCoeff_)
00145 return false;
00146
00147 if (!xfunc_.coeff) {
00148 xfunc_.coeff = new float[numCoeff_];
00149 yfunc_.coeff = new float[numCoeff_];
00150 zfunc_.coeff = new float[numCoeff_];
00151 }
00152
00153
00154
00155
00156
00157
00158
00159
00160 TNT::Array1D<float> y(ctrlPoints_.size());
00161 TNT::Array2D<float> X(ctrlPoints_.size(), numCoeff_);
00162 TNT::Array1D<float> c(numCoeff_);
00163
00164
00165 for (int i=0; i<static_cast<int>(ctrlPoints_.size()); ++i) {
00166 for (int j=0; j<numCoeff_; ++j) {
00167 X[i][j] = pow(static_cast<float>(i), static_cast<float>(j));
00168 }
00169 }
00170 JAMA::QR<float> QR_Matrix(X);
00171
00172
00173 for (int i=0; i<static_cast<int>(ctrlPoints_.size()); ++i)
00174 y[i] = ctrlPoints_[i].x;
00175
00176 c = QR_Matrix.solve(y);
00177 for (int i=0; i<numCoeff_; ++i)
00178 xfunc_.coeff[i] = c[i];
00179
00180
00181 for (int i=0; i<static_cast<int>(ctrlPoints_.size()); ++i)
00182 y[i] = ctrlPoints_[i].y;
00183
00184 c = QR_Matrix.solve(y);
00185 for (int i=0; i<numCoeff_; ++i)
00186 yfunc_.coeff[i] = c[i];
00187
00188
00189 for (int i=0; i<static_cast<int>(ctrlPoints_.size()); ++i)
00190 y[i] = ctrlPoints_[i].z;
00191 c = QR_Matrix.solve(y);
00192 for (int i=0; i<numCoeff_; ++i)
00193 zfunc_.coeff[i] = c[i];
00194
00195
00196 paramScale_ = static_cast<float>(ctrlPoints_.size()-1);
00197 paramShift_ = 0.f;
00198 if (curveLength > 0.f) {
00199 float length = getSegmentLength(0.f, 1.f);
00200 paramScale_ = (curveLength / length) * (ctrlPoints_.size()-1);
00201 paramShift_ = -(paramScale_-(ctrlPoints_.size()-1)) / 2.f;
00202 }
00203
00204 return true;
00205 }
00206
00207 tgt::vec3 Curve3DPolynomial::getCurvePoint(float t) {
00208 float p = t*paramScale_+paramShift_;
00209 tgt::vec3 result;
00210 result.x = evalPolynomial(p, &xfunc_);
00211 result.y = evalPolynomial(p, &yfunc_);
00212 result.z = evalPolynomial(p, &zfunc_);
00213 return result;
00214 }
00215
00216 tgt::vec3 Curve3DPolynomial::getTangent(float t) {
00217 float p = t*paramScale_+paramShift_;
00218 tgt::vec3 result = vec3(0.f);
00219 result.x = evalPolynomialDerivative(p, &xfunc_);
00220 result.y = evalPolynomialDerivative(p, &yfunc_);
00221 result.z = evalPolynomialDerivative(p, &zfunc_);
00222 return result*paramScale_;
00223 }
00224
00225 float Curve3DPolynomial::getTangentMagnitude(float t) {
00226 return length(getTangent(t));
00227 }
00228
00229
00230 float Curve3DPolynomial::getSegmentLength(float t1, float t2) {
00231 float avgTangentMagnitude = ( getTangentMagnitude(t1) +
00232 getTangentMagnitude((t1+t2)/2.f) +
00233 getTangentMagnitude(t2) ) / 3.f;
00234 return fabs(t2-t1)*avgTangentMagnitude;
00235 }
00236
00237 tgt::vec3 Curve3DPolynomial::getNextPoint(float &curParam, float offset) {
00238 float pixelsPerParam = getTangentMagnitude(curParam);
00239 curParam += offset / pixelsPerParam;
00240 return getCurvePoint(curParam);
00241 }
00242
00243 void Curve3DPolynomial::shift(vec3 shiftVector) {
00244 xfunc_.coeff[0] += shiftVector.x;
00245 yfunc_.coeff[0] += shiftVector.y;
00246 zfunc_.coeff[0] += shiftVector.z;
00247
00248 for (size_t i=0; i<ctrlPoints_.size(); ++i)
00249 ctrlPoints_[i] = ctrlPoints_[i] + shiftVector;
00250 }
00251
00252
00253
00254
00255 Curve2DPolynomial::Curve2DPolynomial(int degree) {
00256 degree_ = degree;
00257 numCoeff_ = degree+1;
00258 xfunc_.degree = degree;
00259 xfunc_.coeff = 0;
00260 yfunc_.degree = degree;
00261 yfunc_.coeff = 0;
00262 }
00263
00264 bool Curve2DPolynomial::calcFunction(float curveLength) {
00265 if (ctrlPoints_.size() < (size_t)numCoeff_)
00266 return false;
00267
00268 if (!xfunc_.coeff){
00269 xfunc_.coeff = new float[numCoeff_];
00270 yfunc_.coeff = new float[numCoeff_];
00271 }
00272
00273
00274
00275
00276
00277
00278
00279
00280 TNT::Array1D<float> y(ctrlPoints_.size());
00281 TNT::Array2D<float> X(ctrlPoints_.size(), numCoeff_);
00282 TNT::Array1D<float> c(numCoeff_);
00283
00284
00285 for (int i=0; i<static_cast<int>(ctrlPoints_.size()); i++)
00286 for (int j=0; j<numCoeff_; j++)
00287 X[i][j] = pow((float)i, (float)j);
00288
00289 JAMA::QR<float> QR_Matrix(X);
00290
00291
00292 for (int i=0; i<static_cast<int>(ctrlPoints_.size()); ++i)
00293 y[i] = ctrlPoints_[i].x;
00294 c = QR_Matrix.solve(y);
00295 for (int i=0; i<numCoeff_; ++i)
00296 xfunc_.coeff[i] = c[i];
00297
00298
00299 for (int i=0; i<static_cast<int>(ctrlPoints_.size()); ++i)
00300 y[i] = ctrlPoints_[i].y;
00301 c = QR_Matrix.solve(y);
00302 for (int i=0; i<numCoeff_; ++i)
00303 yfunc_.coeff[i] = c[i];
00304
00305
00306 paramScale_ = static_cast<float>(ctrlPoints_.size()-1);
00307 paramShift_ = 0.f;
00308 if (curveLength > 0.f) {
00309 float length = getSegmentLength(0.f, 1.f);
00310 paramScale_ = (curveLength / length) * (ctrlPoints_.size()-1);
00311 paramShift_ = -(paramScale_-(ctrlPoints_.size()-1)) / 2.f;
00312 }
00313 return true;
00314 }
00315
00316 tgt::vec2 Curve2DPolynomial::getCurvePoint(float t) {
00317 float p = t*paramScale_+paramShift_;
00318 tgt::vec2 result;
00319 result.x = evalPolynomial(p, &xfunc_);
00320 result.y = evalPolynomial(p, &yfunc_);
00321 return result;
00322 }
00323
00324 tgt::vec2 Curve2DPolynomial::getTangent(float t) {
00325 float p = t*paramScale_+paramShift_;
00326 tgt::vec2 result = vec2(0.f);
00327 result.x = evalPolynomialDerivative(p, &xfunc_);
00328 result.y = evalPolynomialDerivative(p, &yfunc_);
00329 return result*paramScale_;
00330 }
00331
00332 float Curve2DPolynomial::getTangentMagnitude(float t) {
00333 return length(getTangent(t));
00334 }
00335
00336
00337 float Curve2DPolynomial::getSegmentLength(float t1, float t2) {
00338 float avgTangentMagnitude = ( getTangentMagnitude(t1) +
00339 getTangentMagnitude((t1+t2)/2.f) +
00340 getTangentMagnitude(t2) ) / 3.f;
00341 return fabs(t2-t1)*avgTangentMagnitude;
00342 }
00343
00344 tgt::vec2 Curve2DPolynomial::getNextPoint(float &curParam, float offset) {
00345 float pixelsPerParam = getTangentMagnitude(curParam);
00346 curParam += offset / pixelsPerParam;
00347 return getCurvePoint(curParam);
00348 }
00349
00350 void Curve2DPolynomial::shift(vec2 shiftVector) {
00351 xfunc_.coeff[0] += shiftVector.x;
00352 yfunc_.coeff[0] += shiftVector.y;
00353
00354 for (size_t i=0; i<ctrlPoints_.size(); i++)
00355 ctrlPoints_[i] = ctrlPoints_[i] + shiftVector;
00356 }
00357
00358
00359
00360 BezierPatch::BezierPatch(bool useDisplayList) {
00361 degreeS_ = -1;
00362 degreeT_ = -1;
00363 ctrlPoints_ = NULL;
00364 displayList_ = 0;
00365 useDisplayList_ = useDisplayList;
00366 }
00367
00368 BezierPatch::~BezierPatch() {
00369 if (displayList_ > 0) {
00370 glDeleteLists(displayList_, 1);
00371 displayList_ = 0;
00372 }
00373 }
00374
00375 int BezierPatch::getDegreeS(){
00376 return degreeS_;
00377 }
00378
00379 int BezierPatch::getDegreeT(){
00380 return degreeT_;
00381 }
00382
00383 void BezierPatch::setCtrlPoints(vec3* ctrlPoints, int degreeS, int degreeT) {
00384 delete ctrlPoints_;
00385
00386 ctrlPoints_ = ctrlPoints;
00387 degreeS_ = degreeS;
00388 degreeT_ = degreeT;
00389 if (displayList_ > 0) {
00390 glDeleteLists(displayList_, 1);
00391 displayList_ = 0;
00392 }
00393 }
00394
00395 vec3* BezierPatch::getCtrlPoints(int °reeS, int °reeT) {
00396 degreeS = degreeS_;
00397 degreeT = degreeT_;
00398 return ctrlPoints_;
00399 }
00400
00401 vec3 BezierPatch::getPoint(float s, float t) {
00402 vec3 result = vec3(0.f);
00403 for (int i=0; i<=degreeS_; ++i) {
00404 for (int j=0; j<=degreeT_; ++j) {
00405 result += bernstein(s,i,degreeS_)*bernstein(t,j,degreeT_)*
00406 ctrlPoints_[j*(degreeS_+1)+i];
00407 }
00408 }
00409 return result;
00410 }
00411
00412 vec3 BezierPatch::getTangentS(float s, float t) {
00413 vec3 result = vec3(0.f);
00414 for (int i=0; i<=degreeS_; ++i){
00415 for (int j=0; j<=degreeT_; ++j) {
00416 result += bernsteinDerivative(s,i,degreeS_)*bernstein(t,j,degreeT_)*
00417 ctrlPoints_[j*(degreeS_+1)+i];
00418 }
00419 }
00420 return result;
00421 }
00422
00423 vec3 BezierPatch::getTangentT(float s, float t) {
00424 vec3 result = vec3(0.f);
00425 for (int i=0; i<=degreeS_; ++i) {
00426 for (int j=0; j<=degreeT_; ++j) {
00427 result += bernstein(s,i,degreeS_)*bernsteinDerivative(t,j,degreeT_)*
00428 ctrlPoints_[j*(degreeS_+1)+i];
00429 }
00430 }
00431 return result;
00432 }
00433
00434 vec3 BezierPatch::getNormal(float s, float t){
00435 vec3 tangentS = getTangentS(s,t);
00436 vec3 tangentT = getTangentT(s,t);
00437 vec3 result = normalize(cross(tangentS,tangentT));
00438
00439 return result;
00440 }
00441
00442 void BezierPatch::render(int s_steps, int t_steps, bool genTexCoords, GLuint texUnit) {
00443 bool creatingDisplayList = false;
00444 if (displayList_ == 0 && useDisplayList_) {
00445 displayList_ = glGenLists(1);
00446 glNewList(displayList_, GL_COMPILE);
00447 creatingDisplayList = true;
00448 }
00449
00450 if (displayList_ == 0 || creatingDisplayList) {
00451 float s_offset = 1/(s_steps+1.f);
00452 float t_offset = 1/(t_steps+1.f);
00453 for (float s=0.f; s<0.99; s += s_offset ) {
00454 vec3 last0 = getPoint(s,0.f);
00455 vec3 last1 = getPoint(s+s_offset,0.f);
00456 glBegin(GL_QUAD_STRIP);
00457 if (genTexCoords)
00458 glMultiTexCoord2f( texUnit, s, 0.f );
00459 glVertex3fv(last0.elem);
00460 if (genTexCoords)
00461 glMultiTexCoord2f( texUnit, s+s_offset, 0.f );
00462 glVertex3fv(last1.elem);
00463 for (float t=t_offset; t<1.01f; t += t_offset) {
00464 vec3 cur0 = getPoint(s, t);
00465 vec3 cur1 = getPoint(s+s_offset, t);
00466 if (genTexCoords)
00467 glMultiTexCoord2f(texUnit, s,t);
00468 glVertex3fv(cur0.elem);
00469 if (genTexCoords)
00470 glMultiTexCoord2f(texUnit, s+s_offset,t);
00471 glVertex3fv(cur1.elem);
00472
00473 last0 = cur0;
00474 last1 = cur1;
00475 }
00476 glEnd();
00477 }
00478 }
00479
00480 if (creatingDisplayList)
00481 glEndList();
00482
00483 if (displayList_ != 0)
00484 glCallList(displayList_);
00485
00486
00487
00488
00489
00490
00491
00492
00493
00494
00495
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509
00510
00511
00512
00513
00514
00515 }
00516
00517