1 /*---------------------------------------------------------------------------*\
2 * OpenSG NURBS Library *
5 * Copyright (C) 2001-2006 by the University of Bonn, Computer Graphics Group*
7 * http://cg.cs.uni-bonn.de/ *
9 * contact: edhellon@cs.uni-bonn.de, guthe@cs.uni-bonn.de, rk@cs.uni-bonn.de *
11 \*---------------------------------------------------------------------------*/
12 /*---------------------------------------------------------------------------*\
15 * This library is free software; you can redistribute it and/or modify it *
16 * under the terms of the GNU Library General Public License as published *
17 * by the Free Software Foundation, version 2. *
19 * This library is distributed in the hope that it will be useful, but *
20 * WITHOUT ANY WARRANTY; without even the implied warranty of *
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
22 * Library General Public License for more details. *
24 * You should have received a copy of the GNU Library General Public *
25 * License along with this library; if not, write to the Free Software *
26 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
28 \*---------------------------------------------------------------------------*/
29 /*---------------------------------------------------------------------------*\
37 \*---------------------------------------------------------------------------*/
39 # pragma warning (disable : 985)
41 #include "OSGBSplineCurve2D.h"
48 static char THIS_FILE
[] = __FILE__
;
52 const char BSplineCurve2D::ff_const_1
[] = "BEGINBSPLINECURVE2D";
53 const char BSplineCurve2D::ff_const_2
[] = "DIMENSION";
54 const char BSplineCurve2D::ff_const_3
[] = "NUMBEROFCONTROLPOINTS";
55 const char BSplineCurve2D::ff_const_4
[] = "BEGINRATIONALBSPLINECURVE2D";
57 int BSplineCurve2D::CheckKnotPoints(const DCTPdvector
& knots
, int dim
)
59 //now check knotvector whether it has
60 //(a,a,....a, ......., b,b,....b)
61 // |-dim+1-| |-dim+1-|
64 DCTPdvector::size_type max_index
= knots
.size() - 1;
65 double test_begin
= knots
[0], test_end
= knots
[max_index
];
67 for(DCTPdvector::size_type i
= 1; i
< static_cast<unsigned int>(dim
) + 1; ++i
)
68 if(knots
[i
] != test_begin
|| knots
[max_index
- i
] != test_end
)
69 return -1; //FIXME: double comparison ?!
74 int BSplineCurve2D::deleteBezierKnot(double k
)
76 DCTPdvector knots
= basis_function
.getKnotVector();
78 if(k
>= knots
[knots
.size() - 1])
79 return -1; // knot is too high
81 return -2; // knot is too low
83 DCTPdvector::size_type i
= 0;
91 if(mult
< dimension
+ 1)
92 return -2; // knot doesn't have enough multiplicity
95 // delete from knotvector
96 knots
.erase(knots
.begin() + i
);
97 // set new knot vector
98 basis_function
.setKnotVector(knots
);
99 // delete control point corresponding to just deleted knot
100 control_points
.erase(control_points
.begin() + i
- dimension
);
106 int BSplineCurve2D::setKnotsAndDimension(const DCTPdvector
& knots
, int dim
)
109 return -1; //invalid dimension
111 DCTPdvector::size_type max_index
= knots
.size() - 1;
113 return -2; //here's an implicit check fer structure, see below
115 if(CheckKnotPoints(knots
, dim
) )
119 if(basis_function
.setKnotVector(knots
) )
120 return -4; //error in BSplineBasisFunction.setKno...
125 void BSplineCurve2D::setControlPointVector(const DCTPVec3dvector
&cps
)
127 control_points
= cps
;
131 void BSplineCurve2D::getParameterInterval(double &minpar
, double &maxpar
)
133 basis_function
.getParameterInterval(minpar
, maxpar
);
136 //I/O facilities - FIXME: read( char *fname ), etc. missing
137 int BSplineCurve2D::read(std::istream
&infile
)
139 //FIXME: maybe we need more checks!!!
142 bool isemptyknot
= false;
145 infile
.getline(txtbuffer
, 255); //read line
146 if(strcmp(txtbuffer
, ff_const_1
) &&
147 strcmp(txtbuffer
, ff_const_4
))
149 return -1; //bad file format
151 if(!strcmp(txtbuffer
, ff_const_4
))
155 infile
>> txtbuffer
; //FIXME: error prone: too long string causes problem!!!
156 if(strcmp(txtbuffer
, ff_const_2
) )
157 return -1; //yeah, bad file format again
159 infile
>> dimension
>> std::ws
;
161 return -2; //ah, bad dimension
163 int knoterr
= basis_function
.read(infile
);
164 if(knoterr
== -3) // FIXME: hardwired val...
170 return -3; //error reading basis function
172 if(CheckKnotPoints(basis_function
.getKnotVector(), dimension
) )
175 infile
>> txtbuffer
; //FIXME: error prone: too long string causes problem!!!
176 if(strcmp(txtbuffer
, ff_const_3
) )
177 return -1; //bad file format once again
179 DCTPVec3dvector::size_type num_of_cps
;
180 infile
>> num_of_cps
>> std::ws
;
182 return -5; //too few control points
183 control_points
.resize(num_of_cps
); //FIXME: whatif not enoght memory?
185 for(DCTPdvector::size_type i
= 0; i
< num_of_cps
; ++i
)
190 infile
>> cp
[0] >> cp
[1] >> cp
[2] >> std::ws
;
194 infile
>> cp
[0] >> cp
[1] >> std::ws
;
197 control_points
[i
] = cp
; //FIXME: ya see, we need ERROR CHECKS!!!
208 int BSplineCurve2D::write(std::ostream
&outfile
)
211 DCTPdvector::size_type i
= 0;
213 for(i
= 0; i
< control_points
.size(); ++i
)
215 if(osgAbs(control_points
[i
][2] - 1.0) > DCTP_EPS
)
222 //FIXME: maybe we need more checks!!!
223 outfile
.precision(DCTP_PRECISION
);
226 outfile
<< ff_const_1
<< std::endl
;
230 outfile
<< ff_const_4
<< std::endl
;
232 outfile
<< ff_const_2
<< " " << dimension
<< std::endl
;
233 basis_function
.write(outfile
);
234 DCTPdvector::size_type num_of_cps
= control_points
.size();
235 outfile
<< ff_const_3
<< " " << num_of_cps
<< std::endl
;
237 for(i
= 0; i
< num_of_cps
; ++i
)
239 Vec3d cp
= control_points
[i
];
242 outfile
<< cp
[0] << " " << cp
[1] << std::endl
;
246 outfile
<< cp
[0] << " " << cp
[1] << " " << cp
[2] << std::endl
;
255 //some REAL functionality
256 Vec2d
BSplineCurve2D::compute(double t
, int &error
)
258 //FIXME: verification before goin' into computation!!
260 int span
= basis_function
.computeAllNonzero(t
, dimension
, pd_n
);
261 Vec2d
result(0.0, 0.0);
262 Vec3d
rat_res(0.0, 0.0, 0.0);
266 return result
; //error occured in BSplineBasisFunction.computeAll...
269 for(int i
= 0; i
<= dimension
; ++i
)
271 rat_res
= rat_res
+ control_points
[span
- dimension
+ i
] * pd_n
[i
];
275 result
[0] = rat_res
[0] / rat_res
[2];
276 result
[1] = rat_res
[1] / rat_res
[2];
280 //insert knot. Returns < 0 on error, otherwise 0.
281 int BSplineCurve2D::insertKnot(double k
)
283 DCTPdvector knots
= basis_function
.getKnotVector();
284 int span
= basis_function
.insertKnot(k
);
286 return span
; // some error happened
288 DCTPVec3dvector newcps
;
289 newcps
.resize(control_points
.size() + 1);
290 DCTPVec3dvector::size_type i
;
292 for(i
= 0; i
<= static_cast<unsigned int>(span
) - dimension
; i
++)
294 newcps
[i
] = control_points
[i
];
297 for(i
= span
- dimension
+ 1; i
<= static_cast<unsigned int>(span
); i
++)
300 if(knots
[i
+ dimension
] != knots
[i
])
302 alpha
= (k
- knots
[i
]) / (knots
[i
+ dimension
] - knots
[i
]);
308 newcps
[i
] = control_points
[i
] * alpha
+ control_points
[i
- 1] * (1 - alpha
);
311 for(i
= span
+ 1; i
< newcps
.size(); i
++)
314 newcps
[i
] = control_points
[i
- 1];
317 control_points
= newcps
;
321 int BSplineCurve2D::makeBezier(bezier2dvector
&beziers
, DCTPdvector
&pars
)
323 double firstknot
, lastknot
;
324 basis_function
.getParameterInterval(firstknot
, lastknot
);
325 DCTPdvector knots
= basis_function
.getKnotVector();
326 DCTPdvector origknots
= knots
; // backup original curve characteristics
327 DCTPVec3dvector origcps
= control_points
; // same here
328 double prevknot
= firstknot
;
333 for(i
= 1; i
< knots
.size(); i
++)
335 double actk
= knots
[i
];
340 for(int j
= mult
+ 1; j
< dimension
; j
++) //each interior knot must have the multiplicity of dimension-1
341 { //each interior knot must have the multiplicity of dimension -1
342 err
= insertKnot(prevknot
);
344 return err
; // some error happened during insertKnot
347 if(prevknot
!= firstknot
&& prevknot
!= lastknot
)
349 for(int j
= mult
; j
> dimension
- 1; j
--)
351 err
= deleteBezierKnot(prevknot
);
353 return err
; // some error happened during deleteBezierKnot
361 // now do the actual conversation into n. bezier segments
362 knots
= basis_function
.getKnotVector(); // FIXME: it could be more efficient.
363 unsigned int num_of_beziers
= (UInt32(knots
.size()) - 2) / dimension
- 1;
364 if( (num_of_beziers
* dimension
+ 2) != knots
.size() - dimension
)
366 basis_function
.setKnotVector(origknots
);
367 control_points
= origcps
;
371 beziers
.resize(num_of_beziers
);
372 pars
.resize(num_of_beziers
+ 1);
374 for(i
= 0; i
< num_of_beziers
+ 1; i
++)
375 pars
[i
] = knots
[1 + dimension
* i
];
377 DCTPVec3dvector
beziercps(dimension
+ 1);
380 bezier2dvector::size_type bezind
= 0;
381 bezier2dvector::size_type orig_num_of_beziers
= num_of_beziers
;
383 for(i
= 0; i
< orig_num_of_beziers
; i
++)
385 firstcp
= control_points
[i
* dimension
+ 0];
388 for(DCTPVec3dvector::size_type j
= 0;
389 j
< static_cast<unsigned int>(dimension
) + 1; j
++)
391 beziercps
[j
] = control_points
[i
* dimension
+ j
];
393 if(DCTPVecIsNotEqual(firstcp
, beziercps
[j
]) )
402 bezier2dvector::iterator bi
= beziers
.begin() + bezind
; // + i ???
403 DCTPdvector::iterator pi
= pars
.begin() + bezind
;
404 beziers
.erase(bi
); beziers
.resize(num_of_beziers
);
405 pars
.erase(pi
); pars
.resize(num_of_beziers
+ 1);
406 // std::cerr << "Ignoring degenerate curve... " << std::endl;
410 beziers
[bezind
++].setControlPointVector(beziercps
);
414 // restore original curve
415 basis_function
.setKnotVector(origknots
);
416 control_points
= origcps
;