Developer Documentation
BSplineSurfaceT.cc
1 /*===========================================================================*\
2 * *
3 * OpenFlipper *
4  * Copyright (c) 2001-2015, RWTH-Aachen University *
5  * Department of Computer Graphics and Multimedia *
6  * All rights reserved. *
7  * www.openflipper.org *
8  * *
9  *---------------------------------------------------------------------------*
10  * This file is part of OpenFlipper. *
11  *---------------------------------------------------------------------------*
12  * *
13  * Redistribution and use in source and binary forms, with or without *
14  * modification, are permitted provided that the following conditions *
15  * are met: *
16  * *
17  * 1. Redistributions of source code must retain the above copyright notice, *
18  * this list of conditions and the following disclaimer. *
19  * *
20  * 2. Redistributions in binary form must reproduce the above copyright *
21  * notice, this list of conditions and the following disclaimer in the *
22  * documentation and/or other materials provided with the distribution. *
23  * *
24  * 3. Neither the name of the copyright holder nor the names of its *
25  * contributors may be used to endorse or promote products derived from *
26  * this software without specific prior written permission. *
27  * *
28  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
29  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
30  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
31  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
32  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
33  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
34  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
35  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
36  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
37  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
38  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
39 * *
40 \*===========================================================================*/
41 
42 /*===========================================================================*\
43 * *
44 * $Revision$ *
45 * $LastChangedBy$ *
46 * $Date$ *
47 * *
48 \*===========================================================================*/
49 
50 
51 //=============================================================================
52 //
53 // CLASS BSplineSurfaceT - IMPLEMENTATION
54 // Author: Ellen Dekkers <dekkers@cs.rwth-aachen.de>
55 //
56 //=============================================================================
57 
58 #define BSPLINESURFACE_BSPLINESURFACET_C
59 
60 //== INCLUDES =================================================================
61 
62 #include <OpenMesh/Core/Geometry/VectorT.hh>
63 
64 #include <iostream>
65 #include <fstream>
66 
67 #include "BSplineSurfaceT.hh"
68 
69 #include <cfloat>
70 #include <ACG/Geometry/Algorithms.hh>
71 #include <ACG/Math/BSplineBasis.hh>
72 
73 //== NAMESPACES ===============================================================
74 
75 namespace ACG {
76 
77 //== IMPLEMENTATION ==========================================================
78 
79 template <class PointT>
81 BSplineSurfaceT( unsigned int _degm, unsigned int _degn )
82 : dimm_(0),
83  dimn_(0),
84  ref_count_cpselections_(0),
85  ref_count_eselections_(0)
86 {
87  set_degree(_degm, _degn);
88 }
89 
90 //-----------------------------------------------------------------------------
91 
92 template <class PointT>
93 template <class PropT>
94 void
96 request_prop( unsigned int& _ref_count, PropT& _prop)
97 {
98  if(_ref_count == 0)
99  {
100  _ref_count = 1;
101 
102  // always use vertex size!!!
103  _prop.resize(n_control_points_m());
104  for (unsigned int i = 0; i < _prop.size(); ++i)
105  _prop[i].resize(n_control_points_n());
106  }
107  else ++_ref_count;
108 }
109 
110 //-----------------------------------------------------------------------------
111 
112 template <class PointT>
113 template <class PropT>
114 void
116 release_prop( unsigned int& _ref_count, PropT& _prop)
117 {
118  if( _ref_count <= 1)
119  {
120  _ref_count = 0;
121  _prop.clear();
122  }
123  else --_ref_count;
124 }
125 
126 //-----------------------------------------------------------------------------
127 
128 template <class PointT>
129 void
131 resize(unsigned int _m, unsigned int _n)
132 {
133  control_net_.resize(_m);
134 
135  for (unsigned int i = 0; i < control_net_.size(); ++i)
136  control_net_[i].resize(_n);
137 
138  dimm_ = _m;
139  dimn_ = _n;
140 
141  // resize cpselections
142  cpselections_.resize(_m);
143  for (unsigned int i = 0; i < cpselections_.size(); ++i)
144  cpselections_[i].resize(_n);
145 
146  // resize eselections
147  eselections_.resize(_m);
148  for (unsigned int i = 0; i < eselections_.size(); ++i)
149  eselections_[i].resize(_n);
150 }
151 
152 //-----------------------------------------------------------------------------
153 
154 template <class PointT>
155 void
158 {
159  control_net_.clear();
160 
161  // reset properties
162  cpselections_.clear();
163  eselections_.clear();
164 }
165 
166 //-----------------------------------------------------------------------------
167 
168 template <class PointT>
169 void
172 {
173  knotvector_m_.createKnots(degree_m_, dimm_);
174  knotvector_n_.createKnots(degree_n_, dimn_);
175 }
176 
177 //-----------------------------------------------------------------------------
178 
179 template <class PointT>
180 void
182 set_degree(unsigned int _degm, unsigned int _degn)
183 {
184  degree_m_ = _degm;
185  degree_n_ = _degn;
186 }
187 
188 //-----------------------------------------------------------------------------
189 
190 template <class PointT>
191 void
193 add_vector_m(const std::vector< Point> & _control_polygon)
194 {
195  insert_vector_m(_control_polygon, dimm_);
196 }
197 
198 //-----------------------------------------------------------------------------
199 
200 template <class PointT>
201 void
203 add_vector_n(const std::vector< Point> & _control_polygon)
204 {
205  insert_vector_n(_control_polygon, dimn_);
206 }
207 
208 //-----------------------------------------------------------------------------
209 
210 template <class PointT>
211 void
213 insert_vector_m(const std::vector< Point> & _control_polygon, unsigned int _m)
214 {
215  std::cout << "insert_vector_m of size " << _control_polygon.size() << " at m = " << _m << std::endl;
216 
217  assert(_m <= dimm_);
218  if (dimn_ == 0)
219  dimn_ =_control_polygon.size();
220 
221  assert(_control_polygon.size() == dimn_);
222 
223  resize(dimm_ + 1, dimn_);
224 
225  control_net_.insert(control_net_.begin() + _m, _control_polygon);
226  control_net_.pop_back(); // TODO check
227  std::cout << "control_net_: " << control_net_.size() << " x " << control_net_[control_net_.size()-1].size() << std::endl;
228 
229  // resize property net cpselection
230  std::vector<unsigned char> dummy(_control_polygon.size(), 0);
231  cpselections_.insert(cpselections_.begin() + _m, dummy);
232  cpselections_.pop_back();
233  std::cout << "cpselections_: " << cpselections_.size() << " x " << cpselections_[cpselections_.size()-1].size() << std::endl;
234 
235  // resize property net eselection
236  eselections_.insert(eselections_.begin() + _m, dummy);
237  eselections_.pop_back();
238  std::cout << "eselections_: " << eselections_.size() << " x " << eselections_[eselections_.size()-1].size() << std::endl;
239 }
240 
241 //-----------------------------------------------------------------------------
242 
243 template <class PointT>
244 void
246 insert_vector_n(const std::vector< Point> & _control_polygon, unsigned int _n)
247 {
248  assert(_n <= dimn_);
249  if (dimm_ == 0)
250  dimm_ = _control_polygon.size();
251 
252  assert(_control_polygon.size() == dimm_);
253 
254  resize(dimm_, dimn_+1);
255 
256  for (unsigned int i = 0; i < dimm_; ++i)
257  {
258  control_net_[i].insert(control_net_[i].begin() + _n, _control_polygon[i]);
259  control_net_[i].pop_back();
260  }
261 
262  // resize property net cpselection
263  for (unsigned int i = 0; i < dimm_; ++i)
264  {
265  cpselections_[i].insert(cpselections_[i].begin() + _n, 0);
266  cpselections_[i].pop_back();
267  }
268  // resize property net eselection
269  for (unsigned int i = 0; i < dimm_; ++i)
270  {
271  eselections_[i].insert(eselections_[i].begin() + _n, 0);
272  eselections_[i].pop_back();
273  }
274 }
275 
276 //-----------------------------------------------------------------------------
277 
278 template <class PointT>
279 void
281 delete_vector_m(unsigned int _m)
282 {
283  assert(_m < dimm_);
284 
286 
287  if(control_net_.begin() + _m < control_net_.end())
288  control_net_.erase(control_net_.begin() + _m);
289 
290  resize(dimm_-1, dimn_);
291 
292  // erase from properties
293  if(cpselections_.begin() + _m < cpselections_.end())
294  cpselections_.erase(cpselections_.begin() + _m);
295 
296  if(eselections_.begin() + _m < eselections_.end())
297  eselections_.erase(eselections_.begin() + _m);
298 
299  // Now rebuild knot vectors
300  createKnots();
301 }
302 
303 //-----------------------------------------------------------------------------
304 
305 template <class PointT>
306 void
308 delete_vector_n(unsigned int _n)
309 {
310  assert(_n < dimn_);
311 
313 
314  for (unsigned int i = 0; i < control_net_.size(); ++i) {
315  if(control_net_[i].begin() + _n < control_net_[i].end())
316  control_net_[i].erase(control_net_[i].begin() + _n);
317  }
318 
319  resize(dimm_, dimn_-1);
320 
321  // erase from properties
322  for (unsigned int i = 0; i < cpselections_.size(); ++i)
323  if(cpselections_[i].begin() + _n < cpselections_[i].end())
324  cpselections_[i].erase(cpselections_[i].begin() + _n);
325 
326  for (unsigned int i = 0; i < eselections_.size(); ++i)
327  if(eselections_[i].begin() + _n < eselections_[i].end())
328  eselections_[i].erase(eselections_[i].begin() + _n);
329 
330  // Now rebuild knot vectors
331  createKnots();
332 }
333 
334 //-----------------------------------------------------------------------------
335 
336 template <class PointT>
337 void
339 get_vector_m(std::vector< Point> & _control_polygon, unsigned int _m)
340 {
341  assert(_m < dimm_);
342  _control_polygon = control_net_[_m];
343 }
344 
345 //-----------------------------------------------------------------------------
346 
347 template <class PointT>
348 void
350 get_vector_n(std::vector< Point> & _control_polygon, unsigned int _n)
351 {
352  assert(_n < dimn_);
353  _control_polygon.resize(dimm_);
354 
355  for (unsigned int i = 0; i < dimm_; ++i)
356  _control_polygon[i] = control_net_[i][_n];
357 }
358 
359 //-----------------------------------------------------------------------------
360 
361 template <class PointT>
362 void
364 set_knots_m(std::vector< Scalar > _knots)
365 {
366  // set the knotvector
367  knotvector_m_.setKnotvector(_knots);
368 }
369 
370 //-----------------------------------------------------------------------------
371 
372 template <class PointT>
373 void
375 set_knots_n(std::vector< Scalar > _knots)
376 {
377  // set the knotvector
378  knotvector_n_.setKnotvector(_knots);
379 }
380 
381 //-----------------------------------------------------------------------------
382 
383 template <class PointT>
384 void
386 insert_knot_m(double _u)
387 {
388  // span and interval i,i+1
389  Vec2i span = spanm(_u);
390  Vec2i interval = interval_m(_u);
391 
392  // create new knot vector
393  Knotvector newknotvecu( get_knotvector_m() );
394  newknotvecu.insertKnot(interval[1], _u);
395 
396  // alphas
397  std::vector<double> alpha;
398  for( int i = span[0]; i < span[1]; ++i)
399  {
400  double a(knotvector_m_.getKnot(i+1));
401  double b(knotvector_m_.getKnot(i+degree_m_+1));
402  alpha.push_back((_u-a)/(b-a));
403  }
404  knotvector_m_ = newknotvecu;
405 
406  // new control net
407  ControlNet oldcpts(control_net_);
408 
410 
411  for( int i = 0; i < n_control_points_m(); ++i) // for all v rows
412  {
413  if( i <= span[0])
414  control_net_[i] = oldcpts[i];
415  else if( i <= span[1])
416  for( unsigned int j = 0; j < n_control_points_n(); ++j)
417  {
418  control_net_[i][j] = oldcpts[i-1][j]*(1.0-alpha[i-span[0]-1])+oldcpts[i][j]*alpha[i-span[0]-1];
419  }
420  else
421  control_net_[i] = oldcpts[i-1];
422  }
423 }
424 
425 //-----------------------------------------------------------------------------
426 
427 template <class PointT>
428 void
430 insert_knot_n(double _v)
431 {
432  // span and interval i,i+1
433  Vec2i span = spann(_v);
434  Vec2i interval = interval_n(_v);
435 
436  // create new knot vector
437  Knotvector newknotvecv( get_knotvector_n() );
438  newknotvecv.insertKnot(interval[1], _v);
439 
440  // alphas
441  std::vector<double> alpha;
442  for( int i = span[0]; i < span[1]; ++i)
443  {
444  double a(knotvector_n_.getKnot(i+1));
445  double b(knotvector_n_.getKnot(i+degree_n_+1));
446  alpha.push_back((_v-a)/(b-a));
447  }
448  knotvector_n_ = newknotvecv;
449 
450  // new control net
451  ControlNet oldcpts(control_net_);
452 
454 
455  for( int i = 0; i < n_control_points_n(); ++i) // for all v rows
456  {
457  if( i <= span[0])
458  for( unsigned int j = 0; j < n_control_points_m(); ++j)
459  control_net_[j][i] = oldcpts[j][i];
460  else if( i <= span[1])
461  for( unsigned int j = 0; j < n_control_points_m(); ++j)
462  {
463  control_net_[j][i] = oldcpts[j][i-1]*(1.0-alpha[i-span[0]-1])+oldcpts[j][i]*alpha[i-span[0]-1];
464  }
465  else
466  for( unsigned int j = 0; j < n_control_points_m(); ++j)
467  control_net_[j][i] = oldcpts[j][i-1];
468  }
469 }
470 
471 //-----------------------------------------------------------------------------
472 
473 template <class PointT>
474 PointT
476 surfacePoint(double _u, double _v)
477 {
478  double epsilon = 0.0000001;
479 
480  if (_u > upperu() && _u < upperu()+epsilon)
481  _u = upperu();
482 
483  if (_v > upperv() && _v < upperv()+epsilon)
484  _v = upperv();
485 
486  assert(_u >= loweru() && _u <= upperu());
487  assert(_v >= lowerv() && _v <= upperv());
488 
489  int pm = degree_m();
490  int pn = degree_n();
491 
492  Point point = Point(0.0, 0.0, 0.0);
493 
494  Vec2i span_m(spanm(_u));
495  Vec2i span_n(spann(_v));
496 
497 
498  std::vector<Scalar> basisFuns_m(pm+1);
499  std::vector<Scalar> basisFuns_n(pn+1);
500 
501  // evaluate basis functions
502  ACG::bsplineBasisFunctions(basisFuns_m, span_m, _u, knotvector_m_.getKnotvector());
503  ACG::bsplineBasisFunctions(basisFuns_n, span_n, _v, knotvector_n_.getKnotvector());
504 
505  // compute surface point
506 
507  for (int i = span_m[0]; i <= span_m[1]; ++i)
508  for (int j = span_n[0]; j <= span_n[1]; ++j)
509  point += control_net_[i][j] * basisFuns_m[i-span_m[0]] * basisFuns_n[j - span_n[0]];
510 
511  return point;
512 }
513 
514 //-----------------------------------------------------------------------------
515 
516 template <class PointT>
517 void
519 surfacePointNormal( Point& _pt, Point& _normal, double _u, double _v )
520 {
521  double epsilon = 0.0000001;
522 
523  if (_u > upperu() && _u < upperu()+epsilon)
524  _u = upperu();
525 
526  if (_v > upperv() && _v < upperv()+epsilon)
527  _v = upperv();
528 
529  assert(_u >= loweru() && _u <= upperu());
530  assert(_v >= lowerv() && _v <= upperv());
531 
532  int pm = degree_m();
533  int pn = degree_n();
534 
535  _pt = Point(0.0, 0.0, 0.0);
536 
537  Vec2i span_m(spanm(_u));
538  Vec2i span_n(spann(_v));
539 
540 
541  std::vector<Scalar> basisFuns_m(pm+1);
542  std::vector<Scalar> ders_m(pm+1);
543  std::vector<Scalar> basisFuns_n(pn+1);
544  std::vector<Scalar> ders_n(pn+1);
545 
546  // evaluate basis functions
547  ACG::bsplineBasisDerivatives(ders_m, span_m, _u, 1, knotvector_m_.getKnotvector(), &basisFuns_m);
548  ACG::bsplineBasisDerivatives(ders_n, span_n, _v, 1, knotvector_n_.getKnotvector(), &basisFuns_n);
549 
550 
551  // compute surface point and tangents
552 
553  Point dpdu = Point(0,0,0);
554  Point dpdv = Point(0,0,0);
555 
556  for (int i = 0; i <= pm; ++i)
557  {
558  for (int j = 0; j <= pn; ++j)
559  {
560  Point cp = control_net_[i + span_m[0]][j + span_n[0]];
561 
562  _pt += cp * (basisFuns_m[i] * basisFuns_n[j]);
563 
564  dpdu += cp * (ders_m[i] * basisFuns_n[j]);
565  dpdv += cp * (basisFuns_m[i] * ders_n[j]);
566  }
567  }
568 
569  _normal = (dpdu % dpdv).normalize();
570 }
571 
572 //-----------------------------------------------------------------------------
573 
574 template <class PointT>
575 PointT
577 surfacePoint_rec(double _u, double _v)
578 {
579  double epsilon = 0.0000001;
580 
581  if (_u > upperu() && _u < upperu()+epsilon)
582  _u = upperu();
583 
584  if (_v > upperv() && _v < upperv()+epsilon)
585  _v = upperv();
586 
587  assert(_u >= loweru() && _u <= upperu());
588  assert(_v >= lowerv() && _v <= upperv());
589 
590  int pm = degree_m();
591  int pn = degree_n();
592 
593  Point point = Point(0.0, 0.0, 0.0);
594 
595  Vec2i span_m(spanm(_u));
596  Vec2i span_n(spann(_v));
597 
598  for (int i = span_m[0]; i <= span_m[1]; ++i)
599  for (int j = span_n[0]; j <= span_n[1]; ++j)
600  point += control_net_[i][j] * basisFunction(knotvector_m_, i, pm, _u) * basisFunction(knotvector_n_, j, pn, _v);
601 
602  return point;
603 }
604 
605 //-----------------------------------------------------------------------------
606 
607 template <class PointT>
608 typename BSplineSurfaceT<PointT>::Scalar
610 basisFunction(Knotvector & _knotvector, int _i, int _n, double _t)
611 {
612  int m = _knotvector.size() - 1;
613 
614  // Mansfield Cox deBoor recursion
615  if ((_i==0 && _t== _knotvector(0)) || (_i==m-_n-1 && _t==_knotvector(m)))
616  return 1.0;
617 
618  if (_n == 0) {
619  if (_t >= _knotvector(_i) && _t < _knotvector(_i+1))
620  return 1.0;
621  else
622  return 0.0;
623  }
624 
625  double Nin1 = basisFunction(_knotvector, _i, _n-1, _t);
626  double Nin2 = basisFunction(_knotvector, _i+1, _n-1, _t);
627 
628  double fac1 = 0;
629 // if ((_knotvector(_i+_n) - _knotvector(_i)) > 0.000001 )
630  if ((_knotvector(_i+_n) - _knotvector(_i)) != 0)
631  fac1 = (_t - _knotvector(_i)) / (_knotvector(_i+_n) - _knotvector(_i)) ;
632 
633  double fac2 = 0;
634 // if ( (_knotvector(_i+1+_n) - _knotvector(_i+1)) > 0.000001 )
635  if ( (_knotvector(_i+1+_n) - _knotvector(_i+1)) != 0 )
636  fac2 = (_knotvector(_i+1+_n) - _t) / (_knotvector(_i+1+_n) - _knotvector(_i+1));
637 
638 // std::cout << "Nin1 = " << Nin1 << ", Nin2 = " << Nin2 << ", fac1 = " << fac1 << ", fac2 = " << fac2 << std::endl;
639 
640  return (fac1*Nin1 + fac2*Nin2);
641 }
642 
643 //-----------------------------------------------------------------------------
644 
645 template <class PointT>
646 PointT
648 derivativeSurfacePoint(double _u, double _v, int _derm, int _dern)
649 {
650  assert(_u >= loweru() && _u <= upperu());
651  assert(_v >= lowerv() && _v <= upperv());
652 
653  int pn = degree_n();
654  int pm = degree_m();
655 
656  Point point(0,0,0);
657 
658  Vec2i span_m(spanm(_u));
659  Vec2i span_n(spann(_v));
660 
661  std::vector<Scalar> ders_m(pm+1);
662  std::vector<Scalar> ders_n(pn+1);
663 
664  ACG::bsplineBasisDerivatives<Scalar>(ders_m, span_m, _u, _derm, knotvector_m_.getKnotvector(), 0);
665  ACG::bsplineBasisDerivatives<Scalar>(ders_n, span_n, _v, _dern, knotvector_n_.getKnotvector(), 0);
666 
667  for (int i = span_m[0]; i <= span_m[1]; i++)
668  for (int j = span_n[0]; j <= span_n[1]; j++)
669  point += control_net_[i][j] * ders_m[i - span_m[0]] * ders_n[j - span_n[0]];
670 
671 
672  return point;
673 }
674 
675 //-----------------------------------------------------------------------------
676 
677 template <class PointT>
678 PointT
680 normalSurfacePoint(double _u, double _v)
681 {
682  assert(_u >= loweru() && _u <= upperu());
683  assert(_v >= lowerv() && _v <= upperv());
684 
685  Point derivu = derivativeSurfacePoint(_u,_v,1,0);
686  Point derivv = derivativeSurfacePoint(_u,_v,0,1);
687 
688  Point normal( (derivu%derivv).normalize());
689 
690  return normal;
691 }
692 
693 //-----------------------------------------------------------------------------
694 
695 template <class PointT>
696 typename BSplineSurfaceT<PointT>::Scalar
698 derivativeBasisFunction(Knotvector & _knotvector, int _i, int _n, double _t, int _der)
699 {
700  assert(_n >= 0);
701  assert(_i >= 0);
702 
703  if (_der == 0)
704  return basisFunction(_knotvector, _i, _n, _t);
705 
706  Scalar Nin1 = derivativeBasisFunction(_knotvector, _i, _n-1, _t, _der-1);
707  Scalar Nin2 = derivativeBasisFunction(_knotvector, _i+1, _n-1, _t, _der-1);
708 
709  Scalar fac1 = 0;
710  if ( fabs(_knotvector(_i+_n)-_knotvector(_i)) > 1e-6 )
711  fac1 = Scalar(_n) / (_knotvector(_i+_n)-_knotvector(_i));
712 
713  Scalar fac2 = 0;
714  if ( fabs(_knotvector(_i+_n+1)-_knotvector(_i+1)) > 1e-6 )
715  fac2 = Scalar(_n) / (_knotvector(_i+_n+1)-_knotvector(_i+1));
716 
717  return (fac1*Nin1 - fac2*Nin2);
718 }
719 
720 //-----------------------------------------------------------------------------
721 
722 template <class PointT>
723 typename BSplineSurfaceT<PointT>::Scalar
726 {
727  return knotvector_m_(degree_m());
728 }
729 
730 //-----------------------------------------------------------------------------
731 
732 template <class PointT>
733 typename BSplineSurfaceT<PointT>::Scalar
736  return knotvector_m_(knotvector_m_.size() - 1 - degree_m());
737 }
738 
739 //-----------------------------------------------------------------------------
740 
741 template <class PointT>
742 typename BSplineSurfaceT<PointT>::Scalar
745 {
746  return knotvector_n_(degree_n());
747 }
748 
749 //-----------------------------------------------------------------------------
750 
751 template <class PointT>
752 typename BSplineSurfaceT<PointT>::Scalar
755  return knotvector_n_(knotvector_n_.size() - 1 - degree_n());
756 }
757 
758 //-----------------------------------------------------------------------------
759 
760 template <class PointT>
763 spanm(double _t)
764 {
765  return ACG::bsplineSpan(_t, degree_m(), knotvector_m_.getKnotvector());
766 }
767 
768 //-----------------------------------------------------------------------------
769 
770 template <class PointT>
773 spann(double _t)
774 {
775  return ACG::bsplineSpan(_t, degree_n(), knotvector_n_.getKnotvector());
776 }
777 
778 //-----------------------------------------------------------------------------
779 
780 template <class PointT>
783 interval_m(double _t)
784 {
785  unsigned int i(0);
786 
787  if (_t >= upperu())
788  i = dimm_-1;
789  else
790  {
791  while (_t >= knotvector_m_(i)) i++;
792  while (_t < knotvector_m_(i)) i--;
793  }
794 
795  return Vec2i(i, i+1);
796 }
797 
798 //-----------------------------------------------------------------------------
799 
800 template <class PointT>
803 interval_n(double _t)
804 {
805  unsigned int i(0);
806 
807  if (_t >= upperv())
808  i = dimn_-1;
809  else
810  {
811  while (_t >= knotvector_n_(i)) i++;
812  while (_t < knotvector_n_(i)) i--;
813  }
814 
815  return Vec2i(i, i+1);
816 }
817 
818 //-----------------------------------------------------------------------------
819 
820 //=============================================================================
821 } // namespace ACG
822 //=============================================================================
unsigned int degree_m_
Spline degree in m direction.
void createKnots()
Creates interpolating knotvectors 0...0, 1, 2, ..., n...n.
Knotvector knotvector_n_
Knotvector in n direction.
void set_knots_n(std::vector< Scalar > _knots)
Set the knotvector of the bspline surface in n direction.
PropertyNet cpselections_
list of control point properties
int degree_n() const
Returns the spline degree in n direction.
Scalar basisFunction(Knotvector &_knotvector, int _i, int _n, double _t)
A Spline Basis Function.
Scalar loweru()
Returns the lower u parameter.
ACG::Vec2i spanm(double _t)
Returns the basis functions which are unequal to zero at parameter u.
Point surfacePoint(double _u, double _v)
Evaluates a spline surface at parameters _u and _v.
Scalar upperu()
Returns the upper u parameter.
unsigned int dimm_
number of control points in m direction
BSplineSurfaceT(unsigned int _degm=3, unsigned int _degn=3)
Constructor.
void get_vector_m(std::vector< Point > &_control_polygon, unsigned int _m)
Returns an n control point vector.
Knotvector get_knotvector_n()
Get the knotvector in n direction.
ACG::Vec2i interval_n(double _t)
Returns the index of the knots v and v+1 such that t in [v, v+1)
Knotvector knotvector_m_
Knotvector in m direction.
unsigned int n_control_points_m() const
Returns the number of controlpoints in m direction.
void resize(unsigned int _m, unsigned int _n)
Resizes the spline struct.
void bsplineBasisFunctions(std::vector< Scalar > &_N, const Vec2i &_span, Scalar _t, const std::vector< Scalar > &_knots)
Evaluate basis functions in a span.
void add_vector_m(const std::vector< Point > &_control_polygon)
Adds a control point n-vector.
void insert_knot_n(double _t)
Insert a knot i in n direction without changing the surface.
void delete_vector_m(unsigned int _m)
Deletes an n control point vector.
void reset_control_net()
Clears the control net.
Knotvector get_knotvector_m()
Get the knotvector in m direction.
ACG::Vec2i interval_m(double _t)
Returns the index of the knots u and u+1 such that t in [u, u+1)
PropertyNet eselections_
list of edge properties
void delete_vector_n(unsigned int _n)
Deletes an m control point vector.
Scalar derivativeBasisFunction(Knotvector &_knotvector, int _i, int _n, double _t, int _der)
Derivative of a Spline Basis Function.
VectorT< signed int, 2 > Vec2i
Definition: VectorT.hh:104
void insert_vector_m(const std::vector< Point > &_control_polygon, unsigned int _m)
Inserts an n control point vector.
Vec2i bsplineSpan(Scalar _t, int _degree, const std::vector< Scalar > &_knots)
Find the span of a parameter value.
Definition: BSplineBasis.cc:77
void surfacePointNormal(Point &_pt, Point &_normal, double _u, double _v)
Evaluates a spline surface at parameters _u and _v.
Namespace providing different geometric functions concerning angles.
Definition: DBSCANT.cc:51
void insert_vector_n(const std::vector< Point > &_control_polygon, unsigned int _n)
Inserts an m control point vector.
void get_vector_n(std::vector< Point > &_control_polygon, unsigned int _n)
Returns an m ctrPointVector.
void bsplineBasisDerivatives(std::vector< Scalar > &_ders, const Vec2i &_span, Scalar _t, int _der, const std::vector< Scalar > &_knots, std::vector< Scalar > *_functionVals)
Compute derivatives of basis functions in a span.
int degree_m() const
Returns the spline degree in m direction.
void insert_knot_m(double _t)
Insert a knot i in m direction without changing the surface.
unsigned int n_control_points_n() const
Returns the number of controlpoints in n direction.
ACG::Vec2i spann(double _t)
Returns the basis functions which are unequal to zero at parameter v.
Scalar lowerv()
Returns the lower v parameter.
Point normalSurfacePoint(double _u, double _v)
Returns the normal of a spline surface.
Scalar upperv()
Returns the upper v parameter.
void set_knots_m(std::vector< Scalar > _knots)
Set the knotvector of the bspline surface in m direction.
unsigned int dimn_
number of control points in n direction
unsigned int degree_n_
Spline degree in n direction.
void set_degree(unsigned int _degm, unsigned int _degn)
Sets the degree of the spline surface.
Point surfacePoint_rec(double _u, double _v)
Evaluates a spline surface at parameters _u and _v.
Point derivativeSurfacePoint(double _u, double _v, int _derm, int _dern)
Returns the _derm&#39;th derivative of a spline surface.
void add_vector_n(const std::vector< Point > &_control_polygon)
Adds a control point m-vector.