1 /*=========================================================================
2
3 Program: Visualization Toolkit
4 Module: vtkSpline.cxx
5
6 Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
7 All rights reserved.
8 See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
9
10 This software is distributed WITHOUT ANY WARRANTY; without even
11 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
12 PURPOSE. See the above copyright notice for more information.
13
14 =========================================================================*/
15 #include "vtkSpline.h"
16
17 #include "vtkPiecewiseFunction.h"
18
19 //------------------------------------------------------------------------------
20 // Construct a spline with the following defaults:
21 // ClampValueOff
vtkSpline()22 vtkSpline::vtkSpline()
23 {
24 this->ComputeTime = 0;
25 this->ClampValue = 0;
26 this->PiecewiseFunction = vtkPiecewiseFunction::New();
27 this->Intervals = nullptr;
28 this->Coefficients = nullptr;
29 this->LeftConstraint = 1;
30 this->LeftValue = 0.0;
31 this->RightConstraint = 1;
32 this->RightValue = 0.0;
33 this->Closed = 0;
34
35 this->ParametricRange[0] = -1;
36 this->ParametricRange[1] = -1;
37 }
38
39 //------------------------------------------------------------------------------
~vtkSpline()40 vtkSpline::~vtkSpline()
41 {
42 this->PiecewiseFunction->Delete();
43 delete[] this->Coefficients;
44 delete[] this->Intervals;
45 }
46
47 //------------------------------------------------------------------------------
SetParametricRange(double tMin,double tMax)48 void vtkSpline::SetParametricRange(double tMin, double tMax)
49 {
50 if (tMin != this->ParametricRange[0] || tMax != this->ParametricRange[1])
51 {
52 if (tMin >= tMax)
53 {
54 tMax = tMin + 1;
55 }
56
57 this->ParametricRange[0] = tMin;
58 this->ParametricRange[1] = tMax;
59
60 this->Modified();
61 }
62 }
63
64 //------------------------------------------------------------------------------
GetParametricRange(double tRange[2]) const65 void vtkSpline::GetParametricRange(double tRange[2]) const
66 {
67 if (this->ParametricRange[0] != this->ParametricRange[1])
68 {
69 tRange[0] = this->ParametricRange[0];
70 tRange[1] = this->ParametricRange[1];
71 }
72 else
73 {
74 tRange[0] = this->PiecewiseFunction->GetRange()[0];
75 tRange[1] = this->PiecewiseFunction->GetRange()[1];
76 }
77 }
78
79 //------------------------------------------------------------------------------
ComputeLeftDerivative()80 double vtkSpline::ComputeLeftDerivative()
81 {
82 double* dptr = this->PiecewiseFunction->GetDataPointer();
83 int size = this->PiecewiseFunction->GetSize();
84 if (dptr == nullptr || size < 2)
85 {
86 return 0.0;
87 }
88 else
89 {
90 return (dptr[2] - dptr[0]);
91 }
92 }
93
94 //------------------------------------------------------------------------------
ComputeRightDerivative()95 double vtkSpline::ComputeRightDerivative()
96 {
97 double* dptr = this->PiecewiseFunction->GetDataPointer();
98 int size = this->PiecewiseFunction->GetSize();
99 if (dptr == nullptr || size < 2)
100 {
101 return 0.0;
102 }
103 else
104 {
105 return (dptr[(size - 1) * 2] - dptr[(size - 2) * 2]);
106 }
107 }
108
109 //------------------------------------------------------------------------------
GetNumberOfPoints()110 int vtkSpline::GetNumberOfPoints()
111 {
112 return this->PiecewiseFunction->GetSize();
113 }
114
115 //------------------------------------------------------------------------------
116 // Add a point to the Piecewise Functions containing the data
AddPoint(double t,double x)117 void vtkSpline::AddPoint(double t, double x)
118 {
119 if (this->ParametricRange[0] != this->ParametricRange[1])
120 {
121 t = (t < this->ParametricRange[0]
122 ? this->ParametricRange[0]
123 : (t > this->ParametricRange[1] ? this->ParametricRange[1] : t));
124 }
125 this->PiecewiseFunction->AddPoint(t, x);
126 }
127
128 //------------------------------------------------------------------------------
129 // Remove a point from the Piecewise Functions.
RemovePoint(double t)130 void vtkSpline::RemovePoint(double t)
131 {
132 if (this->ParametricRange[0] != this->ParametricRange[1])
133 {
134 t = (t < this->ParametricRange[0]
135 ? this->ParametricRange[0]
136 : (t > this->ParametricRange[1] ? this->ParametricRange[1] : t));
137 }
138 this->PiecewiseFunction->RemovePoint(t);
139 }
140
141 //------------------------------------------------------------------------------
142 // Remove all points from the Piecewise Functions.
RemoveAllPoints()143 void vtkSpline::RemoveAllPoints()
144 {
145 this->PiecewiseFunction->RemoveAllPoints();
146 }
147
148 //------------------------------------------------------------------------------
DeepCopy(vtkSpline * s)149 void vtkSpline::DeepCopy(vtkSpline* s)
150 {
151 vtkSpline* spline = vtkSpline::SafeDownCast(s);
152
153 if (spline != nullptr)
154 {
155 this->ClampValue = s->ClampValue;
156 this->LeftConstraint = s->LeftConstraint;
157 this->LeftValue = s->LeftValue;
158 this->RightConstraint = s->RightConstraint;
159 this->RightValue = s->RightValue;
160 this->Closed = s->Closed;
161 this->PiecewiseFunction->DeepCopy(s->PiecewiseFunction);
162 }
163 }
164
165 //------------------------------------------------------------------------------
166 // Overload standard modified time function. If data is modified,
167 // then this object is modified as well.
GetMTime()168 vtkMTimeType vtkSpline::GetMTime()
169 {
170 vtkMTimeType mTime = this->vtkObject::GetMTime();
171 vtkMTimeType DataMTime;
172
173 if (this->PiecewiseFunction != nullptr)
174 {
175 DataMTime = this->PiecewiseFunction->GetMTime();
176 mTime = (DataMTime > mTime ? DataMTime : mTime);
177 }
178
179 return mTime;
180 }
181
182 //------------------------------------------------------------------------------
FindIndex(int size,double t)183 int vtkSpline::FindIndex(int size, double t)
184 {
185 int index = 0;
186 if (size > 2) // bisection method for speed
187 {
188 int rightIdx = size - 1;
189 int centerIdx = rightIdx - size / 2;
190 for (int converged = 0; !converged;)
191 {
192 if (this->Intervals[index] <= t && t <= this->Intervals[centerIdx])
193 {
194 rightIdx = centerIdx;
195 }
196 else // if ( this->Intervals[centerIdx] < t && t <= this->Intervals[rightIdx] )
197 {
198 index = centerIdx;
199 }
200 if ((index + 1) == rightIdx)
201 {
202 converged = 1;
203 }
204 else
205 {
206 centerIdx = index + (rightIdx - index) / 2;
207 }
208 } // while not converged
209 }
210 return index;
211 }
212
213 //------------------------------------------------------------------------------
PrintSelf(ostream & os,vtkIndent indent)214 void vtkSpline::PrintSelf(ostream& os, vtkIndent indent)
215 {
216 this->Superclass::PrintSelf(os, indent);
217
218 os << indent << "Clamp Value: " << (this->ClampValue ? "On\n" : "Off\n");
219 os << indent << "Left Constraint: " << this->LeftConstraint << "\n";
220 os << indent << "Right Constraint: " << this->RightConstraint << "\n";
221 os << indent << "Left Value: " << this->LeftValue << "\n";
222 os << indent << "Right Value: " << this->RightValue << "\n";
223 os << indent << "Closed: " << (this->Closed ? "On\n" : "Off\n");
224
225 os << indent << "Piecewise Function:\n";
226 this->PiecewiseFunction->PrintSelf(os, indent.GetNextIndent());
227
228 os << indent << "Closed: " << (this->Closed ? "On\n" : "Off\n");
229 }
230