Skip to content

Commit 35e72d1

Browse files
committed
Add support curved scan path when using five-axis
1 parent a2e3a41 commit 35e72d1

7 files changed

Lines changed: 111 additions & 16 deletions

File tree

source/ElectronBeamHeatSource.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ void ElectronBeamHeatSource<dim>::update_time(double time)
2828
this->_scan_path.get_power_modifier(time);
2929
this->_source_on = (segment_power_modifier > 0.0);
3030
dealii::Point<3> const &path = this->_scan_path.value(time);
31-
_quaternion = this->_scan_path.get_current_quaternion();
31+
_quaternion = this->_scan_path.get_quaternion(time);
3232
// Copy the scalar value of path to the vectorized data type
3333
for (unsigned int d = 0; d < 3; ++d)
3434
{

source/GoldakHeatSource.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ void GoldakHeatSource<dim>::update_time(double time)
2828
this->_scan_path.get_power_modifier(time);
2929
this->_source_on = (segment_power_modifier > 0.0);
3030
dealii::Point<3> const &path = this->_scan_path.value(time);
31-
_quaternion = this->_scan_path.get_current_quaternion();
31+
_quaternion = this->_scan_path.get_quaternion(time);
3232
// Copy the scalar value of path to the vectorized data type
3333
for (unsigned int d = 0; d < 3; ++d)
3434
{

source/ScanPath.cc

Lines changed: 49 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -196,24 +196,27 @@ void ScanPath::load_event_series_scan_path()
196196

197197
void ScanPath::update_current_segment_info(
198198
double time, bool save_segment, unsigned int &current_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,52 @@ 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+
interpolated_rotation /= segment_start_rotation;
329+
interpolated_rotation.pow((time - segment_start_time) / duration);
330+
interpolated_rotation *= segment_start_rotation;
331+
332+
return interpolated_rotation;
294333
}
295334

296335
std::vector<ScanPathSegment> ScanPath::get_segment_list() const

source/ScanPath.hh

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -97,9 +97,10 @@ public:
9797
dealii::Point<3> const &point) const;
9898

9999
/**
100-
* Return the quaternion associated with the current segment.
100+
* Return the quaternion at the given @p time. The quaternion is interpolated
101+
* linearly (Slerp) between the start and the end of the segment.
101102
*/
102-
Quaternion get_current_quaternion() const;
103+
Quaternion get_quaternion(double const time) const;
103104

104105
/**
105106
* Return the scan path's list of segments
@@ -138,7 +139,8 @@ private:
138139
void update_current_segment_info(double time, bool save_segment,
139140
unsigned int &current_segment,
140141
dealii::Point<3> &segment_start_point,
141-
double &segment_start_time) const;
142+
double &segment_start_time,
143+
Quaternion &segment_start_rotation) const;
142144

143145
/**
144146
* Flag is true if we have reached the end of _scan_path_file.

tests/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,7 @@ adamantine_COPY_DATA_FILE(raytracing_experimental_data_0_0.csv)
116116
adamantine_COPY_DATA_FILE(raytracing_non_AA_cells-0-0.csv)
117117
adamantine_COPY_DATA_FILE(scan_path.txt)
118118
adamantine_COPY_DATA_FILE(scan_path_5_axis.txt)
119+
adamantine_COPY_DATA_FILE(scan_path_arcs.txt)
119120
adamantine_COPY_DATA_FILE(scan_path_diagonal.txt)
120121
adamantine_COPY_DATA_FILE(scan_path_event_series.inp)
121122
adamantine_COPY_DATA_FILE(scan_path_L.txt)

tests/data/scan_path_arcs.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
0.1, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0
2+
1.0, 0.5, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0
3+
2.0, 0.5, 0.0, 0.0, 0.70710678118, 0.0, 0.70710678118, 0.0, 1.0
4+
3.0, 1.0, 0.0, 0.0, 0.70710678118, 0.70710678118, 0.0, 0.0, 1.0

tests/test_scan_path.cc

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* SPDX-FileCopyrightText: Copyright (c) 2016 - 2021, the adamantine authors.
1+
/* SPDX-FileCopyrightText: Copyright (c) 2016 - 2026, the adamantine authors.
22
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
33
*/
44

@@ -103,4 +103,53 @@ BOOST_AUTO_TEST_CASE(scan_path_location, *utf::tolerance(1e-10))
103103
BOOST_TEST(power == 0.0);
104104
}
105105

106+
BOOST_AUTO_TEST_CASE(five_axis, *utf::tolerance(1e-9))
107+
{
108+
boost::optional<boost::property_tree::ptree const &> units_optional_database;
109+
ScanPath scan_path("scan_path_arcs.txt", "event_series",
110+
units_optional_database);
111+
112+
double time = 0.5;
113+
auto p = scan_path.value(time);
114+
auto rotated_p = scan_path.rotate(time, p);
115+
BOOST_TEST(rotated_p[0] == 0.2222222222);
116+
BOOST_TEST(rotated_p[1] == 0.0);
117+
BOOST_TEST(rotated_p[2] == 0.0);
118+
119+
time = 1.0;
120+
p = scan_path.value(time);
121+
rotated_p = scan_path.rotate(time, p);
122+
BOOST_TEST(rotated_p[0] == 0.5);
123+
BOOST_TEST(rotated_p[1] == 0.0);
124+
BOOST_TEST(rotated_p[2] == 0.0);
125+
126+
time = 1.5;
127+
p = scan_path.value(time);
128+
rotated_p = scan_path.rotate(time, p);
129+
BOOST_TEST(rotated_p[0] == 0.35355339059327373);
130+
BOOST_TEST(rotated_p[1] == 0.0);
131+
BOOST_TEST(rotated_p[2] == -0.35355339059327373);
132+
133+
time = 2.0;
134+
p = scan_path.value(time);
135+
rotated_p = scan_path.rotate(time, p);
136+
BOOST_TEST(rotated_p[0] == 0.0);
137+
BOOST_TEST(rotated_p[1] == 0.0);
138+
BOOST_TEST(rotated_p[2] == -0.5);
139+
140+
time = 2.5;
141+
p = scan_path.value(time);
142+
rotated_p = scan_path.rotate(time, p);
143+
BOOST_TEST(rotated_p[0] == 0.5);
144+
BOOST_TEST(rotated_p[1] == 0.25);
145+
BOOST_TEST(rotated_p[2] == -0.5);
146+
147+
time = 3.0;
148+
p = scan_path.value(time);
149+
rotated_p = scan_path.rotate(time, p);
150+
BOOST_TEST(rotated_p[0] == 1.0);
151+
BOOST_TEST(rotated_p[1] == 0.0);
152+
BOOST_TEST(rotated_p[2] == 0.0);
153+
}
154+
106155
} // namespace adamantine

0 commit comments

Comments
 (0)