@@ -196,24 +196,27 @@ void ScanPath::load_event_series_scan_path()
196196
197197void ScanPath::update_current_segment_info (
198198 double time, bool save_segment, unsigned int ¤t_segment,
199- dealii::Point<3 > &segment_start_point, double &segment_start_time) const
199+ dealii::Point<3 > &segment_start_point, double &segment_start_time,
200+ Quaternion &segment_start_rotation) const
200201{
201202 // Get to the correct segment
202203 current_segment = _old_segment;
203204 while (time > _segment_list[current_segment].end_time )
204205 {
205206 ++current_segment;
206207 }
207- // Update the start position and time for the current segment
208+ // Update the start position, time, and rotation for the current segment
208209 if (current_segment > 0 )
209210 {
210211 segment_start_time = _segment_list[current_segment - 1 ].end_time ;
211212 segment_start_point = _segment_list[current_segment - 1 ].end_point ;
213+ segment_start_rotation = _segment_list[current_segment - 1 ].end_rotation ;
212214 }
213215 else
214216 {
215217 segment_start_time = 0.0 ;
216218 segment_start_point = _segment_list[current_segment].end_point ;
219+ segment_start_rotation = _segment_list[current_segment].end_rotation ;
217220 }
218221
219222 if (save_segment)
@@ -237,9 +240,11 @@ dealii::Point<3> ScanPath::value(double const time, bool save_segment) const
237240 // Get to the correct segment
238241 dealii::Point<3 > segment_start_point;
239242 double segment_start_time = 0.0 ;
243+ Quaternion segment_start_rotation;
240244 unsigned int current_segment = 0 ;
241245 update_current_segment_info (time, save_segment, current_segment,
242- segment_start_point, segment_start_time);
246+ segment_start_point, segment_start_time,
247+ segment_start_rotation);
243248
244249 // Calculate the position in the direction given by "component"
245250 dealii::Point<3 > position =
@@ -261,9 +266,10 @@ double ScanPath::get_power_modifier(double const time) const
261266 // Get to the correct segment
262267 dealii::Point<3 > segment_start_point;
263268 double segment_start_time = 0.0 ;
269+ Quaternion segment_start_rotation;
264270 unsigned int current_segment = 0 ;
265271 update_current_segment_info (time, true , current_segment, segment_start_point,
266- segment_start_time);
272+ segment_start_time, segment_start_rotation );
267273
268274 return _segment_list[current_segment].power_modifier ;
269275}
@@ -278,19 +284,61 @@ dealii::Point<3> ScanPath::rotate(double const time,
278284 return point;
279285 }
280286
287+ return get_quaternion (time).rotate (point);
288+ }
289+
290+ Quaternion ScanPath::get_quaternion (double const time) const
291+ {
292+ if (!_five_axis)
293+ {
294+ return Quaternion (1.0 , 0.0 , 0.0 , 0.0 );
295+ }
296+
297+ // If the current time is after the scan path data is over, return the
298+ // end rotation.
299+ if (time > _segment_list.back ().end_time )
300+ {
301+ return _segment_list.back ().end_rotation ;
302+ }
303+
281304 // Get to the correct segment
282305 dealii::Point<3 > segment_start_point;
283306 double segment_start_time = 0.0 ;
307+ Quaternion segment_start_rotation;
284308 unsigned int current_segment = 0 ;
285309 update_current_segment_info (time, false , current_segment, segment_start_point,
286- segment_start_time);
310+ segment_start_time, segment_start_rotation );
287311
288- return _segment_list[current_segment].end_rotation .rotate (point);
289- }
312+ // If the start and end rotation are the same, return the start rotation
313+ if (segment_start_rotation == _segment_list[current_segment].end_rotation )
314+ {
315+ return segment_start_rotation;
316+ }
290317
291- Quaternion ScanPath::get_current_quaternion () const
292- {
293- return _segment_list[_old_segment].end_rotation ;
318+ // Compute the interpolated rotation
319+ double const duration =
320+ _segment_list[current_segment].end_time - segment_start_time;
321+ if (duration < 1e-12 )
322+ {
323+ return _segment_list[current_segment].end_rotation ;
324+ }
325+
326+ Quaternion interpolated_rotation =
327+ _segment_list[current_segment].end_rotation ;
328+
329+ // If the dot product of the initial quaternion and the final rotation is
330+ // negative, slerp will take the long way instead of the short path. In that
331+ // case, we need to negate one of the quaternion.
332+ if (dot_product (segment_start_rotation, interpolated_rotation) < 0 .)
333+ {
334+ interpolated_rotation *= -1 .;
335+ }
336+
337+ interpolated_rotation /= segment_start_rotation;
338+ interpolated_rotation.pow ((time - segment_start_time) / duration);
339+ interpolated_rotation *= segment_start_rotation;
340+
341+ return interpolated_rotation;
294342}
295343
296344std::vector<ScanPathSegment> ScanPath::get_segment_list () const
0 commit comments