Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/orxonox/trunk/src/lib/math/curve.cc @ 4539

Last change on this file since 4539 was 4472, checked in by bensch, 19 years ago

orxonox/trunk: curve doxygen, and redesign

File size: 6.5 KB
Line 
1/*
2   orxonox - the future of 3D-vertical-scrollers
3
4   Copyright (C) 2004 orx
5
6   This program is free software; you can redistribute it and/or modify
7   it under the terms of the GNU General Public License as published by
8   the Free Software Foundation; either version 2, or (at your option)
9   any later version.
10
11   ### File Specific:
12   main-programmer: Benjamin Grauer
13   co-programmer: Patrick Boenzli
14
15   ADD: Patrick Boenzli           B-Spline
16
17
18   TODO:
19     local-Time implementation
20     NURBS
21     tList implementation
22     
23*/
24
25#define DEBUG_SPECIAL_MODULE DEBUG_MODULE_MATH
26
27#include "curve.h"
28
29#include "debug.h"
30
31#include <math.h>
32#include <stdio.h>
33
34
35/**
36    \brief default constructor for a Curve
37*/
38Curve::Curve(void)
39{
40  nodeCount = 0;
41  firstNode = new PathNode;
42  currentNode = firstNode;
43
44  firstNode->position = Vector (.0, .0, .0);
45  firstNode->number = 0;
46  firstNode->next = 0; // not sure if this really points to NULL!!
47}
48
49/**
50   \brief adds a new Node to the bezier Curve
51   \param newNode a Vector to the position of the new node
52*/
53void Curve::addNode(const Vector& newNode)
54{
55  if (nodeCount != 0 )
56    {
57      currentNode = currentNode->next = new PathNode;
58    }
59  currentNode->position = newNode;
60  currentNode->next = 0;
61  currentNode->number = (++nodeCount);
62  this->rebuild();
63  return;
64}
65
66/**
67   \brief adds a new Node to the bezier Curve
68   \param newNode a Vector to the position of the new node
69   \param insertPosition after the n-th node the new node will be inserted
70*/
71void Curve::addNode(const Vector& newNode, unsigned int insertPosition)
72{
73
74  if (this->nodeCount == 0 || insertPosition > this->nodeCount)
75    return addNode(newNode);
76
77  if (insertPosition == 0)
78    insertPosition = 1;
79
80  PathNode* insNode = new PathNode;
81
82  // relinking
83  PathNode* tmpNode = this->firstNode;
84  if (insertPosition > 1)
85    {
86      while (tmpNode->next->number != insertPosition)
87        tmpNode= tmpNode->next;
88      insNode->next = tmpNode->next;
89      tmpNode->next = insNode;
90    }
91  else
92    {
93      insNode->next = this->firstNode;
94      this->firstNode = insNode;
95    }
96  // renumbering
97  insNode->number = insertPosition;
98  tmpNode = insNode->next;
99  while (tmpNode)
100    {
101      tmpNode->number++;
102      tmpNode = tmpNode->next;
103    }
104
105    // finished
106  insNode->position = newNode;
107  ++nodeCount;
108  this->rebuild();
109  return;
110}
111
112/**
113   \brief Finds a Node by its Number, and returns its Position
114   \param nodeToFind the n'th node in the List of nodes
115   \returns A Vector to the Position of the Node.
116*/
117Vector Curve::getNode(unsigned int nodeToFind)
118{
119  if (nodeToFind > this->nodeCount || nodeToFind < 0)
120    return Vector(0,0,0);
121  PathNode* tmpNode = this->firstNode;
122  for (int i = 1; i < nodeToFind; i++)
123    tmpNode = tmpNode->next;
124  return tmpNode->position;
125}
126
127/**
128   \brief Outputs information about the state of this Curve
129*/
130void Curve::debug(void)
131{
132  printf("<<-------------------------------\n");
133  printf("Curve Information:\n");
134  printf("NodeCount: %d\n", this->nodeCount);
135  PathNode* tmpNode = this->firstNode;
136  while (tmpNode)
137    {
138      printf("node #%d: %f, %f, %f\n", tmpNode->number, tmpNode->position.x, tmpNode->position.y, tmpNode->position.z);
139      tmpNode = tmpNode->next;
140    }
141  printf("------------------------------->>\n");
142}
143
144
145///////////////////////////////////
146/// Bezier Curve //////////////////
147///////////////////////////////////
148
149/**
150   \brief Creates a new BezierCurve
151*/
152BezierCurve::BezierCurve (void)
153{
154  this->derivation = 0;
155  dirCurve = new BezierCurve(1);
156}
157
158/**
159   \brief Creates a new BezierCurve-Derivation-Curve
160*/
161BezierCurve::BezierCurve (int derivation)
162{
163  this->derivation = derivation;
164  dirCurve=NULL;
165}
166
167/**
168   \brief Deletes a BezierCurve.
169
170   It does this by freeing all the space taken over from the nodes
171*/
172BezierCurve::~BezierCurve(void)
173{
174  PathNode* tmpNode;
175  currentNode = firstNode;
176  while (tmpNode != 0)
177    {
178      tmpNode = currentNode;
179      currentNode = currentNode->next;
180      delete tmpNode;
181    }
182  if (dirCurve)
183    delete dirCurve;
184}
185
186/**
187   \brief Rebuilds a Curve
188*/
189void BezierCurve::rebuild(void)
190{
191  PathNode* tmpNode = firstNode;
192
193  // rebuilding the Curve itself
194  float k=0;
195  float n = nodeCount -1;
196  float binCoef = 1;
197  while(tmpNode)
198    {
199      tmpNode->factor = binCoef;
200      if (tmpNode =tmpNode->next)
201        {
202          binCoef *=(n-k)/(k+1);
203          ++k;
204        }
205    }
206
207  // rebuilding the Derivation curve
208  if(this->derivation <= 1)
209    {
210      tmpNode = firstNode;
211      delete dirCurve;
212      dirCurve = new BezierCurve(1);
213      while(tmpNode->next)
214        {
215          Vector tmpVector = (tmpNode->next->position)- (tmpNode->position);
216          tmpVector.x*=(float)nodeCount;
217          tmpVector.y*=(float)nodeCount;
218          tmpVector.z*=(float)nodeCount;
219          tmpVector.normalize();
220          this->dirCurve->addNode(tmpVector);
221          tmpNode = tmpNode->next;
222        }
223    }
224}
225
226/**
227   \brief calculates the Position on the curve
228   \param t The position on the Curve (0<=t<=1)
229   \return the Position on the Path
230*/
231Vector BezierCurve::calcPos(float t) 
232{
233  Vector ret = Vector(0.0,0.0,0.0);
234  if (this->nodeCount >= 3)
235    {
236      PathNode* tmpNode = this->firstNode;
237      double factor = pow(1.0-t,nodeCount-1);
238      while(tmpNode)
239        {
240          ret.x += tmpNode->factor * factor * tmpNode->position.x;
241          ret.y += tmpNode->factor * factor * tmpNode->position.y;
242          ret.z += tmpNode->factor * factor * tmpNode->position.z;
243          factor *= t/(1.0-t); // same as pow but much faster.
244         
245          tmpNode = tmpNode->next;
246        }
247    }
248  else if (nodeCount == 2)
249    {
250      ret = this->firstNode->position *(1.0-t);
251      ret = ret + this->firstNode->next->position * t;
252    }
253  else if (nodeCount == 1)
254    ret = this->firstNode->position;
255  return ret;
256}
257
258/**
259   \brief Calulates the direction of the Curve at time t.
260   \param t The time at which to evaluate the curve.
261   \returns The valuated Vector.
262*/
263Vector BezierCurve::calcDir (float t)
264{
265  return this->dirCurve->calcPos(t);
266}
267
268/**
269   \brief Calulates the acceleration (second derivate) of the Curve at time t.
270   \param t The time at which to evaluate the curve.
271   \returns The valuated Vector.
272*/
273Vector BezierCurve::calcAcc (float t)
274{
275  return this->dirCurve->getDirCurve()->calcPos(t);
276}
277
278/**
279   \brief Calculates the Quaternion needed for our rotations
280   \param t The time at which to evaluate the cuve.
281   \returns The evaluated Quaternion.
282*/
283Quaternion BezierCurve::calcQuat (float t)
284{
285  return Quaternion (calcDir(t), Vector(0,0,1));
286}
287
288
289/**
290  \brief returns the Position of the point calculated on the Curve
291  \return a Vector to the calculated position
292*/
293Vector BezierCurve::getPos(void) const
294{
295  return curvePoint;
296}
Note: See TracBrowser for help on using the repository browser.