https://mooseframework.inl.gov
Loading...
Searching...
No Matches
Functions
SplineUtils Namespace Reference

Utilities useful for splines in general Reference for B-Spline implementation: https://mat.fsv.cvut.cz/gcg/sbornik/prochazkova.pdf. More...

Functions

std::vector< Point > circularControlPoints (const libMesh::Point &start_point, const libMesh::Point &end_point, const libMesh::RealVectorValue &parallel_direction, const unsigned int num_cps)
 Creates control points for the special case of parallel lines using an interpolating circle.
 
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.
 
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::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.
 

Detailed Description

Utilities useful for splines in general Reference for B-Spline implementation: https://mat.fsv.cvut.cz/gcg/sbornik/prochazkova.pdf.

Function Documentation

◆ bSplineControlPoints()

std::vector< Point > SplineUtils::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.

Parameters
start_pointstart point for spline
end_pointend point for spline
start_directionincoming direction (derivative)
end_directionoutgoing direction (derivative)
cps_per_halfnumber of control points per half of the spline – will be along extrapolated line from the point and its direction
sharpnessnumber in [0,1] that determines the sharpness of the curve

Definition at line 67 of file SplineUtils.C.

74{
75 // check that start_point is different from end_point
76 if ((start_point - end_point).norm_sq() < libMesh::TOLERANCE * libMesh::TOLERANCE)
77 mooseError(caller_name + ": Start and end points must be different.");
78 // check that neither direction is the zero vector
79 if (start_direction.norm_sq() < libMesh::TOLERANCE * libMesh::TOLERANCE ||
81 mooseError(caller_name + ": Direction vectors must have a nonzero magnitude.");
82 mooseAssert(sharpness <= 1.0 && sharpness >= 0, "Sharpness must be in [0,1]!");
83
84 // check if directions are parallel, use a special case if so
85 const bool parallel = ((start_direction.cross(end_direction)).norm() < libMesh::TOLERANCE);
86 const bool aligned =
87 ((start_direction.cross(end_point - start_point)).norm() < libMesh::TOLERANCE);
88 if (parallel && !aligned)
89 {
90 // We should not revert to a circle for this case
91 if (MooseUtils::absoluteFuzzyEqual(start_direction.unit(), -end_direction.unit()))
92 mooseError(caller_name +
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;
96 if (num_cps < 30)
97 mooseWarning(caller_name +
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));
101 return SplineUtils::circularControlPoints(start_point, end_point, start_direction, num_cps);
102 }
103
104 // find closest points --> these will be identical if the extrapolated lines intersect
105 const auto closest_points_vector =
106 SplineUtils::closestPoints(start_point, end_point, start_direction, end_direction);
107 const auto & closest_point_1 = closest_points_vector.first;
108 const auto & closest_point_2 = closest_points_vector.second;
109
110 std::vector<Point> first_half = SplineUtils::controlPointsAlongLine(
111 start_point, closest_point_1, start_direction, sharpness, cps_per_half);
112 std::vector<Point> second_half = SplineUtils::controlPointsAlongLine(
113 end_point, closest_point_2, end_direction, sharpness, cps_per_half, true);
114
115 std::vector<Point> control_points;
116
117 // put it all together
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]);
122
123 return control_points;
124}
void mooseWarning(Args &&... args)
Emit a warning message with the given stringified, concatenated args.
Definition MooseError.h:345
void mooseError(Args &&... args)
Emit an error message with the given stringified, concatenated args and terminate the application.
Definition MooseError.h:311
TypeVector< typename CompareTypes< T, T2 >::supertype > cross(const TypeVector< T2 > &v) const
LIBMESH_DEVICE_INLINE TypeVector< T > unit() const
auto norm_sq() const
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 &parallel_direction, const unsigned int num_cps)
Creates control points for the special case of parallel lines using an interpolating circle.
Definition SplineUtils.C:19
static constexpr Real TOLERANCE

Referenced by Moose::BSpline::createControlPoints(), and BSplineCurveGenerator::generate().

◆ circularControlPoints()

std::vector< Point > SplineUtils::circularControlPoints ( const libMesh::Point &  start_point,
const libMesh::Point &  end_point,
const libMesh::RealVectorValue &  parallel_direction,
const unsigned int  num_cps 
)

Creates control points for the special case of parallel lines using an interpolating circle.

Parameters
start_pointstart point for spline
end_pointend point for spline
parallel_directiondirection of both curves to be connected. must be the same for both
num_cpstotal number of control points to be created

Definition at line 19 of file SplineUtils.C.

23{
24 // establish the direction vector between the two points
25 const auto orthogonal_direction = start_point - end_point;
26
27 // circular control points will only honor the derivatives if the points are colinear along the
28 // orthogonal direction
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: ",
32 start_point,
33 "\nEnd point: ",
34 end_point,
35 "\nDirection: ",
36 parallel_direction);
37
38 // define the distance between the two points
39 const auto distance_between = orthogonal_direction.norm();
40
41 // connecting circle is assumed to be between each point along the orthogonal_direction vector
42 const auto radius = distance_between / 2.0;
43
44 // normalize vectors
45 const auto unit_normal = orthogonal_direction / distance_between;
46 const auto unit_parallel = parallel_direction / parallel_direction.norm();
47
48 // calculate circle center
49 const auto center_point = end_point + radius * unit_normal;
50
51 // initialize vector of control points
52 std::vector<Point> control_points;
53
54 // loop over the number of control points to generate the 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))
57 {
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));
61 }
62
63 return control_points;
64}
const Real radius

Referenced by bSplineControlPoints().

◆ closestPoints()

std::pair< Point, Point > SplineUtils::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.

If the lines intersect, the two points returned will be identical.

Parameters
point_1starting point of the first line
point_2starting point of the second line
direction_1direction of the first line
direction_2direction of the second line

Definition at line 189 of file SplineUtils.C.

193{
194 const auto n_vec = direction_1.cross(direction_2);
195 const bool aligned = ((direction_1.cross(point_2 - point_1)).norm() < libMesh::TOLERANCE);
196
197 // check if n_vec is the zero vector (indicates parallel lines)
198 if (n_vec.norm_sq() < libMesh::TOLERANCE * libMesh::TOLERANCE)
199 {
200 if (!aligned)
201 mooseError("Lines are parallel! Infinitely many closest points exist.");
202 else
203 return std::make_pair((point_1 + point_2) / 2., (point_1 + point_2) / 2.);
204 }
205
206 const auto n1_vec = direction_1.cross(n_vec);
207 const auto n2_vec = direction_2.cross(n_vec);
208
209 // calculate closest points
210 // take absolute value to ensure specified directions are honored
211 libMesh::Real point_a_dir_scalar =
212 std::abs((point_2 - point_1) * n2_vec / (direction_1 * n2_vec));
213 libMesh::Real point_b_dir_scalar =
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;
217
218 // points will be returned as a vector containing two points
219 const auto closest_points = std::make_pair(point_a, point_b);
220
221 return closest_points;
222}
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real

Referenced by bSplineControlPoints().

◆ controlPointsAlongLine()

std::vector< Point > SplineUtils::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.

Parameters
start_pointstart point for the line
end_pointend point of the line
direction_vectordirection of the line
sharpnessnumber in [0,1] that determines the sharpness of the future curve. In this context, it will determine how close to the end point the control points are placed.
reverse_orderboolean to return the vector of control points in the reverse order

Definition at line 127 of file SplineUtils.C.

133{
134 // initialize a vector of control points with the starting point inserted
135 std::vector<Point> control_points;
136
137 mooseAssert(num_cps != 0, "Number of control points cannot be zero!");
138 if (num_cps == 1)
139 control_points.push_back(start_point);
140
141 // create the control points by varying the sharpness linearly
142 else
143 {
144 for (const auto i : libMesh::make_range(num_cps))
145 {
146 const auto point_sharpness = (Real)i / (Real)(num_cps - 1) * sharpness;
147 control_points.push_back(
148 SplineUtils::makeControlPoint(start_point, end_point, direction_vector, point_sharpness));
149 }
150
151 // reverse_order parameter only set to true when required
152 if (reverse_order)
153 std::reverse(control_points.begin(), control_points.end());
154 }
155 return control_points;
156}
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.
The following methods are specializations for using the libMesh::Parallel::packed_range_* routines fo...

Referenced by bSplineControlPoints().

◆ makeControlPoint()

libMesh::Point SplineUtils::makeControlPoint ( const libMesh::Point &  start_point,
const libMesh::Point &  end_point,
const libMesh::RealVectorValue &  direction_vector,
const libMesh::Real  sharpness 
)

Creates a control point.

Subroutine of controlPointsAlongLine

Parameters
start_pointstart point for the line
end_pointend point of the line
direction_vectordirection of the line
sharpnessnumber in [0,1] that determines the sharpness of the future curve. In this context, it will determine how close to the end point the control point is placed.

Definition at line 159 of file SplineUtils.C.

163{
164 // check that sharpness value is ok
165 mooseAssert(sharpness <= 1.0 && sharpness >= 0, "Sharpness must be in [0,1]!");
166
167 // normalize direction vector
168 const auto unit_direction = direction_vector.unit();
169
170 // calculate the distance between points
171 const auto distance = (end_point - start_point).norm();
172 const auto distance_sq = distance * distance;
173
174 // initialize return quantity and attempt to calculate control vector
175 libMesh::Point control_point = start_point + sharpness * distance * unit_direction;
176
177 // check if we went the wrong way, further from the end_point
178 if ((end_point - control_point).norm_sq() > distance_sq)
179 {
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");
183 }
184
185 return control_point;
186}
Real distance(const Point &p)

Referenced by controlPointsAlongLine().