Flutter Impeller
impeller::CubicPathComponent Struct Reference

#include <path_component.h>

Public Types

using PointProc = std::function< void(const Point &point)>
 

Public Member Functions

 CubicPathComponent ()
 
 CubicPathComponent (const QuadraticPathComponent &q)
 
 CubicPathComponent (Point ap1, Point acp1, Point acp2, Point ap2)
 
Point Solve (Scalar time) const
 
Point SolveDerivative (Scalar time) const
 
void AppendPolylinePoints (Scalar scale, std::vector< Point > &points) const
 
std::vector< PointExtrema () const
 
void ToLinearPathComponents (Scalar scale, const PointProc &proc) const
 
CubicPathComponent Subsegment (Scalar t0, Scalar t1) const
 
bool operator== (const CubicPathComponent &other) const
 
std::optional< Vector2GetStartDirection () const
 
std::optional< Vector2GetEndDirection () const
 

Public Attributes

Point p1
 
Point cp1
 
Point cp2
 
Point p2
 

Detailed Description

Definition at line 99 of file path_component.h.

Member Typedef Documentation

◆ PointProc

using impeller::CubicPathComponent::PointProc = std::function<void(const Point& point)>

Definition at line 133 of file path_component.h.

Constructor & Destructor Documentation

◆ CubicPathComponent() [1/3]

impeller::CubicPathComponent::CubicPathComponent ( )
inline

Definition at line 109 of file path_component.h.

109 {}

Referenced by Subsegment().

◆ CubicPathComponent() [2/3]

impeller::CubicPathComponent::CubicPathComponent ( const QuadraticPathComponent q)
inlineexplicit

Definition at line 111 of file path_component.h.

112  : p1(q.p1),
113  cp1(q.p1 + (q.cp - q.p1) * (2.0 / 3.0)),
114  cp2(q.p2 + (q.cp - q.p2) * (2.0 / 3.0)),
115  p2(q.p2) {}

◆ CubicPathComponent() [3/3]

impeller::CubicPathComponent::CubicPathComponent ( Point  ap1,
Point  acp1,
Point  acp2,
Point  ap2 
)
inline

Definition at line 117 of file path_component.h.

118  : p1(ap1), cp1(acp1), cp2(acp2), p2(ap2) {}

Member Function Documentation

◆ AppendPolylinePoints()

void impeller::CubicPathComponent::AppendPolylinePoints ( Scalar  scale,
std::vector< Point > &  points 
) const

Definition at line 196 of file path_component.cc.

198  {
200  scale, [&points](const Point& point) { points.emplace_back(point); });
201 }

References scale, and ToLinearPathComponents().

◆ Extrema()

std::vector< Point > impeller::CubicPathComponent::Extrema ( ) const

Definition at line 312 of file path_component.cc.

312  {
313  /*
314  * As described in: https://pomax.github.io/bezierinfo/#extremities
315  */
316  std::vector<Scalar> values;
317 
320 
321  std::vector<Point> points = {p1, p2};
322 
323  for (const auto& value : values) {
324  points.emplace_back(Solve(value));
325  }
326 
327  return points;
328 }

References cp1, cp2, impeller::CubicPathBoundingPopulateValues(), p1, p2, Solve(), impeller::TPoint< T >::x, and impeller::TPoint< T >::y.

Referenced by impeller::QuadraticPathComponent::Extrema(), and impeller::testing::TEST().

◆ GetEndDirection()

std::optional< Vector2 > impeller::CubicPathComponent::GetEndDirection ( ) const

Definition at line 343 of file path_component.cc.

343  {
344  if (p2 != cp2) {
345  return (p2 - cp2).Normalize();
346  }
347  if (p2 != cp1) {
348  return (p2 - cp1).Normalize();
349  }
350  if (p2 != p1) {
351  return (p2 - p1).Normalize();
352  }
353  return std::nullopt;
354 }

References cp1, cp2, p1, and p2.

Referenced by impeller::PathComponentEndDirectionVisitor::operator()().

◆ GetStartDirection()

std::optional< Vector2 > impeller::CubicPathComponent::GetStartDirection ( ) const

Definition at line 330 of file path_component.cc.

330  {
331  if (p1 != cp1) {
332  return (p1 - cp1).Normalize();
333  }
334  if (p1 != cp2) {
335  return (p1 - cp2).Normalize();
336  }
337  if (p1 != p2) {
338  return (p1 - p2).Normalize();
339  }
340  return std::nullopt;
341 }

References cp1, cp2, p1, and p2.

Referenced by impeller::PathComponentStartDirectionVisitor::operator()().

◆ operator==()

bool impeller::CubicPathComponent::operator== ( const CubicPathComponent other) const
inline

Definition at line 139 of file path_component.h.

139  {
140  return p1 == other.p1 && cp1 == other.cp1 && cp2 == other.cp2 &&
141  p2 == other.p2;
142  }

References cp1, cp2, p1, and p2.

◆ Solve()

Point impeller::CubicPathComponent::Solve ( Scalar  time) const

Definition at line 182 of file path_component.cc.

182  {
183  return {
184  CubicSolve(time, p1.x, cp1.x, cp2.x, p2.x), // x
185  CubicSolve(time, p1.y, cp1.y, cp2.y, p2.y), // y
186  };
187 }

References cp1, cp2, impeller::CubicSolve(), p1, p2, impeller::TPoint< T >::x, and impeller::TPoint< T >::y.

Referenced by Extrema(), and Subsegment().

◆ SolveDerivative()

Point impeller::CubicPathComponent::SolveDerivative ( Scalar  time) const

Definition at line 189 of file path_component.cc.

189  {
190  return {
191  CubicSolveDerivative(time, p1.x, cp1.x, cp2.x, p2.x), // x
192  CubicSolveDerivative(time, p1.y, cp1.y, cp2.y, p2.y), // y
193  };
194 }

References cp1, cp2, impeller::CubicSolveDerivative(), p1, p2, impeller::TPoint< T >::x, and impeller::TPoint< T >::y.

◆ Subsegment()

CubicPathComponent impeller::CubicPathComponent::Subsegment ( Scalar  t0,
Scalar  t1 
) const

Definition at line 208 of file path_component.cc.

208  {
209  auto p0 = Solve(t0);
210  auto p3 = Solve(t1);
211  auto d = Lower();
212  auto scale = (t1 - t0) * (1.0 / 3.0);
213  auto p1 = p0 + scale * d.Solve(t0);
214  auto p2 = p3 - scale * d.Solve(t1);
215  return CubicPathComponent(p0, p1, p2, p3);
216 }

References CubicPathComponent(), p1, p2, scale, and Solve().

Referenced by ToLinearPathComponents().

◆ ToLinearPathComponents()

void impeller::CubicPathComponent::ToLinearPathComponents ( Scalar  scale,
const PointProc proc 
) const

Definition at line 218 of file path_component.cc.

219  {
220  constexpr Scalar accuracy = 0.1;
221  // The maximum error, as a vector from the cubic to the best approximating
222  // quadratic, is proportional to the third derivative, which is constant
223  // across the segment. Thus, the error scales down as the third power of
224  // the number of subdivisions. Our strategy then is to subdivide `t` evenly.
225  //
226  // This is an overestimate of the error because only the component
227  // perpendicular to the first derivative is important. But the simplicity is
228  // appealing.
229 
230  // This magic number is the square of 36 / sqrt(3).
231  // See: http://caffeineowl.com/graphics/2d/vectorial/cubic2quad01.html
232  auto max_hypot2 = 432.0 * accuracy * accuracy;
233  auto p1x2 = 3.0 * cp1 - p1;
234  auto p2x2 = 3.0 * cp2 - p2;
235  auto p = p2x2 - p1x2;
236  auto err = p.Dot(p);
237  auto quad_count = std::max(1., ceil(pow(err / max_hypot2, 1. / 6.0)));
238  for (size_t i = 0; i < quad_count; i++) {
239  auto t0 = i / quad_count;
240  auto t1 = (i + 1) / quad_count;
241  auto seg = Subsegment(t0, t1);
242  auto p1x2 = 3.0 * seg.cp1 - seg.p1;
243  auto p2x2 = 3.0 * seg.cp2 - seg.p2;
244  QuadraticPathComponent(seg.p1, ((p1x2 + p2x2) / 4.0), seg.p2)
245  .ToLinearPathComponents(scale, proc);
246  }
247 }

References cp1, cp2, impeller::TPoint< T >::Dot(), p1, p2, scale, Subsegment(), and impeller::QuadraticPathComponent::ToLinearPathComponents().

Referenced by AppendPolylinePoints().

Member Data Documentation

◆ cp1

◆ cp2

◆ p1

◆ p2


The documentation for this struct was generated from the following files:
impeller::TPoint::y
Type y
Definition: point.h:31
impeller::Scalar
float Scalar
Definition: scalar.h:18
impeller::CubicPathComponent::Subsegment
CubicPathComponent Subsegment(Scalar t0, Scalar t1) const
Definition: path_component.cc:208
impeller::CubicPathComponent::p1
Point p1
Definition: path_component.h:101
impeller::CubicPathComponent::cp2
Point cp2
Definition: path_component.h:105
impeller::CubicPathComponent::Solve
Point Solve(Scalar time) const
Definition: path_component.cc:182
impeller::CubicPathBoundingPopulateValues
static void CubicPathBoundingPopulateValues(std::vector< Scalar > &values, Scalar p1, Scalar p2, Scalar p3, Scalar p4)
Definition: path_component.cc:257
impeller::TPoint::Dot
constexpr Type Dot(const TPoint &p) const
Definition: point.h:220
impeller::CubicSolveDerivative
static Scalar CubicSolveDerivative(Scalar t, Scalar p0, Scalar p1, Scalar p2, Scalar p3)
Definition: path_component.cc:44
impeller::CubicPathComponent::cp1
Point cp1
Definition: path_component.h:103
impeller::Point
TPoint< Scalar > Point
Definition: point.h:316
impeller::CubicSolve
static Scalar CubicSolve(Scalar t, Scalar p0, Scalar p1, Scalar p2, Scalar p3)
Definition: path_component.cc:33
impeller::TPoint::x
Type x
Definition: point.h:30
impeller::CubicPathComponent::CubicPathComponent
CubicPathComponent()
Definition: path_component.h:109
impeller::CubicPathComponent::ToLinearPathComponents
void ToLinearPathComponents(Scalar scale, const PointProc &proc) const
Definition: path_component.cc:218
scale
const Scalar scale
Definition: stroke_path_geometry.cc:297
impeller::CubicPathComponent::p2
Point p2
Definition: path_component.h:107