Developer Documentation
BSplineSurfaceT_impl.hh
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 
45 //=============================================================================
46 //
47 // CLASS BSplineSurfaceT - IMPLEMENTATION
48 // Author: Ellen Dekkers <dekkers@cs.rwth-aachen.de>
49 //
50 //=============================================================================
51 
52 #define BSPLINESURFACE_BSPLINESURFACET_C
53 
54 //== INCLUDES =================================================================
55 
56 #include <OpenMesh/Core/Geometry/VectorT.hh>
57 
58 #include <iostream>
59 #include <fstream>
60 
61 #include "BSplineSurfaceT.hh"
62 
63 #include <cfloat>
64 #include <ACG/Geometry/Algorithms.hh>
65 #include <ACG/Math/BSplineBasis.hh>
66 
67 //== NAMESPACES ===============================================================
68 
69 namespace ACG {
70 
71 //== IMPLEMENTATION ==========================================================
72 
73 template <class PointT>
75 BSplineSurfaceT( unsigned int _degm, unsigned int _degn )
76 : dimm_(0),
77  dimn_(0),
78  ref_count_cpselections_(0),
79  ref_count_eselections_(0)
80 {
81  set_degree(_degm, _degn);
82 }
83 
84 //-----------------------------------------------------------------------------
85 
86 template <class PointT>
87 template <class PropT>
88 void
90 request_prop( unsigned int& _ref_count, PropT& _prop)
91 {
92  if(_ref_count == 0)
93  {
94  _ref_count = 1;
95 
96  // always use vertex size!!!
97  _prop.resize(n_control_points_m());
98  for (unsigned int i = 0; i < _prop.size(); ++i)
99  _prop[i].resize(n_control_points_n());
100  }
101  else ++_ref_count;
102 }
103 
104 //-----------------------------------------------------------------------------
105 
106 template <class PointT>
107 template <class PropT>
108 void
110 release_prop( unsigned int& _ref_count, PropT& _prop)
111 {
112  if( _ref_count <= 1)
113  {
114  _ref_count = 0;
115  _prop.clear();
116  }
117  else --_ref_count;
118 }
119 
120 //-----------------------------------------------------------------------------
121 
122 template <class PointT>
123 void
125 resize(unsigned int _m, unsigned int _n)
126 {
127  control_net_.resize(_m);
128 
129  for (unsigned int i = 0; i < control_net_.size(); ++i)
130  control_net_[i].resize(_n);
131 
132  dimm_ = _m;
133  dimn_ = _n;
134 
135  // resize cpselections
136  cpselections_.resize(_m);
137  for (unsigned int i = 0; i < cpselections_.size(); ++i)
138  cpselections_[i].resize(_n);
139 
140  // resize eselections
141  eselections_.resize(_m);
142  for (unsigned int i = 0; i < eselections_.size(); ++i)
143  eselections_[i].resize(_n);
144 }
145 
146 //-----------------------------------------------------------------------------
147 
148 template <class PointT>
149 void
152 {
153  control_net_.clear();
154 
155  // reset properties
156  cpselections_.clear();
157  eselections_.clear();
158 }
159 
160 //-----------------------------------------------------------------------------
161 
162 template <class PointT>
163 void
166 {
167  knotvector_m_.createKnots(degree_m_, dimm_);
168  knotvector_n_.createKnots(degree_n_, dimn_);
169 }
170 
171 //-----------------------------------------------------------------------------
172 
173 template <class PointT>
174 void
176 set_degree(unsigned int _degm, unsigned int _degn)
177 {
178  degree_m_ = _degm;
179  degree_n_ = _degn;
180 }
181 
182 //-----------------------------------------------------------------------------
183 
184 template <class PointT>
185 void
187 add_vector_m(const std::vector< Point> & _control_polygon)
188 {
189  insert_vector_m(_control_polygon, dimm_);
190 }
191 
192 //-----------------------------------------------------------------------------
193 
194 template <class PointT>
195 void
197 add_vector_n(const std::vector< Point> & _control_polygon)
198 {
199  insert_vector_n(_control_polygon, dimn_);
200 }
201 
202 //-----------------------------------------------------------------------------
203 
204 template <class PointT>
205 void
207 insert_vector_m(const std::vector< Point> & _control_polygon, unsigned int _m)
208 {
209  std::cout << "insert_vector_m of size " << _control_polygon.size() << " at m = " << _m << std::endl;
210 
211  assert(_m <= dimm_);
212  if (dimn_ == 0)
213  dimn_ =_control_polygon.size();
214 
215  assert(_control_polygon.size() == dimn_);
216 
217  resize(dimm_ + 1, dimn_);
218 
219  control_net_.insert(control_net_.begin() + _m, _control_polygon);
220  control_net_.pop_back(); // TODO check
221  std::cout << "control_net_: " << control_net_.size() << " x " << control_net_[control_net_.size()-1].size() << std::endl;
222 
223  // resize property net cpselection
224  std::vector<unsigned char> dummy(_control_polygon.size(), 0);
225  cpselections_.insert(cpselections_.begin() + _m, dummy);
226  cpselections_.pop_back();
227  std::cout << "cpselections_: " << cpselections_.size() << " x " << cpselections_[cpselections_.size()-1].size() << std::endl;
228 
229  // resize property net eselection
230  eselections_.insert(eselections_.begin() + _m, dummy);
231  eselections_.pop_back();
232  std::cout << "eselections_: " << eselections_.size() << " x " << eselections_[eselections_.size()-1].size() << std::endl;
233 }
234 
235 //-----------------------------------------------------------------------------
236 
237 template <class PointT>
238 void
240 insert_vector_n(const std::vector< Point> & _control_polygon, unsigned int _n)
241 {
242  assert(_n <= dimn_);
243  if (dimm_ == 0)
244  dimm_ = _control_polygon.size();
245 
246  assert(_control_polygon.size() == dimm_);
247 
248  resize(dimm_, dimn_+1);
249 
250  for (unsigned int i = 0; i < dimm_; ++i)
251  {
252  control_net_[i].insert(control_net_[i].begin() + _n, _control_polygon[i]);
253  control_net_[i].pop_back();
254  }
255 
256  // resize property net cpselection
257  for (unsigned int i = 0; i < dimm_; ++i)
258  {
259  cpselections_[i].insert(cpselections_[i].begin() + _n, 0);
260  cpselections_[i].pop_back();
261  }
262  // resize property net eselection
263  for (unsigned int i = 0; i < dimm_; ++i)
264  {
265  eselections_[i].insert(eselections_[i].begin() + _n, 0);
266  eselections_[i].pop_back();
267  }
268 }
269 
270 //-----------------------------------------------------------------------------
271 
272 template <class PointT>
273 void
275 delete_vector_m(unsigned int _m)
276 {
277  assert(_m < dimm_);
278 
280 
281  if(control_net_.begin() + _m < control_net_.end())
282  control_net_.erase(control_net_.begin() + _m);
283 
284  resize(dimm_-1, dimn_);
285 
286  // erase from properties
287  if(cpselections_.begin() + _m < cpselections_.end())
288  cpselections_.erase(cpselections_.begin() + _m);
289 
290  if(eselections_.begin() + _m < eselections_.end())
291  eselections_.erase(eselections_.begin() + _m);
292 
293  // Now rebuild knot vectors
294  createKnots();
295 }
296 
297 //-----------------------------------------------------------------------------
298 
299 template <class PointT>
300 void
302 delete_vector_n(unsigned int _n)
303 {
304  assert(_n < dimn_);
305 
307 
308  for (unsigned int i = 0; i < control_net_.size(); ++i) {
309  if(control_net_[i].begin() + _n < control_net_[i].end())
310  control_net_[i].erase(control_net_[i].begin() + _n);
311  }
312 
313  resize(dimm_, dimn_-1);
314 
315  // erase from properties
316  for (unsigned int i = 0; i < cpselections_.size(); ++i)
317  if(cpselections_[i].begin() + _n < cpselections_[i].end())
318  cpselections_[i].erase(cpselections_[i].begin() + _n);
319 
320  for (unsigned int i = 0; i < eselections_.size(); ++i)
321  if(eselections_[i].begin() + _n < eselections_[i].end())
322  eselections_[i].erase(eselections_[i].begin() + _n);
323 
324  // Now rebuild knot vectors
325  createKnots();
326 }
327 
328 //-----------------------------------------------------------------------------
329 
330 template <class PointT>
331 void
333 get_vector_m(std::vector< Point> & _control_polygon, unsigned int _m)
334 {
335  assert(_m < dimm_);
336  _control_polygon = control_net_[_m];
337 }
338 
339 //-----------------------------------------------------------------------------
340 
341 template <class PointT>
342 void
344 get_vector_n(std::vector< Point> & _control_polygon, unsigned int _n)
345 {
346  assert(_n < dimn_);
347  _control_polygon.resize(dimm_);
348 
349  for (unsigned int i = 0; i < dimm_; ++i)
350  _control_polygon[i] = control_net_[i][_n];
351 }
352 
353 //-----------------------------------------------------------------------------
354 
355 template <class PointT>
356 void
358 set_knots_m(std::vector< Scalar > _knots)
359 {
360  // set the knotvector
361  knotvector_m_.setKnotvector(_knots);
362 }
363 
364 //-----------------------------------------------------------------------------
365 
366 template <class PointT>
367 void
369 set_knots_n(std::vector< Scalar > _knots)
370 {
371  // set the knotvector
372  knotvector_n_.setKnotvector(_knots);
373 }
374 
375 //-----------------------------------------------------------------------------
376 
377 template <class PointT>
378 void
380 insert_knot_m(double _u)
381 {
382  // span and interval i,i+1
383  Vec2i span = spanm(_u);
384  Vec2i interval = interval_m(_u);
385 
386  // create new knot vector
387  Knotvector newknotvecu( get_knotvector_m() );
388  newknotvecu.insertKnot(interval[1], _u);
389 
390  // alphas
391  std::vector<double> alpha;
392  for( int i = span[0]; i < span[1]; ++i)
393  {
394  double a(knotvector_m_.getKnot(i+1));
395  double b(knotvector_m_.getKnot(i+degree_m_+1));
396  alpha.push_back((_u-a)/(b-a));
397  }
398  knotvector_m_ = newknotvecu;
399 
400  // new control net
401  ControlNet oldcpts(control_net_);
402 
404 
405  for( int i = 0; i < n_control_points_m(); ++i) // for all v rows
406  {
407  if( i <= span[0])
408  control_net_[i] = oldcpts[i];
409  else if( i <= span[1])
410  for( unsigned int j = 0; j < n_control_points_n(); ++j)
411  {
412  control_net_[i][j] = oldcpts[i-1][j]*(1.0-alpha[i-span[0]-1])+oldcpts[i][j]*alpha[i-span[0]-1];
413  }
414  else
415  control_net_[i] = oldcpts[i-1];
416  }
417 }
418 
419 //-----------------------------------------------------------------------------
420 
421 template <class PointT>
422 void
424 insert_knot_n(double _v)
425 {
426  // span and interval i,i+1
427  Vec2i span = spann(_v);
428  Vec2i interval = interval_n(_v);
429 
430  // create new knot vector
431  Knotvector newknotvecv( get_knotvector_n() );
432  newknotvecv.insertKnot(interval[1], _v);
433 
434  // alphas
435  std::vector<double> alpha;
436  for( int i = span[0]; i < span[1]; ++i)
437  {
438  double a(knotvector_n_.getKnot(i+1));
439  double b(knotvector_n_.getKnot(i+degree_n_+1));
440  alpha.push_back((_v-a)/(b-a));
441  }
442  knotvector_n_ = newknotvecv;
443 
444  // new control net
445  ControlNet oldcpts(control_net_);
446 
448 
449  for( int i = 0; i < n_control_points_n(); ++i) // for all v rows
450  {
451  if( i <= span[0])
452  for( unsigned int j = 0; j < n_control_points_m(); ++j)
453  control_net_[j][i] = oldcpts[j][i];
454  else if( i <= span[1])
455  for( unsigned int j = 0; j < n_control_points_m(); ++j)
456  {
457  control_net_[j][i] = oldcpts[j][i-1]*(1.0-alpha[i-span[0]-1])+oldcpts[j][i]*alpha[i-span[0]-1];
458  }
459  else
460  for( unsigned int j = 0; j < n_control_points_m(); ++j)
461  control_net_[j][i] = oldcpts[j][i-1];
462  }
463 }
464 
465 //-----------------------------------------------------------------------------
466 
467 template <class PointT>
468 PointT
470 surfacePoint(double _u, double _v)
471 {
472  double epsilon = 0.0000001;
473 
474  if (_u > upperu() && _u < upperu()+epsilon)
475  _u = upperu();
476 
477  if (_v > upperv() && _v < upperv()+epsilon)
478  _v = upperv();
479 
480  assert(_u >= loweru() && _u <= upperu());
481  assert(_v >= lowerv() && _v <= upperv());
482 
483  int pm = degree_m();
484  int pn = degree_n();
485 
486  Point point = Point(0.0, 0.0, 0.0);
487 
488  Vec2i span_m(spanm(_u));
489  Vec2i span_n(spann(_v));
490 
491 
492  std::vector<Scalar> basisFuns_m(pm+1);
493  std::vector<Scalar> basisFuns_n(pn+1);
494 
495  // evaluate basis functions
496  ACG::bsplineBasisFunctions(basisFuns_m, span_m, _u, knotvector_m_.getKnotvector());
497  ACG::bsplineBasisFunctions(basisFuns_n, span_n, _v, knotvector_n_.getKnotvector());
498 
499  // compute surface point
500 
501  for (int i = span_m[0]; i <= span_m[1]; ++i)
502  for (int j = span_n[0]; j <= span_n[1]; ++j)
503  point += control_net_[i][j] * basisFuns_m[i-span_m[0]] * basisFuns_n[j - span_n[0]];
504 
505  return point;
506 }
507 
508 //-----------------------------------------------------------------------------
509 
510 template <class PointT>
511 void
513 surfacePointNormal( Point& _pt, Point& _normal, double _u, double _v )
514 {
515  double epsilon = 0.0000001;
516 
517  if (_u > upperu() && _u < upperu()+epsilon)
518  _u = upperu();
519 
520  if (_v > upperv() && _v < upperv()+epsilon)
521  _v = upperv();
522 
523  assert(_u >= loweru() && _u <= upperu());
524  assert(_v >= lowerv() && _v <= upperv());
525 
526  int pm = degree_m();
527  int pn = degree_n();
528 
529  _pt = Point(0.0, 0.0, 0.0);
530 
531  Vec2i span_m(spanm(_u));
532  Vec2i span_n(spann(_v));
533 
534 
535  std::vector<Scalar> basisFuns_m(pm+1);
536  std::vector<Scalar> ders_m(pm+1);
537  std::vector<Scalar> basisFuns_n(pn+1);
538  std::vector<Scalar> ders_n(pn+1);
539 
540  // evaluate basis functions
541  ACG::bsplineBasisDerivatives(ders_m, span_m, _u, 1, knotvector_m_.getKnotvector(), &basisFuns_m);
542  ACG::bsplineBasisDerivatives(ders_n, span_n, _v, 1, knotvector_n_.getKnotvector(), &basisFuns_n);
543 
544 
545  // compute surface point and tangents
546 
547  Point dpdu = Point(0,0,0);
548  Point dpdv = Point(0,0,0);
549 
550  for (int i = 0; i <= pm; ++i)
551  {
552  for (int j = 0; j <= pn; ++j)
553  {
554  Point cp = control_net_[i + span_m[0]][j + span_n[0]];
555 
556  _pt += cp * (basisFuns_m[i] * basisFuns_n[j]);
557 
558  dpdu += cp * (ders_m[i] * basisFuns_n[j]);
559  dpdv += cp * (basisFuns_m[i] * ders_n[j]);
560  }
561  }
562 
563  _normal = (dpdu % dpdv).normalize();
564 }
565 
566 //-----------------------------------------------------------------------------
567 
568 template <class PointT>
569 PointT
571 surfacePoint_rec(double _u, double _v)
572 {
573  double epsilon = 0.0000001;
574 
575  if (_u > upperu() && _u < upperu()+epsilon)
576  _u = upperu();
577 
578  if (_v > upperv() && _v < upperv()+epsilon)
579  _v = upperv();
580 
581  assert(_u >= loweru() && _u <= upperu());
582  assert(_v >= lowerv() && _v <= upperv());
583 
584  int pm = degree_m();
585  int pn = degree_n();
586 
587  Point point = Point(0.0, 0.0, 0.0);
588 
589  Vec2i span_m(spanm(_u));
590  Vec2i span_n(spann(_v));
591 
592  for (int i = span_m[0]; i <= span_m[1]; ++i)
593  for (int j = span_n[0]; j <= span_n[1]; ++j)
594  point += control_net_[i][j] * basisFunction(knotvector_m_, i, pm, _u) * basisFunction(knotvector_n_, j, pn, _v);
595 
596  return point;
597 }
598 
599 //-----------------------------------------------------------------------------
600 
601 template <class PointT>
602 typename BSplineSurfaceT<PointT>::Scalar
604 basisFunction(Knotvector & _knotvector, int _i, int _n, double _t)
605 {
606  int m = _knotvector.size() - 1;
607 
608  // Mansfield Cox deBoor recursion
609  if ((_i==0 && _t== _knotvector(0)) || (_i==m-_n-1 && _t==_knotvector(m)))
610  return 1.0;
611 
612  if (_n == 0) {
613  if (_t >= _knotvector(_i) && _t < _knotvector(_i+1))
614  return 1.0;
615  else
616  return 0.0;
617  }
618 
619  double Nin1 = basisFunction(_knotvector, _i, _n-1, _t);
620  double Nin2 = basisFunction(_knotvector, _i+1, _n-1, _t);
621 
622  double fac1 = 0;
623 // if ((_knotvector(_i+_n) - _knotvector(_i)) > 0.000001 )
624  if ((_knotvector(_i+_n) - _knotvector(_i)) != 0)
625  fac1 = (_t - _knotvector(_i)) / (_knotvector(_i+_n) - _knotvector(_i)) ;
626 
627  double fac2 = 0;
628 // if ( (_knotvector(_i+1+_n) - _knotvector(_i+1)) > 0.000001 )
629  if ( (_knotvector(_i+1+_n) - _knotvector(_i+1)) != 0 )
630  fac2 = (_knotvector(_i+1+_n) - _t) / (_knotvector(_i+1+_n) - _knotvector(_i+1));
631 
632 // std::cout << "Nin1 = " << Nin1 << ", Nin2 = " << Nin2 << ", fac1 = " << fac1 << ", fac2 = " << fac2 << std::endl;
633 
634  return (fac1*Nin1 + fac2*Nin2);
635 }
636 
637 //-----------------------------------------------------------------------------
638 
639 template <class PointT>
640 PointT
642 derivativeSurfacePoint(double _u, double _v, int _derm, int _dern)
643 {
644  assert(_u >= loweru() && _u <= upperu());
645  assert(_v >= lowerv() && _v <= upperv());
646 
647  int pn = degree_n();
648  int pm = degree_m();
649 
650  Point point(0,0,0);
651 
652  Vec2i span_m(spanm(_u));
653  Vec2i span_n(spann(_v));
654 
655  std::vector<Scalar> ders_m(pm+1);
656  std::vector<Scalar> ders_n(pn+1);
657 
658  ACG::bsplineBasisDerivatives<Scalar>(ders_m, span_m, _u, _derm, knotvector_m_.getKnotvector(), 0);
659  ACG::bsplineBasisDerivatives<Scalar>(ders_n, span_n, _v, _dern, knotvector_n_.getKnotvector(), 0);
660 
661  for (int i = span_m[0]; i <= span_m[1]; i++)
662  for (int j = span_n[0]; j <= span_n[1]; j++)
663  point += control_net_[i][j] * ders_m[i - span_m[0]] * ders_n[j - span_n[0]];
664 
665 
666  return point;
667 }
668 
669 //-----------------------------------------------------------------------------
670 
671 template <class PointT>
672 PointT
674 normalSurfacePoint(double _u, double _v)
675 {
676  assert(_u >= loweru() && _u <= upperu());
677  assert(_v >= lowerv() && _v <= upperv());
678 
679  Point derivu = derivativeSurfacePoint(_u,_v,1,0);
680  Point derivv = derivativeSurfacePoint(_u,_v,0,1);
681 
682  Point normal( (derivu%derivv).normalize());
683 
684  return normal;
685 }
686 
687 //-----------------------------------------------------------------------------
688 
689 template <class PointT>
690 typename BSplineSurfaceT<PointT>::Scalar
692 derivativeBasisFunction(Knotvector & _knotvector, int _i, int _n, double _t, int _der)
693 {
694  assert(_n >= 0);
695  assert(_i >= 0);
696 
697  if (_der == 0)
698  return basisFunction(_knotvector, _i, _n, _t);
699 
700  Scalar Nin1 = derivativeBasisFunction(_knotvector, _i, _n-1, _t, _der-1);
701  Scalar Nin2 = derivativeBasisFunction(_knotvector, _i+1, _n-1, _t, _der-1);
702 
703  Scalar fac1 = 0;
704  if ( fabs(_knotvector(_i+_n)-_knotvector(_i)) > 1e-6 )
705  fac1 = Scalar(_n) / (_knotvector(_i+_n)-_knotvector(_i));
706 
707  Scalar fac2 = 0;
708  if ( fabs(_knotvector(_i+_n+1)-_knotvector(_i+1)) > 1e-6 )
709  fac2 = Scalar(_n) / (_knotvector(_i+_n+1)-_knotvector(_i+1));
710 
711  return (fac1*Nin1 - fac2*Nin2);
712 }
713 
714 //-----------------------------------------------------------------------------
715 
716 template <class PointT>
717 typename BSplineSurfaceT<PointT>::Scalar
720 {
721  return knotvector_m_(degree_m());
722 }
723 
724 //-----------------------------------------------------------------------------
725 
726 template <class PointT>
727 typename BSplineSurfaceT<PointT>::Scalar
730  return knotvector_m_(knotvector_m_.size() - 1 - degree_m());
731 }
732 
733 //-----------------------------------------------------------------------------
734 
735 template <class PointT>
736 typename BSplineSurfaceT<PointT>::Scalar
739 {
740  return knotvector_n_(degree_n());
741 }
742 
743 //-----------------------------------------------------------------------------
744 
745 template <class PointT>
746 typename BSplineSurfaceT<PointT>::Scalar
749  return knotvector_n_(knotvector_n_.size() - 1 - degree_n());
750 }
751 
752 //-----------------------------------------------------------------------------
753 
754 template <class PointT>
757 spanm(double _t)
758 {
759  return ACG::bsplineSpan(_t, degree_m(), knotvector_m_.getKnotvector());
760 }
761 
762 //-----------------------------------------------------------------------------
763 
764 template <class PointT>
767 spann(double _t)
768 {
769  return ACG::bsplineSpan(_t, degree_n(), knotvector_n_.getKnotvector());
770 }
771 
772 //-----------------------------------------------------------------------------
773 
774 template <class PointT>
777 interval_m(double _t)
778 {
779  unsigned int i(0);
780 
781  if (_t >= upperu())
782  i = dimm_-1;
783  else
784  {
785  while (_t >= knotvector_m_(i)) i++;
786  while (_t < knotvector_m_(i)) i--;
787  }
788 
789  return Vec2i(i, i+1);
790 }
791 
792 //-----------------------------------------------------------------------------
793 
794 template <class PointT>
797 interval_n(double _t)
798 {
799  unsigned int i(0);
800 
801  if (_t >= upperv())
802  i = dimn_-1;
803  else
804  {
805  while (_t >= knotvector_n_(i)) i++;
806  while (_t < knotvector_n_(i)) i--;
807  }
808 
809  return Vec2i(i, i+1);
810 }
811 
812 //-----------------------------------------------------------------------------
813 
814 //=============================================================================
815 } // namespace ACG
816 //=============================================================================
void delete_vector_n(unsigned int _n)
Deletes an m control point vector.
void resize(unsigned int _m, unsigned int _n)
Resizes the spline struct.
Point normalSurfacePoint(double _u, double _v)
Returns the normal of a spline surface.
VectorT< signed int, 2 > Vec2i
Definition: VectorT.hh:98
Point surfacePoint_rec(double _u, double _v)
Evaluates a spline surface at parameters _u and _v.
int degree_m() const
Returns the spline degree in m direction.
unsigned int dimm_
number of control points in m direction
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.
ACG::Vec2i spanm(double _t)
Returns the basis functions which are unequal to zero at parameter u.
Scalar loweru()
Returns the lower u parameter.
Namespace providing different geometric functions concerning angles.
Scalar upperv()
Returns the upper v parameter.
unsigned int n_control_points_n() const
Returns the number of controlpoints in n direction.
void add_vector_n(const std::vector< Point > &_control_polygon)
Adds a control point m-vector.
Knotvector knotvector_m_
Knotvector in m direction.
void set_degree(unsigned int _degm, unsigned int _degn)
Sets the degree of the spline surface.
ACG::Vec2i spann(double _t)
Returns the basis functions which are unequal to zero at parameter v.
ACG::Vec2i interval_n(double _t)
Returns the index of the knots v and v+1 such that t in [v, v+1)
unsigned int n_control_points_m() const
Returns the number of controlpoints in m direction.
void createKnots()
Creates interpolating knotvectors 0...0, 1, 2, ..., n...n.
ACG::Vec2i interval_m(double _t)
Returns the index of the knots u and u+1 such that t in [u, u+1)
Point surfacePoint(double _u, double _v)
Evaluates a spline surface at parameters _u and _v.
BSplineSurfaceT(unsigned int _degm=3, unsigned int _degn=3)
Constructor.
Vec2i bsplineSpan(Scalar _t, int _degree, const std::vector< Scalar > &_knots)
Find the span of a parameter value.
Definition: BSplineBasis.cc:71
void add_vector_m(const std::vector< Point > &_control_polygon)
Adds a control point n-vector.
void set_knots_m(std::vector< Scalar > _knots)
Set the knotvector of the bspline surface in m direction.
void insert_vector_n(const std::vector< Point > &_control_polygon, unsigned int _n)
Inserts an m control point vector.
void set_knots_n(std::vector< Scalar > _knots)
Set the knotvector of the bspline surface in n direction.
Knotvector get_knotvector_m()
Get the knotvector in m direction.
PropertyNet cpselections_
list of control point properties
unsigned int degree_n_
Spline degree in n direction.
void get_vector_m(std::vector< Point > &_control_polygon, unsigned int _m)
Returns an n control point vector.
void bsplineBasisFunctions(std::vector< Scalar > &_N, const Vec2i &_span, Scalar _t, const std::vector< Scalar > &_knots)
Evaluate basis functions in a span.
void reset_control_net()
Clears the control net.
Scalar lowerv()
Returns the lower v parameter.
void delete_vector_m(unsigned int _m)
Deletes an n control point vector.
unsigned int dimn_
number of control points in n direction
Scalar upperu()
Returns the upper u parameter.
void insert_knot_m(double _t)
Insert a knot i in m direction without changing the surface.
Knotvector knotvector_n_
Knotvector in n direction.
PropertyNet eselections_
list of edge properties
void insert_vector_m(const std::vector< Point > &_control_polygon, unsigned int _m)
Inserts an n control point vector.
void surfacePointNormal(Point &_pt, Point &_normal, double _u, double _v)
Evaluates a spline surface at parameters _u and _v.
void get_vector_n(std::vector< Point > &_control_polygon, unsigned int _n)
Returns an m ctrPointVector.
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.
void insert_knot_n(double _t)
Insert a knot i in n direction without changing the surface.
Knotvector get_knotvector_n()
Get the knotvector in n direction.
Point derivativeSurfacePoint(double _u, double _v, int _derm, int _dern)
Returns the _derm&#39;th derivative of a spline surface.
unsigned int degree_m_
Spline degree in m direction.
Scalar derivativeBasisFunction(Knotvector &_knotvector, int _i, int _n, double _t, int _der)
Derivative of a Spline Basis Function.