Skip to content

Commit

Permalink
VerticesHelper: move non-template code to cpp
Browse files Browse the repository at this point in the history
  • Loading branch information
msmk0 committed Jun 30, 2020
1 parent a8cd803 commit 67ea15e
Show file tree
Hide file tree
Showing 3 changed files with 135 additions and 116 deletions.
135 changes: 19 additions & 116 deletions Core/include/Acts/Surfaces/detail/VerticesHelper.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,44 +25,10 @@ namespace VerticesHelper {
/// @param phiMax the maximum Phi of the bounds object
/// @param phiRef is a vector of reference phi values to be included as well
/// @param phiTolerance is the tolerance for reference phi insertion
///
/// @return a vector
inline std::vector<double> phiSegments(double phiMin = -M_PI,
double phiMax = M_PI,
std::vector<double> phiRefs = {},
double phiTolerance = 1e-6) {
// This is to ensure that the extrema are built regardless of number
// of segments
std::vector<double> phiSegments;
std::vector<double> quarters = {-M_PI, -0.5 * M_PI, 0., 0.5 * M_PI, M_PI};
// It does not cover the full azimuth
if (phiMin != -M_PI or phiMax != M_PI) {
phiSegments.push_back(phiMin);
for (unsigned int iq = 1; iq < 4; ++iq) {
if (phiMin < quarters[iq] and phiMax > quarters[iq]) {
phiSegments.push_back(quarters[iq]);
}
}
phiSegments.push_back(phiMax);
} else {
phiSegments = quarters;
}
// Insert the reference phis if
if (not phiRefs.empty()) {
for (const auto& phiRef : phiRefs) {
// Trying to find the right patch
auto match = std::find_if(
phiSegments.begin(), phiSegments.end(), [&](double phiSeg) {
return std::abs(phiSeg - phiRef) < phiTolerance;
});
if (match == phiSegments.end()) {
phiSegments.push_back(phiRef);
}
}
std::sort(phiSegments.begin(), phiSegments.end());
}
return phiSegments;
}
std::vector<double> phiSegments(double phiMin = -M_PI, double phiMax = M_PI,
const std::vector<double>& phiRefs = {},
double phiTolerance = 1e-6);

/// Helper method to create a regular 2 or 3 D segment
/// between two phi values
Expand Down Expand Up @@ -99,7 +65,7 @@ inline void createSegment(
}
}

/// Vertices on an ellipse-like bound object
/// Construct vertices on an ellipse-like bound object.
///
/// @param innerRx The radius of the inner ellipse (in x), 0 if sector
/// @param innerRy The radius of the inner ellipse (in y), 0 if sector
Expand All @@ -108,74 +74,27 @@ inline void createSegment(
/// @param avgPhi The phi direction of the center if sector
/// @param halfPhi The half phi sector if sector
/// @param lseg The number of segments for for a full 2*pi segment
///
/// @return a vector of 2d-vectors
inline std::vector<Vector2D> ellispoidVertices(double innerRx, double innerRy,
double outerRx, double outerRy,
double avgPhi = 0.,
double halfPhi = M_PI,
unsigned int lseg = 1) {
// List of vertices counter-clockwise starting at smallest phi w.r.t center,
// for both inner/outer ring/segment
std::vector<Acts::Vector2D> rvertices; // return vertices
std::vector<Acts::Vector2D> ivertices; // inner vertices
std::vector<Acts::Vector2D> overtices; // outer verices
std::vector<Vector2D> ellispoidVertices(double innerRx, double innerRy,
double outerRx, double outerRy,
double avgPhi = 0.,
double halfPhi = M_PI,
unsigned int lseg = 1);

bool innerExists = (innerRx > 0. and innerRy > 0.);
bool closed = std::abs(halfPhi - M_PI) < s_onSurfaceTolerance;

// Get the phi segments from the helper method
auto phiSegs = detail::VerticesHelper::phiSegments(
avgPhi - halfPhi, avgPhi + halfPhi, {avgPhi});

// The inner (if exists) and outer bow
for (unsigned int iseg = 0; iseg < phiSegs.size() - 1; ++iseg) {
int addon = (iseg == phiSegs.size() - 2 and not closed) ? 1 : 0;
if (innerExists) {
detail::VerticesHelper::createSegment<Vector2D, Transform2D>(
ivertices, {innerRx, innerRy}, phiSegs[iseg], phiSegs[iseg + 1], lseg,
addon);
}
detail::VerticesHelper::createSegment<Vector2D, Transform2D>(
overtices, {outerRx, outerRy}, phiSegs[iseg], phiSegs[iseg + 1], lseg,
addon);
}

// We want to keep the same counter-clockwise orientation for displaying
if (not innerExists) {
if (not closed) {
// Add the center case we have a sector
rvertices.push_back(Vector2D(0., 0.));
}
rvertices.insert(rvertices.end(), overtices.begin(), overtices.end());
} else if (not closed) {
rvertices.insert(rvertices.end(), overtices.begin(), overtices.end());
rvertices.insert(rvertices.end(), ivertices.rbegin(), ivertices.rend());
} else {
rvertices.insert(rvertices.end(), overtices.begin(), overtices.end());
rvertices.insert(rvertices.end(), ivertices.begin(), ivertices.end());
}
return rvertices;
}

/// Vertices on an disc/wheel-like bound object
/// Construct vertices on an disc/wheel-like bound object.
///
/// @param innerR The radius of the inner circle (sector)
/// @param outerR The radius of the outer circle (sector)
/// @param avgPhi The phi direction of the center if sector
/// @param halfPhi The half phi sector if sector
/// @param lseg The number of segments for for a full 2*pi segment
///
/// @return a vector of 2d-vectors
inline std::vector<Vector2D> circularVertices(double innerR, double outerR,
double avgPhi = 0.,
double halfPhi = M_PI,
unsigned int lseg = 1) {
return ellispoidVertices(innerR, innerR, outerR, outerR, avgPhi, halfPhi,
lseg);
}
std::vector<Vector2D> circularVertices(double innerR, double outerR,
double avgPhi = 0.,
double halfPhi = M_PI,
unsigned int lseg = 1);

/// Check if the point is inside the polygon w/o any tolerances
/// Check if the point is inside the polygon w/o any tolerances.
///
/// @tparam vertex_container_t is an iterable container
///
Expand Down Expand Up @@ -221,7 +140,7 @@ inline bool isInsidePolygon(const vertex_t& point,
return true;
}

/// Check if the point is inside the rectangle
/// Check if the point is inside the rectangle.
///
/// @tparam vertex_t is vector with [0],[1] access
///
Expand All @@ -238,29 +157,13 @@ inline bool isInsideRectangle(const vertex_t& point, const vertex_t& lowerLeft,
(lowerLeft[1] <= point[1]) && (point[1] < upperRight[1]);
}

/// This method checks if a cloud of points are on 2D hyper-plane in 3D space
/// This method checks if a cloud of points are on 2D hyper-plane in 3D space.
///
/// @param vertices The list of vertices to test
/// @param tolerance The allowed out of plane tolerance
///
/// It bails out at the first moment a point is outside the hyper plane
/// @return boolean to indicate if all points are inside/outside
inline bool onHyperPlane(const std::vector<Vector3D>& vertices,
double tolerance = s_onSurfaceTolerance) {
// Obvious always on one surface
if (vertices.size() < 4) {
return true;
}
// Create the hyperplane
auto hyperPlane = Eigen::Hyperplane<double, 3>::Through(
vertices[0], vertices[1], vertices[2]);
for (size_t ip = 3; ip < vertices.size(); ++ip) {
if (hyperPlane.absDistance(vertices[ip]) > tolerance) {
return false;
}
}
return true;
}
bool onHyperPlane(const std::vector<Vector3D>& vertices,
double tolerance = s_onSurfaceTolerance);

} // namespace VerticesHelper
} // namespace detail
Expand Down
1 change: 1 addition & 0 deletions Core/src/Surfaces/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,5 @@ target_sources_local(
SurfaceArray.cpp
TrapezoidBounds.cpp
detail/AlignmentHelper.cpp
VerticesHelper.cpp
)
115 changes: 115 additions & 0 deletions Core/src/Surfaces/VerticesHelper.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
// This file is part of the Acts project.
//
// Copyright (C) 2020 CERN for the benefit of the Acts project
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

#include "Acts/Surfaces/detail/VerticesHelper.hpp"

std::vector<double> Acts::detail::VerticesHelper::phiSegments(
double phiMin, double phiMax, const std::vector<double>& phiRefs,
double phiTolerance) {
// This is to ensure that the extrema are built regardless of number
// of segments
std::vector<double> phiSegments;
std::vector<double> quarters = {-M_PI, -0.5 * M_PI, 0., 0.5 * M_PI, M_PI};
// It does not cover the full azimuth
if (phiMin != -M_PI or phiMax != M_PI) {
phiSegments.push_back(phiMin);
for (unsigned int iq = 1; iq < 4; ++iq) {
if (phiMin < quarters[iq] and phiMax > quarters[iq]) {
phiSegments.push_back(quarters[iq]);
}
}
phiSegments.push_back(phiMax);
} else {
phiSegments = quarters;
}
// Insert the reference phis if
if (not phiRefs.empty()) {
for (const auto& phiRef : phiRefs) {
// Trying to find the right patch
auto match = std::find_if(
phiSegments.begin(), phiSegments.end(), [&](double phiSeg) {
return std::abs(phiSeg - phiRef) < phiTolerance;
});
if (match == phiSegments.end()) {
phiSegments.push_back(phiRef);
}
}
std::sort(phiSegments.begin(), phiSegments.end());
}
return phiSegments;
}

std::vector<Acts::Vector2D> Acts::detail::VerticesHelper::ellispoidVertices(
double innerRx, double innerRy, double outerRx, double outerRy,
double avgPhi, double halfPhi, unsigned int lseg) {
// List of vertices counter-clockwise starting at smallest phi w.r.t center,
// for both inner/outer ring/segment
std::vector<Vector2D> rvertices; // return vertices
std::vector<Vector2D> ivertices; // inner vertices
std::vector<Vector2D> overtices; // outer verices

bool innerExists = (innerRx > 0. and innerRy > 0.);
bool closed = std::abs(halfPhi - M_PI) < s_onSurfaceTolerance;

// Get the phi segments from the helper method
auto phiSegs = detail::VerticesHelper::phiSegments(
avgPhi - halfPhi, avgPhi + halfPhi, {avgPhi});

// The inner (if exists) and outer bow
for (unsigned int iseg = 0; iseg < phiSegs.size() - 1; ++iseg) {
int addon = (iseg == phiSegs.size() - 2 and not closed) ? 1 : 0;
if (innerExists) {
createSegment(ivertices, {innerRx, innerRy}, phiSegs[iseg],
phiSegs[iseg + 1], lseg, addon, Vector2D::Zero(),
Transform2D::Identity());
}
createSegment(overtices, {outerRx, outerRy}, phiSegs[iseg],
phiSegs[iseg + 1], lseg, addon, Vector2D::Zero(),
Transform2D::Identity());
}

// We want to keep the same counter-clockwise orientation for displaying
if (not innerExists) {
if (not closed) {
// Add the center case we have a sector
rvertices.push_back(Vector2D(0., 0.));
}
rvertices.insert(rvertices.end(), overtices.begin(), overtices.end());
} else if (not closed) {
rvertices.insert(rvertices.end(), overtices.begin(), overtices.end());
rvertices.insert(rvertices.end(), ivertices.rbegin(), ivertices.rend());
} else {
rvertices.insert(rvertices.end(), overtices.begin(), overtices.end());
rvertices.insert(rvertices.end(), ivertices.begin(), ivertices.end());
}
return rvertices;
}

std::vector<Acts::Vector2D> Acts::detail::VerticesHelper::circularVertices(
double innerR, double outerR, double avgPhi, double halfPhi,
unsigned int lseg) {
return ellispoidVertices(innerR, innerR, outerR, outerR, avgPhi, halfPhi,
lseg);
}

bool Acts::detail::VerticesHelper::onHyperPlane(
const std::vector<Acts::Vector3D>& vertices, double tolerance) {
// Obvious always on one surface
if (vertices.size() < 4) {
return true;
}
// Create the hyperplane
auto hyperPlane = Eigen::Hyperplane<double, 3>::Through(
vertices[0], vertices[1], vertices[2]);
for (size_t ip = 3; ip < vertices.size(); ++ip) {
if (hyperPlane.absDistance(vertices[ip]) > tolerance) {
return false;
}
}
return true;
}

0 comments on commit 67ea15e

Please sign in to comment.