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");
56 for (
const auto i : make_range(num_cps))
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,
73 const std::string & caller_name)
77 mooseError(caller_name +
": Start and end points must be different.");
81 mooseError(caller_name +
": Direction vectors must have a nonzero magnitude.");
82 mooseAssert(sharpness <= 1.0 && sharpness >= 0,
"Sharpness must be in [0,1]!");
88 if (parallel && !aligned)
91 if (MooseUtils::absoluteFuzzyEqual(start_direction.
unit(), -end_direction.
unit()))
93 ": Start and end directions are opposite, this is not currently supported");
94 mooseWarning(
"Directions are parallel! Attempting to use circular control points...");
95 unsigned int num_cps = 2 * cps_per_half + 1;
98 ": Number of control points required for circular control points "
99 "is much greater than for BSplines. Current num_cps: " +
100 std::to_string(num_cps));
105 const auto closest_points_vector =
107 const auto & closest_point_1 = closest_points_vector.first;
108 const auto & closest_point_2 = closest_points_vector.second;
111 start_point, closest_point_1, start_direction, sharpness, cps_per_half);
113 end_point, closest_point_2, end_direction, sharpness, cps_per_half,
true);
115 std::vector<Point> control_points;
118 for (
const auto i : index_range(first_half))
119 control_points.push_back(first_half[i]);
120 for (
const auto i : index_range(second_half))
121 control_points.push_back(second_half[i]);
123 return control_points;
131 const unsigned int num_cps,
132 const bool reverse_order)
135 std::vector<Point> control_points;
137 mooseAssert(num_cps != 0,
"Number of control points cannot be zero!");
139 control_points.push_back(start_point);
146 const auto point_sharpness = (Real)i / (Real)(num_cps - 1) * sharpness;
147 control_points.push_back(
153 std::reverse(control_points.begin(), control_points.end());
155 return control_points;
165 mooseAssert(sharpness <= 1.0 && sharpness >= 0,
"Sharpness must be in [0,1]!");
168 const auto unit_direction = direction_vector.
unit();
171 const auto distance = (end_point - start_point).norm();
178 if ((end_point - control_point).norm_sq() > distance_sq)
180 control_point = start_point - sharpness *
distance * unit_direction;
181 mooseAssert((end_point - control_point).norm_sq() <= distance_sq,
182 "Also going further from end point");
185 return control_point;
188std::pair<Point, Point>
194 const auto n_vec = direction_1.
cross(direction_2);
201 mooseError(
"Lines are parallel! Infinitely many closest points exist.");
203 return std::make_pair((point_1 + point_2) / 2., (point_1 + point_2) / 2.);
206 const auto n1_vec = direction_1.
cross(n_vec);
207 const auto n2_vec = direction_2.
cross(n_vec);
212 std::abs((point_2 - point_1) * n2_vec / (direction_1 * n2_vec));
214 std::abs((point_1 - point_2) * n1_vec / (direction_2 * n1_vec));
215 libMesh::Point point_a = point_1 + point_a_dir_scalar * direction_1;
216 libMesh::Point point_b = point_2 + point_b_dir_scalar * direction_2;
219 const auto closest_points = std::make_pair(point_a, point_b);
221 return closest_points;
void mooseWarning(Args &&... args)
Emit a warning message with the given stringified, concatenated args.
void mooseError(Args &&... args)
Emit an error message with the given stringified, concatenated args and terminate the application.
TypeVector< typename CompareTypes< T, T2 >::supertype > cross(const TypeVector< T2 > &v) const
LIBMESH_DEVICE_INLINE TypeVector< T > unit() const
Utilities useful for splines in general Reference for B-Spline implementation: https://mat....
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, const std::string &caller_name)
Creates control points for an open uniform BSpline.
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.
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.
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.
static constexpr Real TOLERANCE
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
IntRange< T > make_range(T beg, T end)
Real distance(const Point &p)