51 template <
typename spacepo
int_iterator_t>
53 spacepoint_iterator_t spBegin, spacepoint_iterator_t spEnd,
58 ACTS_ERROR(
"At least three space points are required.")
68 for (spacepoint_iterator_t
it = spBegin;
it != spEnd;
it++) {
70 ACTS_ERROR(
"Empty space point found. This should not happen.")
107 ActsScalar q2 = Cr2r2 * (Cxx - Cyy) - Cxr2 * Cxr2 + Cyr2 * Cyr2;
110 ActsScalar k = (std::sin(phi) * Cxr2 - std::cos(phi) * Cyr2) * (1. / Cr2r2);
154 template <
typename spacepo
int_iterator_t>
163 ACTS_ERROR(
"There should be exactly three space points provided.")
171 if (bFieldInTesla < bFieldMinInTesla) {
174 ACTS_WARNING(
"The magnetic field at the bottom space point: B = "
175 << bFieldInTesla <<
" T is smaller than |B|_min = "
176 << bFieldMinInTesla <<
" T. Estimation is not performed.")
181 std::array<Vector3, 3> spGlobalPositions = {Vector3::Zero(), Vector3::Zero(),
185 for (
size_t isp = 0; isp < 3; ++isp) {
186 spacepoint_iterator_t
it =
std::next(spBegin, isp);
187 if (*it ==
nullptr) {
188 ACTS_ERROR(
"Empty space point found. This should not happen.")
191 const auto& sp = *
it;
192 spGlobalPositions[isp] =
Vector3(sp->x(), sp->y(), sp->z());
200 Vector3 relVec = spGlobalPositions[1] - spGlobalPositions[0];
201 Vector3 newZAxis = bField.normalized();
202 Vector3 newYAxis = newZAxis.cross(relVec).normalized();
203 Vector3 newXAxis = newYAxis.cross(newZAxis);
205 rotation.col(0) = newXAxis;
206 rotation.col(1) = newYAxis;
207 rotation.col(2) = newZAxis;
214 Vector3 local1 = transform.inverse() * spGlobalPositions[1];
215 Vector3 local2 = transform.inverse() * spGlobalPositions[2];
220 ActsScalar denominator = local.x() * local.x() + local.y() * local.y();
221 uv.x() = local.x() / denominator;
222 uv.y() = local.y() / denominator;
226 Vector2 uv1 = uvTransform(local1);
227 Vector2 uv2 = uvTransform(local2);
231 ActsScalar A = (uv2.y() - uv1.y()) / (uv2.x() - uv1.x());
237 ActsScalar rn = local2.x() * local2.x() + local2.y() * local2.y();
241 local2.z() * std::sqrt(1. / rn) / (1. + G * rho * rho * rn);
244 Vector3 transDirection(1., A, std::hypot(1, A) * invTanTheta);
246 Vector3 direction = rotation * transDirection.normalized();
257 auto lpResult = surface.
globalToLocal(gctx, spGlobalPositions[0], direction);
258 if (not lpResult.ok()) {
260 "Global to local transformation did not succeed. Please make sure the "
261 "bottom space point lies on the provided surface.");
264 Vector2 bottomLocalPos = lpResult.value();
273 params[
eBoundQOverP] = qOverPt / std::hypot(1., invTanTheta);
278 ActsScalar pzInGeV = 1.0 / std::abs(qOverPt) * invTanTheta;
282 ActsScalar v = pInGeV / std::hypot(pInGeV, massInGeV);
283 ActsScalar vz = pzInGeV / std::hypot(pInGeV, massInGeV);
286 ActsScalar pathz = spGlobalPositions[0].dot(bField) / bField.norm();
289 if (pathz != 0 && vz != 0) {
292 params[
eBoundTime] = spGlobalPositions[0].norm() /
v;
295 if (params.hasNaN()) {
297 "The NaN value exists at the estimated track parameters from seed with"
298 <<
"\nbottom sp: " << spGlobalPositions[0] <<
"\nmiddle sp: "
299 << spGlobalPositions[1] <<
"\ntop sp: " << spGlobalPositions[2]);