source: trunk/source/graphics_reps/doc/G4NURBS.txt @ 1350

Last change on this file since 1350 was 1350, checked in by garnier, 13 years ago

update to last version 4.9.4

File size: 28.3 KB
Line 
1$Id: G4NURBS.txt,v 1.1 1999/01/07 16:09:09 gunter Exp $
2Olivier Crumeyrolle, 17th September 1996.
3
4                The G4NURBS C++ class library
5
6 
7
8                Documentation (September 6  '96)
9
10        Introduction
11
12In GEANT4, there is a need for visual representations. Non Uniform Rational
13B-Spline (NURBS) are an interesting choice as they allow an exact
14representation of conics, unlike others, and have a lot of other convenient
15properties. Furthermore NURBS are an industry standard in  Computer Aided
16Design (CAD) systems.
17
18The goal of the G4NURBS C++ class library is to handle NURBS and to provide all
19the necessary methods so they can be succesfully used.
20
21        Summary
22
23The G4NURBS class handles the data needed to define a NURBS surface,
24i.e. the orders of the NURBS used, the knot values and control points
25(explanations later).
26
27G4NURBS provides an important number of access functions to allow any graphics
28model (GM) to build its own NURBS. Although building the GM's NURBS with
29G4NURBS data (or vice versa) without any copy would be the more efficient way,
30different GMs typically use different data types, so copying and converting is
31required. For that G4NURBS provides some basic functions and also some more
32clever iterators  to simplify the user's task.
33
34Some GMs support NURBS (OpenGL, GPHIGS), but for others G4NURBS (will) provide
35some adaptative tessellation functionalities, if possible as a convertion to
36G4Polyhedron.
37
38For the GEANT4 geometry user, G4NURBSbox, G4NURBScylinder, G4NURBStube  and
39G4NURBStubesector are implemented.
40
41Some transformation functions (partial revolution in particular) will may be
42added so anyone can build almost any shape with G4NURBS, starting with some
43basic ones only, and without complication.
44
45If everything's OK, G4NURBS could become a nice kind of primitive.
46
47
48
49
501 Building a G4NURBS instance
51
52This section is essentialy dedicated to the GEANT4 geometry user.
53
541.1 From a G4VSolid to a G4NURBS
55
561.1.1 Box
57
58It's straightforward with G4NURBSbox. If DX, DY and DZ are the half-lengths in
59the X, Y an Z directions respectively, then
60
61G4NURBSbox * pmybox = new
62G4NURBSbox(DX, DY, DZ);
63
64builds the corresponding box. Thanks to polymorphism,
65this object is a G4NURBS like any other.
66
671.1.2 Tubs
68
69In Geant4, tubs are used to represent some sectors of tube, but also complete
70tubes and cylinders. To keep it simple, there is no G4NURBStubs, but a
71G4NURBScylinder, a G4NURBStube and a G4NURBStubesector.
72
73If RMIN, RMAX, DZ, PHI1, PHI2 are the tubs parameter (but with angles in
74radians), then something like
75
76G4NURBS * pmynurbs;
77if (RMIN != 0)
78        {
79        if ( ((PHI2-PHI1) >= 2*M_PI) || (PHI2==PHI1) )
80                pmynurbs = new G4NURBStube(RMIN, RMAX, DZ);
81           else pmynurbs = new G4NURBStubesector(RMIN, RMAX, DZ, PHI1, PHI2);
82        }
83   else
84        {
85        if ( ((PHI2-PHI1) >= 2*M_PI) || (PHI2==PHI1) )
86                pmynurbs = new G4NURBScylinder(RMAX, DZ);
87           else pmynurbs = new G4NURBStubesector(0.0001, RMAX, DZ, PHI1, PHI2);
88        };
89
90builds the appropriate representation.
91NB: as you can see there is no sector of cylinder, so we use
92G4NURBStubesector(epsilon, RMAX, DZ, PHI1, PHI2).  A new release will include
93G4NURBScylindersector one day.
94
95Note that G4NURBStubesector can in principle handle all possible tubs, (it even
96works with negative radius, negative length and more than two pi angle
97difference) but the graphics system will probably have some difficulties with
98the NURBS, and even if it display it, you will not like the result.
99
100
1011.2 In general
102
103One cannot build directly a G4NURBS object. G4NURBS is just an handling class.
104To have some instance you must derive from G4NURBS and use one of its protected
105constructors in the child class constructor initialisation list. The first
106G4NURBS constructor is able to produce a regular knot vector for an unallocated
107knot vector, and the second one (the most easy to use) handles allocation of
108all arrays and is able to produce some "linear" but also some "circular" knots.
109G4NURBSbox and G4NURBStube use the second constructor and are good examples,
110G4NURBStubs is slightly more complex but shows how to build automatically  a
111G4NURBS. G4NURBScylinder is the only one written with the first constructor, to
112provide an example. See also comments in G4NURBS.hh. This file contains in the
113appendix an introduction to NURBS, with some examples. You should also follow
114the recommendations in 4.2.4.
115
116
1171.3 Future prospects
118
119A child class with an istream based constructor might be written which allows
120the user  to load a NURBS Definition file (as the << overload currently
121generates them).
122
123Some transformation functions might be written in order to help the user to
124build a NURBS from basic one. (suggestions are welcomed)
125
126A child class G4NURBStrimmingcurve might be written  with some methods to help
127the user to clip NURBS or to convert some boolean solids into clipped NURBS.
128However the GMs must support surface trimming, as it's not straightforward to
129generate an equivalent representation of a trimmed NURBS (set of smaller NURBS?)
130
131
132
1332 Access functions
134
135This section will more interest the graphics model devloper.
136
1372.1 Simple data access with and without a direction selector
138
139To retrieve NURBS simple data (order, various numbers) a first set of
140access functions is provided :
141
142        G4int   getUorder() const;
143        G4int   getVorder() const;
144        G4int   getUnbrKnots() const;
145        G4int   getVnbrKnots() const;
146        G4int   getUnbrCtrlPts() const;
147        G4int   getVnbrCtrlPts() const;
148
149where nbr is short for number and CtrlPts for control points.
150
151Another set of functions using a _selector_ is provided :
152
153        G4int   getorder(t_direction in_dir) const;
154        G4int   getnbrKnots(t_direction in_dir) const;
155        G4int   getnbrCtrlPts(t_direction in_dir) const;       
156
157The selector in_dir is an enum in the G4NURBS scope. So the complete type name
158is G4NURBS::t_direction, and values are G4NURBS::U for retrieving data related
159to the U direction, and G4NURBS::V for V.
160
161Hence the following calls are equivalent :
162        my_nurbs.getUorder();
163        my_nurbs.getorder(G4NURBS::U);
164The first may be slightly faster than the second (cf inline code in G4NURBS.hh).
165
166G4NURBS::NofD is also defined, where NofD means nbr of directions. One could use
167it for loops over direction. However as enum can't be incremented this is not as
168useful as it could be. See the << overload in G4NURBS.cc for a loop example  or
169the constuctors (still in G4NURBS.cc) for another example.
170
171
1722.2 Access to knots and control points
173
1742.2.1
175A set of basic functions is provided :
176
177        G4float         getfloatKnot(   t_direction in_dir, t_indKnot in_index)
178                        const;
179
180        G4double        getdoubleKnot(  t_direction in_dir, t_indKnot in_index)
181                        const;
182
183        t_floatCtrlPt*  getfloatCtrlPt( t_indCtrlPt in_onedimindex) const;
184
185        t_floatCtrlPt*  getfloatCtrlPt( t_inddCtrlPt in_Uindex,
186                                        t_inddCtrlPt in_Vindex) const;
187
188        t_doubleCtrlPt* getdoubleCtrlPt(t_indCtrlPts in_onedimindex) const;
189
190        t_doubleCtrlPt* getdoubleCtrlPt(t_inddCtrlPts in_Uindex,
191                                        t_inddCtrlPts in_Vindex) const;
192
193The first two return the in_index th knot (with a 0 based numbering, so the
194valid index goes from 0 to nbrKnots-1) after converting it into G4float or
195G4double. The four others functions do the same with control points. The
196returned pointer points to a brand-new allocated array with the control points
197coordinates. You can do what you want with it, it's _your_ copy, (non-const) and
198you must delete it after use. You can give the U and V index or a global index,
199as control points are stored U increasing first.
200
201The followings calls are equivalent :
202        // suppose a 5 by 9 net of ctrlpts (5 along U, 9 along V)
203        // and t_doubleCtrlPt * pmycp;
204        pmycp = my_nurbs.getdoubleCtrlPt(3, 2);
205        pmycp = my_nurbs.getdoubleCtrlPt(13);
206
207However, iterators are an easier way to retrieve the knots or the control points
208in a sequential manner.
209
2102.2.2 Iterators
211
212Iterators are defined in the G4NURBS public scope, to avoid the  global
213namespace pollution. Therefore their type name is G4NURBS::KnotsIterator,
214G4NURBS::CtrlPtsCoordsIterator, G4NURBS::CtrlPtsIterator.
215
216Iterators are independent objects : you can allocate as many iterators as you
217want and make them work concurrently. However the G4NURBS object MUST be defined
218when you use iterators over it (and must not be changed). See the Possible
219improvements 1.2 section for more about that.
220
2212.2.2.1
222G4NURBS::KnotsIterator allows the user to retrieve knots one after the other. It
223can be used as follows to get all the knots along the U direction as 'float'
224numbers :
225
226// assuming mynurb is a G4NURBS, for instance G4NURBSbox my_nurb(1,2,3);
227G4float * my_array, * my_float_p;
228my_float_p = my_array = new float [my_nurb.getnbrKnots(G4NURBS::U)];
229G4NURBS::KnotsIterator  my_iterator(my_nurb, G4NURBS::U);
230while (my_iterator.pick(my_float_p++));
231
232Then my_array contain all the knots, and my_float_p point just after the array.
233The trick is that pick functions return false when they pick the last knot.
234
235The constructor has an optional third argument, in_startIndex, preseted to zero.
236It's possible to give another value to retrieve half of the knots for instance.
237(will probably be used in splitting)
238
239
240
241
2422.2.2.2
243G4NURBS::CtrlPtsCoordsIterator is very similar to the Knots one.
244The control points are retrieved coordinate after coordinate,
245and, if we note i the index along U and j the one along V,
246control points P_i_j themselves are obtained i increasing first, j after :
247P_1_1, P_2_1, P_3_1, P_4_1, ....., P_1_2, P_2_2, P_3_2, P_4_2, ....
248
249G4float * my_array, * my_float_p;
250my_float_p = my_array = new float [my_nurb.gettotalnbrCtrlPts()
251                                        *G4NURBS::NofC*sizeof(float)];
252G4NURBS::CtrlPtsCoordsIterator my_iterator(my_nurb);
253while (my_iterator.pick(my_float_p++));
254
255
2562.2.2.3
257G4NURBS::CtrlPtsIterator work control point by control point, instead of control
258point coordinate by control point coordinate. Remember that control points are
259given U index increasing first, V after. The << overload in G4NURBS.cc contains
260an exemple where the retrieved control point is used immediately.
261
262
2632.2.3
264
265Some "complete-copy" functions are also provided.
266
267        G4float *       getfloatAllKnots(t_direction in_dir) const;
268        G4double *      getdoubleAllKnots(t_direction in_dir) const;
269        G4float *       getfloatAllCtrlPts() const;
270        G4double *      getdoubleAllCtrlPts() const;
271
272These functions return a pointer over a new array with all the knots or control
273points copied. You do not control the allocation nor the copy, but you own the
274result and will have to delete it.
275
276They are more easy to use than iterators, but less flexible.
277
278Be careful with these functions, as _you_ choose the type, whereas with
279iterators the compiler choose the good pick function for you. If G4double or
280G4float change, you must change your code, instead of just recompile it.
281
282
283
284
2853 Use in GEANT4
286
2873.1 NURBS manipulations
288
289The public interface of G4NURBS does not allow the user to modify a NURBS. The
290user is expected to create G4NURBS via child classes. Splitting, tesslation, or
291other non-conservative processes should occur only as a conversion to a child
292class, via its constructor, or eventually with a conversion operator.
293
294e.g.   
295
296G4NURBSashape mynurbs(foo, goo, hoo);
297
298// for splitting
299G4NURBSsplit mypieceofnurbs(mynurbs, splitdirection, splitpointvalue);
300
301// for tessellation, if
302// class G4PolyhedronedNURBS : public G4Polyhedron
303// has a constructor G4PolyhedronedNURBS(const G4NURBS &, G4Float tolerance)
304G4PolyhedronedNURBS mytessellatednurbs(mynurbs, thetolerance);
305
306// (a multiple inheritance could be used to have a "dual-face"
307// object Polyhedron/NURBS, with the advantage of keeping
308// a NURBS and its tessellation together, and the disadvantge
309// of duplicating the original NURBS into this child)
310
311The resulting instance is not necessary constant, G4NURBSsplit could provide
312some sub-splitting and refinement methods that act on itself.
313
314
3153.2 Copying policy
316
317A copy constructor is provided, but in the private part. A warning message
318( "WARNING: G4NURBS::G4NURBS(const G4NURBS &) used" )
319is printed on cerr each time the copy constructor is called.
320
321As long as there is no sophisticated memory management scheme that reduce
322useless duplications, copying should be avoided. We have already to duplicate
323data for the GM, once is enough.
324
325
326
3274       Possible internal improvements that could have consequences
328
3294.1 Memory management :
330
3314.1.1   G4NURBS use the minimal memory management scheme possible. Control
332        points, knots, are stored in basic arrays. NURBS characteristics are
333        stored in simple structure. All those internal data could be handled in
334        protected classes with ad hoc constructors, which would be more
335        reliable. The G4NURBS copy constructor would be more elegant. However
336        performance may decrease. This point is related to typing. See 2.1.
337
3384.1.2   Some reference counting facilities should be added for internal arrays
339        so that iterators could correctly work after a G4NURBS is
340        deleted/changed. This point could be solved with 1.1 in a elegant way.
341        We should at least warn the user when a nurbs is deleted before the
342        corresponding iterators. However if we want to do the things in a good
343        way references counters must be associated to arrays. Once again 1.1 is
344        the solution for that. To put references as members, we need the future
345        "mutable" keyword planed by the ANSI C++ committee, or the counting will
346        be uncompatible with const instances.
347
3484.2 Internal data type
349
3504.2.1   Knots and control points types are just typedefs, idem for index types.
351        They could be strong types (i.e. classes), but performance costs will
352        may be significant.
353
3544.2.2   enum type are useful to enforce the user to do good things (like using
355        G4NURBS::U instead of 0), but are not really convenient for loops. Some
356        internal alias should be defined to allow some more easy loops. [this
357        concern the geom user only if he/she writes some G4NURBS children]
358
359
360
3614.2.3   As the user doesn't know the internal data type, it could be possible
362        for G4NURBS to adapt itself to the GM currently used, so this GM could
363        use directly the G4NURBS data. This adaptation concern the control
364        points storage order and knot values (some fast algorithms exists for
365        knots which differe of 0 or 1 only). It would be necessary to write some
366        inline functions for control points initialization that spare the child
367        class writer to know the storage order, see 4.2.4. But once again, what
368        about performance ? The G4NURBS constructors and the initializations
369        functions used in child constructors would have to change their target
370        type, and thus we need a very clever scheme to be compatible with the
371        use of different GMs in the same time.
372
3734.2.4   For the momment the control points storage order is publicly known, that
374        could change, with a formal class level between G4NURBS and
375        G4NURBSashape children. Calls like CP(mpCtrlPts[..], .... will have to
376        be rewritten; a tool will may be provided to automaticaly do that. Use
377        if possible explicit U & V index values like
378
379        CP(mpCtrlPts[to1d(U_index, V_index)], .......
380
381        [this concerns the geometry user only if he/she writes some
382        G4NURBSashape].
383
384
3854.3 External interfacing types
386
3874.3.1   For the moment G4int, G4double, G4float, are just alias for int, double,
388        float. These G4 types are used in the G4NURBS interface (the public part
389        of G4NURBS). If their definitions are changed, the significance of the
390        access functions will change too, user should take care about that when
391        using access functions with some others types (e.g. GLfloat )  In a more
392        general way this type interfacing problem will have to be solved at a
393        general level as different  GS are used. For the moment G4Float is used
394        internally and interfaced to G4float and G4double.
395
3964.3.2   Child constructors take all their arguments as G4double. This may have
397        to change, depending on the exact work that G4VSolid children have to
398        do. Length arguments should be unsigned (but unsigned G4double is
399        illegal), and angles in radians should have a different type from those
400        in degrees.
401
402
4034.4 Names
404
4054.4.1   G4NURBS could become G4VNurbs, and G4NURBSbox could become G4NurbsBox.
406
407
4085       Prospects
409       
410
4115.1 For NURBS in general
412
413NURBS are likely to become more and more widely supported by software, but also
414by hardware. Nvidia NV1 PCI card for PCs already accelerate quadratic curves
415(and may be more) . The new SPARCstation 20TurboZX provide dynamic tessellation
416for NURBS in firmware.
417
4185.2  Births
419
420G4NURBS will probably have others children in the future, in particular for
421splitting. However the object oriented programming allows anyone to create some
422child classes. Don't hesitate to enlarge the family.
423
424
425
426
427
428
429
430Appendix
431
432        Non Uniform Rational B-Spline (NURBS).
433
4341 About Representation
435
436A curve or a surface are mathematicaly a set of points. However the number of
437points is infinite, what is not convenient at all. We need a more operational
438way for describing the set of points. Here we use a parametric representation :
439the curve is described by a function of 1 real parameter t : C(t), the surface
440with two parameters called u and v : S(u,v). As the parameter(s) go(es) from a
441minimal value to a maximal one, the function describes the curve/surface. Now we
442need a representation for this function itself. To achieve this, the function is
443projected over a set of basis functions. Of course the kind of functions we can
444represent in this way is determined by the kind of basis functions used. We will
445work with real-valued polynomial function, as they are easy to represent, can
446approximate any continuous function as well as we want and are convenient in
447general. Once basis functions are chosen, the kind of 'coordinates' that a
448function will have over such a basis is determined : the function describe a set
449of point whereas basis functions chosen are real-valued, so the 'coordinates'
450are necessary some points, called control points, noted P_i (or P_{i,j}),
451represented by their position-vector, and multipied by the basis functions.
452
453A curve will then be expressed as C(t) = sum(i = 1, n) { P_i * B_i(t) }
454where B_i is the ith basis functions.
455A surface could be expressed as S(u,v) = sum(i = 1, n) { P_i * B_i(u,v) },
456but we will use a more easy scheme, explained in 2.5
457
458An interesting point is that if T is a linear transformation,
459T[C(t)] = sum(i = 1, n) { T[P_i] * B_i(t) }
460
4612 B-Spline curves and surfaces
462
4632.1 B-Spline basis functions
464
465They are defined as following :
466
467B_{i,1} = 1 if t_i <= t <= t_{i+1}, 0 otherwise
468
469B_{i,k}(t) =    ((t-t_i)/(t_{i+k-1}-t_i))*B_{i,k-1}(t)
470                +
471                ((t_{i+k}-t)/(t_{i+k}-t_{i+1}))*B_{i+1,k-1}
472i goes from 1 to n, the number of basis functions.
473k is the order of the B-Spline.
474(t_i)_{1<=i<=n+k} a sequence of non-decreasing values called knots that defines
475the B_{i,k}, and is globaly designed as the knot vector.
476The B-Spline is said to be uniform if t_{i+1}-t_i = d > 0 for any i, non-uniform
477(NU) otherwise, with the convention 0/0 = 0.
478
479We concentrate first on uniform B-Splines (UBS)
480
481
4822.2 Some UBS properties
483
484The recursive relation defines B_{i,k} as a linear interpolation between
485B_{i,k-1}  and B_{i+1,k-1}. Thus B_{i,k} is a polynomial of degree k-1,
486strictly positive in [t_i, t_{i+k}], nul elsewhere. For a given t / t_i <= t <
487t_{i+1}, only B_{i-k+1,k} to B_{i,k} are non-nul. The (endknot-startknot)
488divisors in the relation imply that sum(i = 1,n){B_{i,k}(t)} = 1.
489
490[picture of UBS basis functions from k=1 to 2 or 3]
491
492
4932.3 Change of basis : the Oslo algorithm
494
495It is possible to increase the number of basis functions used.
496
497If (t_i)_{1<=i<=n+k} is the old knot vector and (t'_i)_{1<=i<=n'+k} the new
498one, then P'_i = sum (j = 1, n) { alpha_{i,j,k} * P_j }
499
500where alpha_{i,j,k} is given by a recursive relations similar to B_i,k ones :
501
502alpha_{i,j,k} =   ((t'_{j+k-1} - t_i) / (t_{i+k-1} - t_i)) * alpha_{i,j,k-1}
503          + ((t_{i+k} - t'_{j+k-1}) / (t_{i+k} - t_{i+1})) * alpha_{i+1,j,k-1}
504
505The Oslo algorithm is not used in the G4NURBS class library at the moment,
506but it will when splitting functionalities will be added.
507
5082.4 UBS curves
509
510Once we have defined the basis function, a curve is expressed as following :
511
512C(t) = sum(i = 1, n) { P_i * B_{i,k}(t) }
513
514where P_i are the control points and k the order.
515(This maps [t_min, t_max] to the curve.)
516
517If we note C^n the class of functions that are continuous up to the nth
518derivative (included), then for t_i < t < t_{i+1}, C(t) is C^infinite, and at t
519= t_i, C(t) is C^{k-2}.
520
521[pictures ?]
522
523If a control points is repeated k-1 time or more, the curve goes through it.
524
525
5262.5 UBS surfaces
527
528Surfaces are expressed as the tensor product of two curves :
529
530S(u,v) = sum(i=1,n) sum(j=1,m) { P_{i,j}*B_{i,k}(u)*B_{j,l}(v) }
531
532where P_{i,j} is the net of control points.
533(This maps [u_min,u_max] x [v_min,v_max] to the surface.)
534
535
536This is more convenient than starting from 2D splines, or similar functions,
537but you must keep in mind that with such a scheme the curve along one direction
538must be sufficently complexe to handle the shape complexity all along this
539direction. However it's sometime possible to choose a direction for a parameter
540in such a way that the surface is more simple along this direction.
541
542
5432.6 Choice of parameter domain
544
545In the G4NURBS class library, the default is zero as the minimal parameter
546value, one for the maximal, and t_{i+1}-t_i = ( 0 or constant) ). However
547examples in section 4 will use t_i = integer for non-coincident knots, as it's
548more legible.
549
550 
551
5523 NURBS curves and surfaces
553
5543.1 NU
555
556As previously said, the knots interval can vary. As we still impose t_{i+1} >=
557t_i, the limit case is t_{i+1} = t_i. In such a case, B_{i,1} is reduced to a
558point, B_{i,2} and B_{i+1,2} overlap on a knot segment reduced to a point, and
559at this point C(t) will be only C^{k-3}, making the curve less smooth. More
560generally if a knot appears M times, C(t) is C^{k-M-1}. If M = k-1, C(t) is
561C^0, the curve is still continuous but can have a corner at t = t_i = ... =
562t_{i+k-2} and go through the corresponding control point P_{i-1}, thanks to
563B_{i-1,k} that cover t_i to t_{i+k-2,k}. If M = k, the curve is no longer
564continous : all the basis B-Splines from B_{i-k,k} to B_{i-1,k} stop at t = t_i
565= ... = t_{i+k-1} and the curve stop a the corresponding  control point
566P_{i-1}. If there are other knots and control points after, the curve restarts
567from next control point P_i, as B_{i,k} to B_{i+k-1,k} start at t_{i+k-1} = t'.
568
569
5703.2 R
571
572The control points are no longer usual position vectors in the plane
573(isomorphic with R^2)  or in the space (isomorphic with R^3) but an element of
574the projective space P^n, which as one dimension more that the corresponding
575usual space. P^n, isomorphic with R^n, is associated with the usual space
576isomorphic with R^{n-1} : (x, y, w) in P^3 corresponds to (x/w, y/w) in R^2,
577(x, y, z, w) in P^4 corresponds to (x/w, y/w, z/w) in R^3 and so on. If w = 0,
578the point goes to infinity, defining a direction. Thus working in the
579projective space allows us to work with points and vectors, and all affine
580transformations in the usual space can be combined into a linear ones in the
581projective space, as well as projections. The coordinates in P^n are said to be
582homogeneous or rational, and items expressed with such  coordinates are
583highlighted by an ^h.
584
585
5863.3 NU R BS
587
588NURBS are NUBS in the projective space. Hence to transform a NURBS, one just
589has to transform the control points, even for projections.
590
591The last homogeneous coordinate w is called the "weight".
592
5933.4 NURBS curves
594
595If P_i = (x_i, y_i), then P^h_i = (w_i*x_i, w_i*y_i, w_i)
596and a curve is expressed in P^3 by
597
598C^h(t) = sum(i = 1, n) { P^h_i * B_{i,k}(t) }
599
600and in R^2 by
601
602C(t) = sum(i = 1, n){ w_i* P_i * B_{i,k}(t) } / sum(i = 1, n){ w_i* B_{i,k}(t) }
603
604
6053.5 NURBS surfaces
606
607If P_i = (x_i, y_i, z_i), then P^h_i = (w_i*x_i, w_i*y_i, w_i*z_i, w_i)
608and a surface is expressed in P^4 by
609
610S^h(u,v) = sum(i=1,n) sum(j=1,m) { P^h_{i,j} * B_{i,k}(u) * B_{j,l}(v) }
611
612and in R^3 by
613
614S(u,v) = sum(i=1,n) sum(j=1,m) { w_{i,j} * P_{i,j} * B_{i,k}(u) * B_{j,l}(v) }
615        /sum(i=1,n) sum(j=1,m) { w_{i,j} * B_{i,k}(u) * B_{j,l}(v) }
616
617
618
6193.6 NURBS advantages/disadvantages
620
6213.6.1 Advantages :
622
623        Common representation for shapes, even with discontinuities.
624
625        Exact representation of conics section (and for all shapes that have a
626        polynomial parametrisation in the projective space).
627
628        Invariant under affine and perspective tranformations.
629
630        Flexible (lot of manipulations possible, cf 4).
631
632        Generalization of others B-splines / Bezier shapes.
633
6343.6.2 Drawbacks :
635 
636        Today need some calculations to be converted to triangles and/or
637        quadrilaterals as these are the only kind of shapes directly handled
638        by graphics systems at low-level (OpenGL is able to do that but it
639        really generate too many triangles/squares).
640
641        Extra storage for simple shapes.
642
643        We must choose a good parameterisation.
644
645
646
647
6484 Examples of NURBS
649
6504.1 Linear
651
652With 2.1 definition, linear B-Spline are order 2 : k = 2.
653All the weigths are equal to ones in what follows.
654
6554.1.1 Segment
656
657We want a strait line from P_1 to P_2. To start the curve at P_1, we need a knot
658repeated k times at the begining and at the end of the knot vector. Thus the
659knot vector looks like { 0 0 ... 1 1 }. Do we need more than four knots ? No,
660two control points, a second order NURBS, 2 + 2 = 4, number of knots. (Remember
661(t_i)_{1<=i<=n+k})
662
6634.1.2 Polyline
664
665We could just put some lines in such a way that they connect each other in a
666head to tail fashion,
667
668{ 0 0  1 1 }
669[ P_1, P_2 ]
670                Set P_3 = P_2
671{ 0 0  1 1 }
672[ P_3, P_4 ]
673                Set P_5 = P_4
674{ 0 0  1 1 }
675[ P_5, P_6 ]
676
677and union them in one NURBS :
678
679{  0 0     1 1       2 2    3 3 }
680[  P_1, P_2, P_3, P_4, P_5, P_6 ] still with P_3 = P_2 and P_5 = P_4.
681
682Then we can simplify the NURBS :
683
684{ 0 0       1         2     3 3 }
685[ P_1,     P_3,      P_4,   P_6 ]
686
687
6884.1.3 Square
689
690If P_1, P_2, P_3, P_4 are the four corners, we can do a NURBS with
691a polyline that starts and stop at P_1 :
692
693{ 0 0  1   2   3  4 4 }
694[ P_1 P_2 P_3 P_4 P_1 ]
695
696
6974.1.4 Box
698
699If we take a square and move it (=extrude) along a perpendicular edge, we get a
700box which lack to faces, the two ones that are perpendicular to the edge along
701which we extruded the square. Note that if you change the order in which you are
702considering the tensor product, this surface is a segment (the edge) moved along
703a square.
704
705{ 0 0   1    2    3   4 4 }   by
706                             
707[ P_1  P_2  P_3  P_4  P_1  ] {  0 0
708[ P'_1 P'_2 P'_3 P'_4 P'_1 ]    1 1 }
709
710To close the sides, we repeat the extremeties,
711
712{ 0 0   1    2    3   4 4 }   by
713                             
714[ P_1  P_2  P_3  P_4  P_1  ] {  0 0
715[ P_1  P_2  P_3  P_4  P_1  ]     1
716[ P'_1 P'_2 P'_3 P'_4 P'_1 ]     2
717[ P'_1 P'_2 P'_3 P'_4 P'_1 ]    3 3 }
718
719and then reduce the first and last square to a line or a point.
720For instance if P_0 is the center of the P_i side and P'_0 the one of the P'_i,
721
722{ 0 0   1    2    3   4 4 }   by
723                             
724[ P_0  P_0  P_0  P_0  P_0  ] {  0 0
725[ P_1  P_2  P_3  P_4  P_1  ]     1
726[ P'_1 P'_2 P'_3 P'_4 P'_1 ]     2
727[ P'_0 P'_0 P'_0 P'_0 P'_0 ]    3 3 }
728
729(Put differently, we take half of a rectangle and "rotate" it along a square.)
730
731The G4NURBSbox use something like
732
733{ 0 0   1    2    3   4 4 }   by
734                             
735[ P_1  P_1  P_4  P_4  P_1  ] {  0 0
736[ P_1  P_2  P_3  P_4  P_1  ]     1
737[ P'_1 P'_2 P'_3 P'_4 P'_1 ]     2
738[ P'_1 P'_1 P'_4 P'_4 P'_1 ]    3 3 }
739
740rectangles reduced to lines, to avoid a "star" effect on display.
741
742
7434.1.4 Trap
744
745There is no realy difference with the box. One just have to check
746that P_i and P'_i are on the same edge, or the trap will be twisted.
747
748
749
750
7514.2 Quadratic :
752
753Quadratic B-Splines are order 3 : k = 3.
754
755
7564.2.1 Arc
757
758We start at P_1 = (1,0) in R^2, and stop at P_3 = ( cos phi, sin phi ).
759With the knot vector { 0 0 0  1 1 1 }, we just need another control point, P_2.
760P_2 defines with P_1 the tangent at P_1, and with P_2 the tangent at P_2,
761thus P_2 is at ( 1, tan phi/2 ) and its weight is not 1, unlike P_1 and P_3,
762but cos phi/2.
763
764
7654.2.2 Circle
766
767To avoid infinite values, a circle is made by many arcs, for instance
768three 120 degrees arcs or four 90 degrees arcs. They are joined and simplified
769as for the polyline.
770
771ex:
772the circle used in G4NURBScylinder is made by four 90 degree arc :
773(s = sqrt(2)/2)
774
775{ 0 0 0         1 1           2 2            3 3         4 4 4 }
776[ 1,0,1  s,s,s 0,1,1 -s,s,s -1,0,1 -s,-s,s -1,0,1 -s,s,s 1,0,1 ]
777
778
7794.2.3 Cylinder
780
781We build a cylinder from the circle as we made the box from the square :
782extrusion + closing
783
784
7854.2.3 Tube
786
787The tube is obtained by revolving a rectangle around the tube axis.
788
789
790
791
792
793For suggestion/change/English corrections : contact me or e-mail (via
794olivierc@h2.ph.man.ac.uk)
795( I'm sure it needs some English corrections )
796
Note: See TracBrowser for help on using the repository browser.