22 const unsigned int num_cps)
25 const auto orthogonal_direction = start_point - end_point;
29 if (!(MooseUtils::absoluteFuzzyEqual(parallel_direction.
unit() * orthogonal_direction.
unit(), 0)))
30 mooseError(
"Parallel lines cannot be interpolated using points along a circle! Direction " 31 "vectors are incompatible with point locations.\nStart point: ",
39 const auto distance_between = orthogonal_direction.norm();
42 const auto radius = distance_between / 2.0;
45 const auto unit_normal = orthogonal_direction / distance_between;
46 const auto unit_parallel = parallel_direction / parallel_direction.
norm();
49 const auto center_point = end_point +
radius * unit_normal;
52 std::vector<Point> control_points;
55 mooseAssert(num_cps > 1,
"This routine does not support a single control point");
58 const auto t = (
Real)i / (
Real)(num_cps - 1);
59 control_points.push_back(center_point +
radius * (
std::cos(t * M_PI) * unit_normal +
60 std::sin(t * M_PI) * unit_parallel));
63 return control_points;
71 const unsigned int cps_per_half,
76 mooseError(
"Start and end points must be different.");
80 mooseError(
"Direction vectors must have a nonzero magnitude.");
81 mooseAssert(sharpness <= 1.0 && sharpness >= 0,
"Sharpness must be in [0,1]!");
88 if (MooseUtils::absoluteFuzzyEqual(start_direction.
unit(), -end_direction.
unit()))
89 mooseError(
"Start and end directions are opposite, this is not currently supported");
90 mooseWarning(
"Directions are parallel! Attempting to use circular control points...");
91 unsigned int num_cps = 2 * cps_per_half + 1;
93 mooseWarning(
"Number of control points required for circular control points is much greater " 94 "than for BSplines. Current num_cps: " +
95 std::to_string(num_cps));
100 const auto closest_points_vector =
102 const auto & closest_point_1 = closest_points_vector.first;
103 const auto & closest_point_2 = closest_points_vector.second;
106 start_point, closest_point_1, start_direction, sharpness, cps_per_half);
108 end_point, closest_point_2, end_direction, sharpness, cps_per_half,
true);
110 std::vector<Point> control_points;
114 control_points.push_back(first_half[i]);
116 control_points.push_back(second_half[i]);
118 return control_points;
126 const unsigned int num_cps,
127 const bool reverse_order)
130 std::vector<Point> control_points;
132 mooseAssert(num_cps != 0,
"Number of control points cannot be zero!");
134 control_points.push_back(start_point);
141 const auto point_sharpness = (
Real)i / (
Real)(num_cps - 1) * sharpness;
142 control_points.push_back(
148 std::reverse(control_points.begin(), control_points.end());
150 return control_points;
160 mooseAssert(sharpness <= 1.0 && sharpness >= 0,
"Sharpness must be in [0,1]!");
163 const auto unit_direction = direction_vector.
unit();
173 if ((end_point - control_point).norm_sq() > distance_sq)
175 control_point = start_point - sharpness *
distance * unit_direction;
176 mooseAssert((end_point - control_point).
norm_sq() <= distance_sq,
177 "Also going further from end point");
180 return control_point;
183 std::pair<Point, Point>
189 const auto n_vec = direction_1.
cross(direction_2);
193 mooseError(
"Lines are parallel! Infinitely many closest points exist.");
195 const auto n1_vec = direction_1.
cross(n_vec);
196 const auto n2_vec = direction_2.
cross(n_vec);
201 std::abs((point_2 - point_1) * n2_vec / (direction_1 * n2_vec));
203 std::abs((point_1 - point_2) * n1_vec / (direction_2 * n1_vec));
204 libMesh::Point point_a = point_1 + point_a_dir_scalar * direction_1;
205 libMesh::Point point_b = point_2 + point_b_dir_scalar * direction_2;
208 const auto closest_points = std::make_pair(point_a, point_b);
210 return closest_points;
MetaPhysicL::DualNumber< V, D, asd > abs(const MetaPhysicL::DualNumber< V, D, asd > &a)
CTSub CT_OPERATOR_BINARY CTMul CTCompareLess CTCompareGreater CTCompareEqual _arg template * sin(_arg) *_arg.template D< dtag >()) CT_SIMPLE_UNARY_FUNCTION(tan
void mooseError(Args &&... args)
Emit an error message with the given stringified, concatenated args and terminate the application...
static constexpr Real TOLERANCE
void mooseWarning(Args &&... args)
Emit a warning message with the given stringified, concatenated args.
std::vector< Point > controlPointsAlongLine(const libMesh::Point &start_point, const libMesh::Point &end_point, const libMesh::RealVectorValue &direction_vector, const libMesh::Real sharpness, const unsigned int num_cps, const bool reverse_order=false)
Creates control points along an extrapolated line up to a certain intercept.
Real distance(const Point &p)
Utilities useful for splines in general Reference for B-Spline implementation: https://mat.fsv.cvut.cz/gcg/sbornik/prochazkova.pdf.
TypeVector< Real > unit() const
CTSub CT_OPERATOR_BINARY CTMul CTCompareLess CTCompareGreater CTCompareEqual _arg template cos(_arg) *_arg.template D< dtag >()) CT_SIMPLE_UNARY_FUNCTION(cos
std::pair< Point, Point > closestPoints(const libMesh::Point &point_1, const libMesh::Point &point_2, const libMesh::RealVectorValue &direction_1, const libMesh::RealVectorValue &direction_2)
Determines the two points defining the shortest line segment between two lines in space...
TypeVector< typename CompareTypes< Real, T2 >::supertype > cross(const TypeVector< T2 > &v) const
libMesh::Point makeControlPoint(const libMesh::Point &start_point, const libMesh::Point &end_point, const libMesh::RealVectorValue &direction_vector, const libMesh::Real sharpness)
Creates a control point.
std::vector< Point > bSplineControlPoints(const libMesh::Point &start_point, const libMesh::Point &end_point, const libMesh::RealVectorValue &start_direction, const libMesh::RealVectorValue &end_direction, const unsigned int cps_per_half, const libMesh::Real sharpness)
Creates control points for an open uniform BSpline.
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
IntRange< T > make_range(T beg, T end)
std::vector< Point > circularControlPoints(const libMesh::Point &start_point, const libMesh::Point &end_point, const libMesh::RealVectorValue ¶llel_direction, const unsigned int num_cps)
Creates control points for the special case of parallel lines using an interpolating circle...
auto index_range(const T &sizable)