Basic Image AlgorithmS Library  2.8.0
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
NurbsSurface.cpp
1 /*
2  * NurbsSurface.cpp
3  *
4  * Created on: Mar 8, 2010
5  * Author: bruenger
6  */
7 
8 
9 #include <iostream>
10 #ifdef BIAS_HAVE_XML2
11 #include <Base/Common/XMLIO.hh>
12 #endif
13 #include <Base/Math/Random.hh>
14 
15 //FIXME: Why is this necessary:
16 #include <Base/Common/XMLIO.hh>
17 
18 #include <MathAlgo/NurbsSurface.hh>
19 
20 using namespace std;
21 using namespace BIAS;
22 
23 NurbsSurface::NurbsSurface() {
24  initialized_ = false;
25 }
26 
27 NurbsSurface::~NurbsSurface() {
28  // TODO Auto-generated destructor stub
29 }
30 
31 void NurbsSurface::Init(int dimu, int dimv, int degree)
32 {
33  initialized_ = true;
34 
35  dimu_ = dimu;
36  dimv_ = dimv;
37  degree_ = degree;
38 
39  if(dimu_ < degree_ || dimv_ < degree_){
40  cout << "NurbsSurface::Init - The Dimensions have to be greater then the degree" << endl;
41  BIASABORT;
42  }
43 
44  knotsu_.resize(dimu_ + degree_ + 1);
45  knotsv_.resize(dimv_ + degree_ + 1);
46 
47  int i;
48 
49  ctrlpoints_.resize(dimu_);
50  for (i = 0; i < dimu_; i++){
51  ctrlpoints_[i].resize(dimv_);
52  }
53 
54  SetKnotsToDefault();
55  SetCTRLPointsToRandom(Vector2<double>(0.0,0.0),Vector2<double>(10.0,10.0));
56 }
57 
58 void NurbsSurface::SetKnotsToDefault()
59 {
60  if(!initialized_){
61  cout << "NurbsSurface::SetKnotsToDefault - Please initialize the Surface first" << endl;
62  BIASABORT;
63  }
64  double tmp;
65  for(int i = 0; i < (dimu_ + degree_ + 1); i++){
66  if(i < degree_ + 1){
67  tmp = (double)0.0;
68  }else if(i > (dimu_ - 1)){
69  tmp = (double)1.0;
70  }else{
71  tmp = (double)(1.0/(dimu_ - degree_))*(double)(i-degree_);
72  }
73  SetKnotU(i,tmp);
74  }
75 
76  for(int i = 0; i < (dimv_ + degree_ + 1); i++){
77  if(i < degree_ + 1){
78  tmp = (double)0.0;
79  }else if(i > (dimv_ - 1)){
80  tmp = (double)1.0;
81  }else{
82  tmp = (double)(1.0/(dimv_ - degree_))*(double)(i-degree_);
83  }
84  SetKnotV(i,tmp);
85  }
86 }
87 
88 
89 void NurbsSurface::SetCTRLPointsToRandom(Vector2<double> start, Vector2<double> ende)
90 {
91  if(!initialized_){
92  cout << "NurbsSurface::SetCTRLPointsToRandom - Please initialize the Surface first" << endl;
93  BIASABORT;
94  }
95 
96  Random r;
97  r.Reset();
98  SetKnotsToDefault();
99 
100  double xdiff, ydiff, xstart, ystart;
101 
102  if (start.GetX() < ende.GetX()){
103  xdiff = (ende.GetX() - start.GetX())/(dimu_ - 1);
104  xstart = start.GetX();
105  }else{
106  xdiff = (start.GetX() - ende.GetX())/(dimu_ - 1);
107  xstart = ende.GetX();
108  }
109 
110  if (start.GetY() < ende.GetY()){
111  ydiff = (ende.GetY() - start.GetY())/(dimv_ - 1);
112  ystart = start.GetY();
113  }else{
114  ydiff = (start.GetY() - ende.GetY())/(dimv_ - 1);
115  ystart = ende.GetY();
116  }
117 
118  HomgPoint3D tmp;
119  for(int x = 0; x < dimu_; x++){
120  for(int y = 0; y < dimv_; y++){
121  tmp.Set(xstart + (x*xdiff),ystart + (y*ydiff),(double)r.GetUniformDistributed(300.0, 500.0),1.0);
122  SetCtrlPoint(x,y,tmp);
123  }
124  }
125 
126 }
127 
128 #ifdef BIAS_HAVE_XML2
129 int NurbsSurface::LoadFromXML(std::string xmlfile)
130 {
131  if(initialized_){
132  cout << "NurbsSurface::LoadFromXML - Your initialization will be overwritten by the XML" << endl;
133  }
134 
135  if (xmlfile == "") {
136  cout << "NurbsSurface::LoadFromXML - No XML-File given" << endl;
137  return -1;
138  //BIASABORT;
139  }
140 
141  XMLIO myXML;
142  xmlNodePtr rootNode;
143  xmlNodePtr currentNode;
144  xmlNodePtr ctrlpointsNode;
145  xmlNodePtr currentCtrlPoint;
146 
147  rootNode = myXML.read(xmlfile);
148 
149  if (rootNode == NULL) {
150  cout << "NurbsSurface::LoadFromXML - Error while parsing XML-File" << endl;
151  BIASABORT;
152  }
153 
154  currentNode = myXML.getChild(rootNode, "dimu");
155  int dimu = myXML.getNodeContentInt(currentNode);
156  currentNode = myXML.getChild(rootNode, "dimv");
157  int dimv = myXML.getNodeContentInt(currentNode);
158  currentNode = myXML.getChild(rootNode, "degree");
159  int degree = myXML.getNodeContentInt(currentNode);
160 
161 
162  Init(dimu,dimv,degree);
163 
164 
165  ctrlpointsNode = myXML.getChild(rootNode, "ctrlpoints");
166  currentCtrlPoint = myXML.getFirstChild(ctrlpointsNode);
167 
168  HomgPoint3D vec;
169 
170  for (int i = 0; i < dimu_; i++){
171  for (int j = 0; j < dimv_; j++){
172  vec.Set((double)myXML.getAttributeValueDouble(currentCtrlPoint,"x"),(double)myXML.getAttributeValueDouble(currentCtrlPoint,"y"),(double)myXML.getAttributeValueDouble(currentCtrlPoint,"z"), 1.0);
173  SetCtrlPoint(i,j,vec);
174  currentCtrlPoint = myXML.getNextChild();
175  }
176  }
177  return 0;
178 }
179 
180 
181 void NurbsSurface::SaveToXML(std::string xmlfile)
182 {
183 
184  if(!initialized_){
185  cout << "NurbsSurface::SaveToXML - Cannot save uninitialized NURBS surface" << endl;
186  }
187 
188  if (xmlfile == "") {
189  cout << "NurbsSurface::SaveToXML - No XML-File given" << endl;
190  BIASABORT;
191  }
192 
193  XMLIO myXML;
194  xmlNodePtr rootNode;
195  //xmlNodePtr currentNode;
196  xmlNodePtr ctrlpointsNode;
197  xmlNodePtr currentCtrlPoint;
198 
199  myXML.create("Surface");
200  rootNode = myXML.getRootNode();
201  myXML.addContent(myXML.addChildNode(rootNode,"dimu"),dimu_);
202  myXML.addContent(myXML.addChildNode(rootNode,"dimv"),dimv_);
203  myXML.addContent(myXML.addChildNode(rootNode,"degree"),degree_);
204  //(myXML.getChild(rootNode,"dimu"))->addContent(dimu);
205  //(myXML.getChild(rootNode,"dimv"))->addContent(dimv);
206  //(myXML.getChild(rootNode,"degree"))->addContent(degree);
207 
208  myXML.addChildNode(rootNode, "ctrlpoints");
209 
210  ctrlpointsNode = myXML.getChild(rootNode, "ctrlpoints");
211  //currentCtrlPoint = myXML.getFirstChild(ctrlpointsNode);
212 
213 
214  for (int i = 0; i < dimu_; i++){
215  for (int j = 0; j < dimv_; j++){
216  currentCtrlPoint = myXML.addChildNode(ctrlpointsNode,"ctrlpoint");
217  HomgPoint3D cPoint = GetCtrlPoint(i,j);
218  myXML.addAttribute(currentCtrlPoint,"x",cPoint[0]);
219  myXML.addAttribute(currentCtrlPoint,"y",cPoint[1]);
220  myXML.addAttribute(currentCtrlPoint,"z",cPoint[2]);
221  //vec.Set((double)myXML.getAttributeValueDouble(currentCtrlPoint,"x"),(double)myXML.getAttributeValueDouble(currentCtrlPoint,"y"),(double)myXML.getAttributeValueDouble(currentCtrlPoint,"z"), 1.0);
222  //SetCtrlPoint(i,j,vec);
223  //currentCtrlPoint = myXML.getNextChild();
224  }
225  }
226 
227  myXML.write(xmlfile);
228 
229 }
230 
231 void NurbsSurface::LoadFromXMLWeighted(std::string xmlfile,float weight){
232  HomgPoint3D* oldCtrlPoints = new HomgPoint3D[dimu_*dimv_];
233  for (int u = 0; u < dimu_; u++){
234  for (int v = 0; v < dimv_; v++){
235  oldCtrlPoints[u+v*dimu_] = GetCtrlPoint(u,v);
236  }
237  }
238  LoadFromXML(xmlfile);
239 
240  for (int u = 0; u < dimu_; u++){
241  for (int v = 0; v < dimv_; v++){
242  HomgPoint3D pNew = GetCtrlPoint(u,v);
243  pNew[0] = pNew[0] * (weight) + oldCtrlPoints[u+v*dimu_][0] * (1.0 - weight);
244  pNew[1] = pNew[1] * (weight) + oldCtrlPoints[u+v*dimu_][1] * (1.0 - weight);
245  pNew[2] = pNew[2] * (weight) + oldCtrlPoints[u+v*dimu_][2] * (1.0 - weight);
246  SetCtrlPoint(u,v,pNew);
247  }
248  }
249 
250 
251 }
252 
253 #endif
254 
255 int NurbsSurface::FindSpan(int n, int p, double u, std::vector<double> U){
256  if(u == U[n+1]) return n;
257  int low = p;
258  int high = n+1;
259  int mid = (low+high)/2;
260  while(u < U[mid] || u >= U[mid+1]){
261  if(u < U[mid])
262  high = mid;
263  else
264  low = mid;
265  mid= (low+high)/2;
266  }
267  return mid;
268 }
269 
270 std::vector<double> NurbsSurface::BasisFuns(int i, double u, int p, std::vector<double> U){
271  std::vector<double> N, left, right;
272  N.resize(p+1);
273  left.resize(p+1);
274  right.resize(p+1);
275  double temp, saved;
276  N[0] = 1.0f;
277  for(int j = 1; j <= p; j++){
278  left[j] = u-U[i+1-j];
279  right[j] = U[i+j]-u;
280  saved = 0.0f;
281  for(int r = 0; r < j; r++){
282  temp = N[r]/(right[r+1]+left[j-r]);
283  N[r] = saved+right[r+1]*temp;
284  saved = left[j-r]*temp;
285  }
286  N[j] = saved;
287  }
288 
289  return N;
290 }
291 
292 
293 Vector3<double> NurbsSurface::GetSurfacePoint(double u, double v){
294  if(u == 1.0){
295  u = 0.999f;
296  }
297  if(v == 1.0){
298  v = 0.999f;
299  }
300  int uspan = FindSpan(dimu_,degree_,u,knotsu_);
301  std::vector<double> Nu = BasisFuns(uspan,u,degree_,knotsu_);
302  int vspan = FindSpan(dimv_,degree_,v,knotsv_);
303  std::vector<double> Nv = BasisFuns(vspan,v,degree_,knotsv_);
304  int uind = uspan - degree_;
305  Vector3<double> temp, S;
306  S.SetZero();
307 
308  for(int l = 0; l <= degree_; l++){
309  temp.SetZero();
310  int vind = vspan-degree_+l;
311  for(int k = 0; k <= degree_; k++){
312  double* ptr = GetCtrlPoint(uind+k,vind).GetData();
313  temp[0] += Nu[k] * ptr[0];
314  temp[1] += Nu[k] * ptr[1];
315  temp[2] += Nu[k] * ptr[2];
316  }
317  S.Set(S.GetData()[0] + Nv[l]*temp[0],S.GetData()[1] + Nv[l]*temp[1],S.GetData()[2] + Nv[l]*temp[2]);
318  }
319  return S;
320 }
321 
void addAttribute(const xmlNodePtr Node, const std::string &AttributeName, bool AttributeValue)
Add an attribute to a node.
Definition: XMLIO.cpp:156
void Set(const T *pv)
copy the array of vectorsize beginning at *T to this-&gt;data_
Definition: Vector3.hh:532
const T * GetData() const
get the data pointer the member function itself is const (before {..}) because it doesn&#39;t change the ...
Definition: Vector3.hh:202
xmlNodePtr getNextChild()
Get the next child of the parent specified in the last getFirstChild() call, the class remembers the ...
Definition: XMLIO.cpp:466
int write(const std::string &Filename, bool AutoAddCompressionSuffix=true) const
Write the whole tree that was constructed in memory to disk.
Definition: XMLIO.cpp:379
xmlNodePtr read(const std::string &Filename)
Read and parse an XML file from disk, DtD validation is not yet implemented.
Definition: XMLIO.cpp:416
xmlNodePtr getChild(const xmlNodePtr ParentNode, const std::string &ChildName)
Get a child of a Parent node by specifying the childs name, NULL is returned if the ParentNode has no...
Definition: XMLIO.cpp:489
void Set(const HOMGPOINT3D_TYPE &x, const HOMGPOINT3D_TYPE &y, const HOMGPOINT3D_TYPE &z)
set elementwise with given 3 euclidean scalar values.
Definition: HomgPoint3D.hh:321
xmlNodePtr create(const std::string &RootNodeName)
Create the base of a new XML-Tree in memory, already with a one and only root node.
Definition: XMLIO.cpp:88
void SetZero()
set all values to 0
Definition: Vector3.hh:559
double GetUniformDistributed(const double min, const double max)
on succesive calls return uniform distributed random variable between min and max ...
Definition: Random.hh:84
void addContent(const xmlNodePtr Node, const std::string &Content)
Add content to a node.
Definition: XMLIO.cpp:254
Wrapper class for reading and writing XML files based on the XML library libxml2. ...
Definition: XMLIO.hh:72
xmlNodePtr addChildNode(const xmlNodePtr ParentNode, const std::string &NewNodeName)
Add a child node to an incoming node with the given name.
Definition: XMLIO.cpp:131
xmlNodePtr getFirstChild(const xmlNodePtr ParentNode)
Get the first child of a given parent, or NULL for no childs.
Definition: XMLIO.cpp:452
class HomgPoint3D describes a point with 3 degrees of freedom in projective coordinates.
Definition: HomgPoint3D.hh:61
T & GetY()
Definition: Vector2.hh:292
T & GetX()
read only access functions to use names instead of indizes
Definition: Vector2.hh:289
double getAttributeValueDouble(const xmlAttrPtr Attribute) const
Definition: XMLIO.cpp:736
void Reset()
calls srand() with a seed generated from system call time, also initializes some other variables ...
Definition: Random.cpp:113
xmlNodePtr getRootNode()
Definition: XMLIO.hh:306
int getNodeContentInt(const xmlNodePtr Node) const
Definition: XMLIO.cpp:579
class for producing random numbers from different distributions
Definition: Random.hh:51