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)
 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 
)

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.

73{
74 // check that start_point is different from end_point
75 if ((start_point - end_point).norm_sq() < libMesh::TOLERANCE * libMesh::TOLERANCE)
76 mooseError("Start and end points must be different.");
77 // check that neither direction is the zero vector
78 if (start_direction.norm_sq() < libMesh::TOLERANCE * libMesh::TOLERANCE ||
80 mooseError("Direction vectors must have a nonzero magnitude.");
81 mooseAssert(sharpness <= 1.0 && sharpness >= 0, "Sharpness must be in [0,1]!");
82
83 // check if directions are parallel, use a special case if so
84 const bool parallel = ((start_direction.cross(end_direction)).norm() < libMesh::TOLERANCE);
85 if (parallel)
86 {
87 // We should not revert to a circle for this case
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;
92 if (num_cps < 30)
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));
96 return SplineUtils::circularControlPoints(start_point, end_point, start_direction, num_cps);
97 }
98
99 // find closest points --> these will be identical if the extrapolated lines intersect
100 const auto closest_points_vector =
101 SplineUtils::closestPoints(start_point, end_point, start_direction, end_direction);
102 const auto & closest_point_1 = closest_points_vector.first;
103 const auto & closest_point_2 = closest_points_vector.second;
104
105 std::vector<Point> first_half = SplineUtils::controlPointsAlongLine(
106 start_point, closest_point_1, start_direction, sharpness, cps_per_half);
107 std::vector<Point> second_half = SplineUtils::controlPointsAlongLine(
108 end_point, closest_point_2, end_direction, sharpness, cps_per_half, true);
109
110 std::vector<Point> control_points;
111
112 // put it all together
113 for (const auto i : index_range(first_half))
114 control_points.push_back(first_half[i]);
115 for (const auto i : index_range(second_half))
116 control_points.push_back(second_half[i]);
117
118 return control_points;
119}
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
auto norm_sq() const
TypeVector< typename CompareTypes< T, T2 >::supertype > cross(const TypeVector< T2 > &v) const
TypeVector< T > unit() 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 184 of file SplineUtils.C.

188{
189 const auto n_vec = direction_1.cross(direction_2);
190
191 // check if n_vec is the zero vector (indicates parallel lines)
192 if (n_vec.norm_sq() < libMesh::TOLERANCE * libMesh::TOLERANCE)
193 mooseError("Lines are parallel! Infinitely many closest points exist.");
194
195 const auto n1_vec = direction_1.cross(n_vec);
196 const auto n2_vec = direction_2.cross(n_vec);
197
198 // calculate closest points
199 // take absolute value to ensure specified directions are honored
200 libMesh::Real point_a_dir_scalar =
201 std::abs((point_2 - point_1) * n2_vec / (direction_1 * n2_vec));
202 libMesh::Real point_b_dir_scalar =
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;
206
207 // points will be returned as a vector containing two points
208 const auto closest_points = std::make_pair(point_a, point_b);
209
210 return closest_points;
211}
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 122 of file SplineUtils.C.

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

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

Referenced by controlPointsAlongLine().