Skip to main content

Curve

Struct Curve 

Source
pub struct Curve {
    pub points: BTreeSet<Point2D>,
    pub x_range: (Decimal, Decimal),
}
Expand description

Represents a mathematical curve as a collection of 2D points.

§Overview

The Curve struct is a fundamental representation of a curve, defined as a series of points in a two-dimensional Cartesian coordinate system. Each curve is associated with an x_range, specifying the inclusive domain of the curve in terms of its x-coordinates.

This structure supports precise mathematical and computational operations, including interpolation, analysis, transformations, and intersections. The use of Decimal for coordinates ensures high-precision calculations, making it particularly suitable for scientific, financial, or mathematical applications.

§Usage

The Curve struct acts as the basis for high-level operations provided within the crate::curves module. These include (but are not limited to):

  • Generating statistical analyses (CurveAnalysisResult)
  • Performing curve interpolation
  • Logical manipulations, such as merging curves (MergeOperation)
  • Visualizing graphs or curve plots using libraries like plotters

§Example Applications

The Curve type fits into mathematical or graphical operations such as:

  • Modeling data over a range of x-values
  • Comparing curves through transformations or intersections
  • Calculating derivatives, integrals, and extrema along the curve

§Constraints

  • All points in the points vector must lie within the specified x_range.
  • Methods working with Curve data will assume that the points vector is ordered by the x-coordinate. Non-ordered inputs may lead to undefined behavior in specific operations.
  • A curve is a function of its abscissa: at most one point per x. See Curve::new for what breaking that rule does to each consumer, and for why no constructor can enforce it.

§See Also

  • Point2D: The fundamental data type for representing points in 2D space.
  • MergeOperation: Enum for combining multiple curves.

Fields§

§points: BTreeSet<Point2D>

A ordered set of Point2D objects that defines the curve in terms of its x-y plane coordinates. Points are stored in a BTreeSet which automatically maintains them in sorted order by their (x, y) pair. The set rejects an exact duplicate of that pair; it does not stop two ordinates from sharing an abscissa.

Public, so a struct literal can populate it without passing through Curve::new. No constructor can therefore guarantee one point per abscissa.

§x_range: (Decimal, Decimal)

A tuple (min_x, max_x) that specifies the minimum and maximum x-coordinate values for the curve. Operations performed on the curve should ensure they fall within this range. Both values are of type Decimal to ensure high precision in boundary calculations.

Implementations§

Source§

impl Curve

Source

pub fn new(points: BTreeSet<Point2D>) -> Self

Creates a new curve from a vector of points.

This constructor initializes a Curve instance using a list of 2D points provided as a BTreeSet<Point2D>. Additionally, the x-range of the curve is calculated and stored. The x-range is determined by evaluating the minimum and maximum x-coordinates among the provided points.

§Parameters
  • points (BTreeSet<Point2D>): A vector of points that define the curve in a two-dimensional Cartesian coordinate plane.
§Returns
  • Curve: A newly instantiated curve containing the provided points and the computed x-range.
§Behavior
  • Calculates the x-range of the points using calculate_range().
  • Stores the provided points for later use in curve-related calculations.
§See Also
§One point per abscissa

A Curve is a function of its abscissa: at most one point per x. Every consumer reads it that way. get_point and contains_point answer from the first point matching x, merge resamples every curve onto one shared x-grid with one y per x, and the interpolators in crate::geometrics bracket x between two consecutive points and divide by the width of that bracket.

Nothing enforces the rule. Point2D orders on the full (x, y) pair, so points may hold several ordinates for one abscissa and new stores them all; a curve built that way is outside the contract and the consumers behave as follows:

  • all four interpolators return InterpolationError::DegenerateInterval when asked about a repeated abscissa, and pick no survivor: the bracket around it has zero width and the slope across it is undefined;
  • get_point and merge_axis_interpolate read the first match in (x, y) order, which is the lowest ordinate of the stack, and the rest are invisible to the caller. Use get_values to see every ordinate at an abscissa.

Normalizing here would not help: points is a pub field, so a struct literal reaches the same state without going through any constructor. Rejecting or collapsing a duplicate can only ever be a convenience on this path, never an invariant of the type.

A projection of a surface is genuinely multi-valued and is therefore not a curve: crate::surfaces::Surface::project_onto returns a Vec<Point2D>, and aggregating it to one ordinate per abscissa is the caller’s job.

Trait Implementations§

Source§

impl Arithmetic<Curve> for Curve

Implements the CurveArithmetic trait for the Curve type, providing functionality for merging multiple curves using a specified mathematical operation and performing arithmetic operations between two curves.

Source§

fn merge( curves: &[&Curve], operation: MergeOperation, ) -> Result<Curve, CurveError>

Merges a collection of curves into a single curve based on the specified mathematical operation.

§Parameters
  • curves (&[&Curve]): A slice of references to the curves to be merged. Each curve must have defined x-ranges and interpolation capabilities.
  • operation (MergeOperation): The arithmetic operation to perform on the interpolated y-values for the provided curves. Operations include addition, subtraction, multiplication, division, and aggregation (e.g., max, min).
§Returns
  • Ok(Curve): Returns a new curve resulting from the merging operation.
  • Err(CurvesError): If input parameters are invalid or the merge operation encounters an error (e.g., incompatible x-ranges or interpolation failure), an error is returned.
§Behavior
  1. Parameter Validation:
  • Verifies that at least one curve is provided in the curves parameter.
  • Returns an error if no curves are included or if x-ranges are incompatible.
  1. Cloning Single Curve:
  • If only one curve is provided, its clone is returned as the result without performing any further calculations.
  1. Range Computation:
  • Computes the intersection of x-ranges across the curves by finding the maximum lower bound (min_x) and minimum upper bound (max_x).
  • If the x-range intersection is invalid (i.e., min_x >= max_x), an error is returned.
  1. Interpolation and Arithmetic:
  • Divides the x-range into steps equally spaced intervals (default: 100).
  • Interpolates the y-values for all curves at each x-value in the range.
  • Applies the specified operation to the aggregated y-values at each x-point.
  1. Parallel Processing:
  • Uses parallel iteration over the grid to interpolate the operands efficiently, leveraging the Rayon library. The grid points are independent of one another and are collected back in x order.
  1. Error Handling:
  • Any errors during interpolation or arithmetic operations are propagated back to the caller.
§Determinism

The same operands in the same order give the same result, digit for digit, with the one exception noted for Max and Min below. Within a grid point the operands are accumulated in the order they were passed in, never in an order chosen by the thread pool.

This matters for Multiply and Divide in particular. Decimal multiplication rounds once a product needs more than 28 decimal digits, so it is not associative, and a parallel reducer would take its bracketing from whatever chunking rayon picked on the day: three or more curves could then merge to different last digits on consecutive runs of one binary over one input. Add and Subtract fold in order for the same reason.

Max and Min still reduce in parallel. They select an operand instead of accumulating one, so no rounding enters and the extremum is the same whatever the grouping. What is not pinned is which of several operands that compare equal is the one returned, and two Decimal values comparing equal can still carry different scales, so a tie between 2.0 and 2.00 is the one case where the stored digits are left to the reducer.

§Errors
  • Invalid Parameter (CurvesError): Returned when no curves are provided or x-ranges are incompatible.
  • Interpolation Failure (CurvesError): Raised if interpolation fails for a specific curve or x-value.
§Example Use Case

This function enables combining multiple curves for tasks such as:

  • Summing y-values across different curves to compute a composite curve.
  • Finding the maximum/minimum y-value at each x-point for a collection of curves.
§One point per abscissa

This assumes the one-point-per-abscissa rule of Curve::new and re-establishes it in the result: the merged curve is sampled on an evenly spaced grid over the common x-range, with one y per grid point, so the original abscissae do not survive the merge.

An input carrying several ordinates at one abscissa never has one of them silently chosen. Each sample is produced by cubic interpolation, which reports InterpolationError::DegenerateInterval, wrapped in a CurveError, whenever the sample lands on the repeated abscissa or brackets across it. A sample far enough from the stack is unaffected and reads the ordinate on its own side, so a merge of such a curve can still succeed on a grid that misses the stack. Aggregate the curve to one ordinate per abscissa before merging it.

Source§

fn merge_with( &self, other: &Curve, operation: MergeOperation, ) -> Result<Curve, CurveError>

Combines the current Curve instance with another curve using a mathematical operation, resulting in a new curve.

§Parameters
  • self (&Self): A reference to the current curve instance.
  • other (&Curve): A reference to the second curve for the arithmetic operation.
  • operation (MergeOperation): The operation to apply when merging the curves.
§Returns
  • Ok(Curve): Returns a new curve that represents the result of the operation.
  • Err(CurvesError): If the merge operation fails (e.g., incompatible x-ranges or interpolation errors), an error is returned.
§Behavior

This function is a convenience wrapper around merge_curves that operates specifically on two curves. It passes self and other as an array to merge_curves and applies the desired operation.

§Errors
  • Inherits all errors returned by the merge_curves method, including parameter validation and interpolation errors.
§Examples

Use this method to easily perform arithmetic operations between two curves, such as summing their y-values or finding their pointwise maximum.

Source§

type Error = CurveError

The error type returned when merging operations fail
Source§

impl AxisOperations<Point2D, Decimal> for Curve

Source§

fn contains_point(&self, x: &Decimal) -> bool

Reports whether the curve has a point at the abscissa x.

Answers on x alone, so it says nothing about how many ordinates sit there. On a curve honouring the one-point-per-abscissa rule of Curve::new there is at most one.

Source§

fn get_index_values(&self) -> Vec<Decimal>

Returns the abscissa of every point, in (x, y) order.

A curve holding several ordinates at one abscissa yields that abscissa once per ordinate; the duplicates are visible here rather than dropped.

Source§

fn get_values(&self, x: Decimal) -> Vec<&Decimal>

Returns every ordinate at the abscissa x, in ascending order.

This is the multi-valued reader: unlike Self::get_point, it never picks a survivor. A curve honouring the one-point-per-abscissa rule of Curve::new returns at most one value; anything longer says the curve is not a function of its abscissa.

Source§

fn get_point(&self, x: &Decimal) -> Option<&Point2D>

Returns the point at the abscissa x, if there is one.

Assumes the one-point-per-abscissa rule of Curve::new. If the curve breaks it, this returns the first match in (x, y) order, which is the lowest ordinate of the stack, and the rest are invisible to the caller. Use Self::get_values to see all of them.

Source§

type Error = CurveError

The type of error that can occur during point operations
Source§

fn get_closest_point(&self, x: &Decimal) -> Result<&Point2D, Self::Error>

Finds the closest point to the given coordinate value. Read more
Source§

fn merge_indexes(&self, axis: Vec<Input>) -> Vec<Input>

Merges the index values from the current structure with an additional set of indices. This combines self.get_index_values() with the provided axis vector to create a single vector of unique indices. Read more
Source§

impl BiLinearInterpolation<Point2D, Decimal> for Curve

Implementation of the BiLinearInterpolation trait for the Curve struct.

§What it computes

Bilinear interpolation is defined on a cell of a two-dimensional grid: the answer is the mean of four corner samples, weighted by the query’s fractional position along each axis. A curve has one axis, so the cell is built out of two of its segments and the second fraction is fixed at one half:

  • the near edge is the segment that brackets x, from sample i to sample i + 1;
  • the far edge is the segment two positions further along, from sample f to sample f + 1;
  • the answer is the mean of the two edges read at the same fraction.
t    = (x - x[i]) / (x[i+1] - x[i])
near = y[i] + t * (y[i+1] - y[i])
far  = y[f] + t * (y[f+1] - y[f])
y    = (near + far) / 2

§Behaviour near the upper boundary

The far edge is f = i + 2 while such a segment exists. Over the last two segments of the curve it does not, and f is clamped to len - 2, the curve’s last segment. Two consequences a caller can act on:

  • on the final segment the two edges coincide, near equals far, and the answer is the linear interpolant there. Not always to the last digit: this method normalises x before scaling by the rise and LinearInterpolation::linear_interpolate scales first, so where the fraction along the segment has no finite decimal expansion the two round at scale 28 on different quantities and can part company in the 28th place;
  • on the second-to-last segment the far edge is the segment immediately after the near one instead of the one after that.

§Why not clamp the window start

The obvious repair, and the one CubicInterpolation::cubic_interpolate applies at its own boundary, is to slide the whole window back to the last four samples. Do not reach for it here. The window start is also the denominator of t, so moving it back off the segment holding x pushes t past 1. Written out, the answer weights the four ordinates it reads by

y = (1 - t)/2 * y[i] + t/2 * y[i+1] + (1 - t)/2 * y[f] + t/2 * y[f+1]

which sums to one for any t, but has every weight non-negative only while t is in [0, 1]. Past 1 the two (1 - t)/2 weights go negative, the answer stops being a convex combination of the cell’s corners, and what is left is an extrapolation of a cell that does not contain x: on (0,0), (1,1), (2,4), (3,9) the window-start clamp returns 9.5 at x = 2.5, above every ordinate the curve has. Being a convex combination of its cell’s corners is what makes bilinear interpolation bilinear interpolation, so it is the near edge that has to stay put and the far edge that gives way. That is why the two boundary rules differ.

Before this rule existed the last two segments returned InterpolationError::Bilinear because the window ran off the end.

§What this is not

The far edge sits elsewhere on the curve, so the result does not follow the samples between knots and this is not an interpolant through them: on (0,0), (1,1), (2,4), (3,9) the value at x = 0.5 is 3.5, not the 0.5 a straight reading of the bracketing segment gives.

An x landing exactly on a sample returns that sample, which neither one-sided limit approaching it matches, so the result jumps at every sample. That jump is as old as the method and owes nothing to the boundary rule above: on (0,0), (1,1), (2,4), (3,9), (4,16) both limits at x = 1 are 5 against a sample of 1, and both segments meeting there are far from the clamp. What the clamp does add is that at the last two samples before the end of the curve the two limits no longer agree with each other either, because the segments on either side get different far edges.

Reach for LinearInterpolation or SplineInterpolation when a curve through the samples is what is wanted.

§Parameters

  • x: The x-coordinate to interpolate at. Must lie within the range of the curve’s x-coordinates.

§Returns

  • Ok(Point2D): The interpolated point at x, both coordinates as Decimal.
  • Err(InterpolationError): See the error list below.

§Errors

§One point per abscissa

A curve is a function of its abscissa; see Curve::new. Asking for a repeated abscissa returns InterpolationError::DegenerateInterval, as it does for the three sibling algorithms; no ordinate of the stack is chosen. A stack elsewhere on the curve does not stop this method answering: only the near edge’s width is divided by, and a stack sitting on the far edge is read for its two ordinates alone.

§See Also

  • Curve: The overarching structure that represents the curve.
  • Point2D: The data type used to represent individual points on the curve.
  • find_bracket_points: A helper method used to locate the two points that bracket the given x-coordinate.
Source§

fn bilinear_interpolate( &self, x: Decimal, ) -> Result<Point2D, InterpolationError>

Reads the curve at x as the mean of the bracketing segment and the segment two positions further along, both at the same fraction.

The far segment is clamped to the curve’s last one where it would run off the end, which makes the final segment a plain linear interpolation. The impl-level documentation states the rule and its consequences in full.

§Errors
Source§

impl Clone for Curve

Source§

fn clone(&self) -> Self

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl ComposeSchema for Curve

Source§

impl CubicInterpolation<Point2D, Decimal> for Curve

Implements the CubicInterpolation trait for the Curve struct, providing an algorithm for cubic interpolation utilizing a Catmull-Rom spline.

§Method: cubic_interpolate

§Parameters
  • x: The x-value at which the interpolation is performed. This value must be within the range of x-values in the curve’s defined points, and it is passed as a Decimal to allow for high-precision computation.
§Returns
  • Ok(Point2D): Returns a Point2D representing the interpolated x and y values.
  • Err(CurvesError): Returns an error if:
    • There are fewer than 4 points available for interpolation.
    • The x-value is outside the curve’s range, or interpolation fails for any other reason.
§Behavior
  1. Point Validation: Ensures at least four points exist for cubic interpolation, as this is a fundamental requirement for computing the Catmull-Rom spline.
  2. Exact Match Check: If the x-value matches an existing point in the curve, the method directly returns the corresponding Point2D without further computation.
  3. Bracket Points: Determines the bracketing points (4 points total) around the provided x-value. Depending on the position of the x-value in the curve, the method dynamically adjusts the selected points to ensure they form a proper bracket:
    • If near the start of the curve, uses the first four points.
    • If near the end, uses the last four points.
    • Else, selects points before and after x to define the bracket.
  4. Parameter Calculation: Computes a normalized parameter t that represents the relative position of the target x-value between p1 and p2.
  5. Catmull-Rom Spline: Performs cubic interpolation using a Catmull-Rom spline, a widely used, smooth spline algorithm. The coefficients are calculated based on the relative x position and the y-values of the four surrounding points.
  6. Interpolation: Calculates the interpolated y-value using the cubic formula:
    y(t) = 0.5 * (
        2 * p1.y + (-p0.y + p2.y) * t
        + (2 * p0.y - 5 * p1.y + 4 * p2.y - p3.y) * t^2
        + (-p0.y + 3 * p1.y - 3 * p2.y + p3.y) * t^3
    )
    Here, t is the normalized x position, and p0, p1, p2, p3 are the four bracketed points.
§Errors
  • Returns an error of type CurvesError::InterpolationError if any issues are encountered, such as insufficient points or the inability to locate bracket points.
§Example

This method is part of the Curve struct, which defines a set of points and supports interpolation. It is often used in applications requiring smooth manifolds or animations.

§Notes
  • The computed y-value ensures smooth transitions and continuity between interpolated segments.
  • Catmull-Rom splines are particularly effective for creating visually smooth transitions, making this method suitable for curves, animations, and numerical analysis.

§See Also

Source§

fn cubic_interpolate(&self, x: Decimal) -> Result<Point2D, InterpolationError>

Performs cubic interpolation on a set of points to estimate the y-coordinate for a given x value using a Catmull-Rom spline.

§Parameters
  • x: The x-coordinate for which the interpolation is performed. This value should lie within the range of the points on the curve.
§Returns
  • Ok(Point2D): A Point2D instance representing the interpolated position (x, y), where y is estimated using cubic interpolation.
  • Err(CurvesError): An error indicating issues with the interpolation process, such as insufficient points or an out-of-range x value.
§Requirements
  • The number of points in the curve must be at least 4, as cubic interpolation requires four points for accurate calculations.
  • The specified x value should be inside the range defined by the curve’s points.
  • If the specified x matches an existing point on the curve, the interpolated result directly returns that exact point.
§Functionality

This method performs cubic interpolation using the general properties of the Catmull-Rom spline, which is well-suited for smooth curve fitting. It operates as follows:

  1. Exact Point Check: If the x value matches an existing point, the method returns that point without further processing.

  2. Bracketing Points Selection:

    • Searches for two points that bracket the given x value (using find_bracket_points from the Interpolate trait). The method ensures that there are always enough points before and after the target x value to perform cubic interpolation.
  3. Point Selection for Interpolation:

    • Depending on the position of the target x value, four points (p0, p1, p2, p3) are selected:
      • When x is near the start of the points, select the first four.
      • When x is near the end, select the last four.
      • Otherwise, select the two points just before and after the x value and include an additional adjacent point on either side.
  4. Parameter Calculation:

    • The t parameter is derived, representing the normalized position of x between p1 and p2.
  5. Cubic Interpolation:

    • The interpolated y-coordinate is computed using the Catmull-Rom spline formula, leveraging the t-value and the y-coordinates of the four selected points.
§Error Handling

This method returns an error in the following circumstances:

  • If fewer than 4 points are available, it returns a CurvesError::InterpolationError with a corresponding message.
  • If the bracketing points cannot be identified (e.g., when x is outside the range of points), the appropriate interpolation error is propagated.
  • If the curve is not a function of its abscissa at the point it is asked about, it returns InterpolationError::DegenerateInterval: several points at x leave the exact-match branch with no single value to return, and two consecutive points sharing an abscissa leave the interpolation bracket with zero width. Neither case picks an ordinate. See Curve::new for the rule.
§Example
  • Interpolating smoothly along a curve defined by a set of points, avoiding sharp transitions between segments.

  • Provides a high degree of precision due to the use of the Decimal type for x and y calculations.

Source§

impl Debug for Curve

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Default for Curve

Source§

fn default() -> Self

Returns the “default value” for a type. Read more
Source§

impl<'de> Deserialize<'de> for Curve

Source§

fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>
where __D: Deserializer<'de>,

Deserialize this value from the given Serde deserializer. Read more
Source§

impl Display for Curve

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl GeometricObject<Point2D, Decimal> for Curve

Source§

fn from_vector<T>(points: Vec<T>) -> Self
where T: Into<Point2D> + Clone,

Builds a curve from a vector of convertible points.

§One point per abscissa

Same rule and same non-enforcement as Curve::new: a curve is a function of its abscissa, and this constructor does not check it. points is collected into a BTreeSet, which drops an exact duplicate of an (x, y) pair but keeps two ordinates that merely share an x. Aggregate before calling if the input can carry several ordinates per abscissa, as the projection returned by crate::surfaces::Surface::project_onto does.

Source§

type Error = CurveError

Type alias for any errors that might occur during the construction of the geometric object.
Source§

fn get_points(&self) -> BTreeSet<&Point2D>

Returns a BTreeSet containing references to the points that constitute the geometric object. The BTreeSet ensures that the points are ordered and unique.
Source§

fn construct<T>(method: T) -> Result<Self, Self::Error>

Constructs a geometric object using a specific construction method. Read more
Source§

fn vector(&self) -> Vec<&Point>

Returns a Vec containing references to the points that constitute the geometric object. This method simply converts the BTreeSet from get_points into a Vec.
Source§

fn to_vector(&self) -> Vec<&Point>

Returns the points of the geometric object as a Vec of references. Equivalent to calling the vector() method.
Source§

fn calculate_range<I>(iter: I) -> (Decimal, Decimal)
where I: Iterator<Item = Decimal>,

Calculates the minimum and maximum decimal values from an iterator of decimals. Read more
Source§

impl GeometricTransformations<Point2D> for Curve

Source§

fn intersect_with(&self, other: &Self) -> Result<Vec<Point2D>, Self::Error>

Reports the samples the two curves share.

§What it computes

Every pair of samples (p1, p2), p1 from self and p2 from other, whose abscissas differ by less than 1e-6 and whose ordinates differ by less than 1e-6, contributes p1 to the result. The result is in (p1, p2) order: by self’s (x, y) order, then by other’s for one p1.

§What it does not compute

Only coinciding samples are compared, never the segments between them. Two curves that cross between their samples are not reported, so (0, 0), (2, 2) and (0, 2), (2, 0), which cross at (1, 1), return nothing. A sample of self that coincides with several samples of other appears once per match. Whether a segment-crossing variant should exist is an open owner decision (#858); this method documents the current behaviour.

§Cost

Both point sets are sorted by abscissa, so the samples of other within 1e-6 of p1 form a window that only slides forward as p1 advances. The walk is O(n + m) plus one step per matching pair, with no allocation beyond the result (#858). It visits the pairs the all-pairs comparison tested on ordinates, in the same order, so the result and any error are the same. When some abscissa difference could overflow, the all-pairs comparison runs instead, so the error names the same pair.

§Errors

CurveError::AnalysisError when a coordinate difference leaves the Decimal range.

Source§

type Error = CurveError

The error type that can be returned by geometric operations.
Source§

fn translate(&self, deltas: Vec<&Decimal>) -> Result<Self, Self::Error>

Translates the geometric object by specified amounts along each dimension. Read more
Source§

fn scale(&self, factors: Vec<&Decimal>) -> Result<Self, Self::Error>

Scales the geometric object by specified factors along each dimension. Read more
Source§

fn derivative_at(&self, point: &Point2D) -> Result<Vec<Decimal>, Self::Error>

Calculates the derivative at a specific point on the geometric object. Read more
Source§

fn extrema(&self) -> Result<(Point2D, Point2D), Self::Error>

Finds the extrema (minimum and maximum points) of the geometric object. Read more
Source§

fn measure_under(&self, base_value: &Decimal) -> Result<Decimal, Self::Error>

Calculates the area or volume under the geometric object relative to a base value. Read more
Source§

impl Index<usize> for Curve

Allows indexed access to the points in a Curve using usize indices.

§Overview

This implementation provides intuitive, array-like access to the points within a Curve. By using the Index<usize> trait, users can directly reference specific points by their index within the internal points collection without manually iterating or managing indices themselves.

§Behavior

  • The index method fetches the Point2D at the specified position in the order of the curve’s points (sorted by the Point2D ordering, typically based on the x values).
  • If the specified index exceeds the range of available points, it triggers a panic with the message "Index out of bounds".

§Constraints

  • The index must be a valid value between 0 and self.points.len() - 1.
  • The Curve’s points are internally stored as a BTreeSet<Point2D>, so indexing reflects the natural order of the set, which is determined by the Ord trait implementation for Point2D.

§Fields Accessed

  • points: A BTreeSet of Point2D structs representing the curve’s 2D points.

§Panics

This implementation will panic if:

  • The index provided is out of bounds (less than 0 or greater than/equal to the number of points in the curve).

§Use Cases

  • Quickly accessing specific points on a curve during visualization, interpolation, or analysis operations.
  • Performing operations that require stepwise access to points, such as slicing or filtering points along the curve.

§Example

Suppose you have a Curve instance curve with multiple points:

ⓘ
let point = curve[0]; // Access the first point

§Important Notes

  • This indexing implementation provides read-only access (&Self::Output).
  • Modifying the points collection or its contents directly is not allowed through this implementation, ensuring immutability when using indexed access.

§Type Associations

  • Input:
    • The input type for the Index operation is usize, the standard for indexing.
  • Output:
    • The output type for the Index operation is a reference to Point2D, specifically &Point2D.

§Key Implementations

  • Index<usize>: Provides indexing-based access to curve points.

§Panics

Panics if index >= self.points.len(), the contract of std::ops::Index and of Vec. Index has no error channel; for a lookup that reports a missing index, use get_points().into_iter().nth(index).

Source§

fn index(&self, index: usize) -> &Self::Output

Fetches the Point2D at the specified index.

§Panics

Panics if index >= self.points.len(). This matches the documented contract of std::ops::Index.

Source§

type Output = Point2D

The returned type after indexing.
Source§

impl Interpolate<Point2D, Decimal> for Curve

Implementation of the Interpolate trait for the Curve struct.

This implementation integrates the get_points method for the Curve structure, providing access to its internal points. The Interpolate trait ensures compatibility with various interpolation methods such as Linear, BiLinear, Cubic, and Spline interpolations. By implementing this trait, Curve gains the ability to perform interpolation operations and access bracketing points.

§Traits Involved

The Interpolate trait is an aggregation of multiple interpolation-related traits:

These underlying traits implement specific interpolation algorithms, enabling Curve to support a robust set of interpolation options through the associated methods. Depending on the use case and provided parameters (e.g., interpolation type and target x-coordinate), the appropriate algorithm is invoked.

§See Also

  • Curve: The underlying mathematical structure being interpolated.
  • Point2D: The fundamental data type for the curve’s points.
  • Interpolate: The trait defining interpolation operations.
Source§

fn find_bracket_points( &self, x: Decimal, ) -> Result<(usize, usize), InterpolationError>

Same contract and same indices as the trait’s default, including the degenerate window over a repeated abscissa, without collecting the points into a Vec first: the pair is found in O(log n) and its index by counting the points before it (#858).

Source§

fn interpolate( &self, x: Input, interpolation_type: InterpolationType, ) -> Result<Point, InterpolationError>

Interpolates a value at the given x-coordinate using the specified interpolation method. Read more
Source§

impl Len for Curve

Source§

fn len(&self) -> usize

Returns the number of elements in the collection or the size of the object. Read more
Source§

fn is_empty(&self) -> bool

Returns true if the collection contains no elements or the object has zero size. Read more
Source§

impl LinearInterpolation<Point2D, Decimal> for Curve

Implements the LinearInterpolation trait for the Curve struct.

This implementation provides linear interpolation functionality for a given set of points on a curve. The interpolation computes the y value corresponding to a given x value using the linear interpolation formula. The method ensures that the input x is within the range of the curve’s defined points.

y = p1.y + (x - p1.x) * (p2.y - p1.y) / (p2.x - p1.x)

§Parameters

  • x: A Decimal representing the x-coordinate for which the corresponding interpolated y value is to be computed.

§Returns

  • Ok(Point2D): A Point2D instance containing the input x value and the interpolated y value.
  • Err(CurvesError): Returns an error of type CurvesError::InterpolationError in any of the following cases:
    • The curve does not have enough points for interpolation.
    • The provided x value is outside the range of the curve’s points.
    • Bracketing points for x cannot be found.

§Working Mechanism

  1. The method calls find_bracket_points (implemented in the Interpolate trait) to locate the index pair (i, j) of two points that bracket the x value.
  2. From the located points p1 and p2, the method calculates the interpolated y value using the linear interpolation formula.
  3. Finally, a Point2D is created and returned with the provided x and the computed y value.

§Implementation Details

  • The function leverages Decimal arithmetic for high precision in calculations.
  • It assumes that the provided points on the curve are sorted in ascending order based on their x values.

§Errors

This method returns a CurvesError in the following cases:

  • Insufficient Points: When the curve has fewer than two points.
  • Out-of-Range x: When the input x value lies outside the range of the defined points.
  • No Bracketing Points Found: When the method fails to find two points that bracket the given x.
  • Degenerate Bracket: When several points share the requested abscissa. The curve has no value there and the bracket around it has zero width, so the method reports InterpolationError::DegenerateInterval instead of picking one of the ordinates stacked there.

§One point per abscissa

A curve is a function of its abscissa; see Curve::new. Asking for a repeated abscissa returns InterpolationError::DegenerateInterval; no ordinate of the stack is chosen.

Away from the stack the method still answers, reading the stack as a vertical jump: an x strictly inside an interval bounded by a repeated abscissa brackets against the point on its own side, the highest ordinate when the stack bounds the interval on the left and the lowest when it bounds it on the right.

§Example (How it works internally)

Suppose the curve is defined by the following points:

  • p1 = (2.0, 4.0)
  • p2 = (5.0, 10.0)

Given x = 3.0, the method computes:

y = 4.0 + (3.0 - 2.0) * (10.0 - 4.0) / (5.0 - 2.0)
  = 4 + 1 * 6 / 3
  = 4 + 2
  = 6.0

It will return Point2D { x: 3.0, y: 6.0 }.

§See Also

  • find_bracket_points: Finds two points that bracket a value.
  • Point2D: Represents points in 2D space.
  • CurvesError: Represents errors related to curve operations.
Source§

fn linear_interpolate(&self, x: Decimal) -> Result<Point2D, InterpolationError>

§Method
§linear_interpolate

Performs linear interpolation for a given x value by finding two consecutive points on the curve (p1 and p2) that bracket the provided x. The y value is then calculated using the linear interpolation formula:

Source§

impl MergeAxisInterpolate<Point2D, Decimal> for Curve
where Self: Sized,

Source§

fn merge_axis_interpolate( &self, other: &Self, interpolation: InterpolationType, ) -> Result<(Self, Self), Self::Error>

Resamples both curves onto the shared x-grid of their merged indices.

Each result holds one point per abscissa of that grid, so it is a function of its abscissa whatever the inputs were: where a curve already has a point at an abscissa, the one kept is the first match in (x, y) order, so a stack of ordinates collapses to its lowest, and elsewhere the point is interpolated. Aggregate such a curve before merging if a different ordinate is wanted.

Source§

fn merge_axis_index<'a>(&'a self, other: &'a Self) -> Vec<Input>

Merges the index values from two structures into a single ordered vector. Read more
Source§

impl MetricsExtractor for Curve

A default implementation for the Curve type using a provided default strategy.

This implementation provides a basic approach to computing curve metrics by using interpolation and statistical methods available in the standard curve analysis library.

§Note

This is a minimal implementation that may need to be customized or enhanced based on specific requirements or domain-specific analysis needs.

Source§

fn compute_basic_metrics(&self) -> Result<BasicMetrics, MetricsError>

Computes basic statistical metrics for the curve. Read more
Source§

fn compute_shape_metrics(&self) -> Result<ShapeMetrics, MetricsError>

Computes shape-related metrics for the curve. Read more
Source§

fn compute_range_metrics(&self) -> Result<RangeMetrics, MetricsError>

Computes range-related metrics for the curve. Read more
Source§

fn compute_trend_metrics(&self) -> Result<TrendMetrics, MetricsError>

Computes trend-related metrics for the curve. Read more
Source§

fn compute_risk_metrics(&self) -> Result<RiskMetrics, MetricsError>

Computes risk-related metrics for the curve. Read more
Source§

fn compute_curve_metrics(&self) -> Result<Metrics, MetricsError>

Computes and aggregates all curve metrics into a comprehensive CurveMetrics struct. Read more
Source§

fn compute_surface_metrics(&self) -> Result<Metrics, MetricsError>

Computes comprehensive metrics for a surface representation. Read more
Source§

impl Serialize for Curve

Source§

fn serialize<__S>(&self, __serializer: __S) -> Result<__S::Ok, __S::Error>
where __S: Serializer,

Serialize this value into the given Serde serializer. Read more
Source§

impl SplineInterpolation<Point2D, Decimal> for Curve

Implements the SplineInterpolation trait for the Curve struct, providing functionality to perform cubic spline interpolation.

§Overview

This method calculates the interpolated y value for a given x value by using cubic spline interpolation on the points in the Curve. The method ensures a smooth transition between points by computing second derivatives of the curve at each point, and uses those derivatives in the spline interpolation formula.

§Parameters

  • x: The x-coordinate at which the curve should be interpolated. This value is passed as a Decimal for precise calculations.

§Returns

  • On success, returns a Point2D instance representing the interpolated point.
  • On error, returns a CurvesError indicating the reason for failure (e.g., insufficient points or an out-of-range x-coordinate).

§Errors

  • Returns CurvesError::InterpolationError with an appropriate error message in the following cases:
    • If the curve contains fewer than three points, as spline interpolation requires at least three points.
    • If the given x value lies outside the range of x-coordinates spanned by the points in the curve.
    • If a valid segment for interpolation cannot be located.

§Details

  1. Validation:
    • Ensures that there are at least three points in the curve for spline interpolation.
    • Validates that the provided x value is within the range of x values of the curve.
  2. Exact Match: If the x value matches the x-coordinate of an existing point, the corresponding Point2D is returned immediately.
  3. Second Derivative Calculation:
    • Uses a tridiagonal matrix to compute the second derivatives at each point. This step involves setting up the system of equations based on the boundary conditions (natural spline) and solving it using the Thomas algorithm.
  4. Segment Identification:
    • Determines the segment (interval between two consecutive points) in which the provided x value lies.
  5. Interpolation:
    • Computes the interpolated y-coordinate using the cubic spline formula, which is based on the second derivatives and the positions of the surrounding points.

§Implementation Notes

  • This implementation uses Decimal from the rust_decimal crate to ensure high precision in calculations, making it suitable for scientific and financial applications.
  • The Thomas algorithm is employed to solve the tridiagonal matrix system efficiently.
  • The method assumes natural spline boundary conditions, where the second derivatives at the endpoints are set to zero, ensuring a smooth and continuous curve shape.

§Example Usage

Refer to the documentation for how to use the SplineInterpolation trait, as examples are not provided inline with this implementation.

§See Also

  • SplineInterpolation: The trait definition for spline interpolation.
  • Point2D: Represents a point in 2D space.
  • Curve: Represents a mathematical curve made up of points for interpolation.
  • CurveError: Enumerates possible errors during curve operations.
Source§

fn spline_interpolate(&self, x: Decimal) -> Result<Point2D, InterpolationError>

Performs cubic spline interpolation for a given x-coordinate and returns the interpolated Point2D value. This function computes the second derivatives of the curve points, solves a tridiagonal system to derive the interpolation parameters, and evaluates the spline function for the provided x value.

§Parameters
  • x:
    • The x-coordinate at which the interpolation is to be performed.
    • Must be of type Decimal.
§Returns
  • Ok(Point2D):

    • The Point2D instance representing the interpolated point at the given x value.
    • The interpolated y value is calculated based on the cubic spline interpolation algorithm.
  • Err(CurvesError):

    • Returned when an error occurs during the interpolation process, such as:
      • Insufficient points provided (less than 3 points).
      • The given x is outside the valid range of the points.
      • Unable to determine the correct segment for interpolation.
§Errors
  • CurvesError::InterpolationError:
    • Occurs under the following conditions:
      • “Need at least three points for spline interpolation”: Requires at least 3 points to perform cubic spline interpolation.
      • “x is outside the range of points”: The provided x value lies outside the domain of the curve points.
      • “Could not find valid segment for interpolation”: Spline interpolation fails due to an invalid segment determination.
§Pre-conditions
  • The curve must contain at least three points for cubic spline interpolation.
  • The x value must fall within the range of the curve’s x-coordinates.
§Implementation Details
  • Inputs:
    • Uses the get_points method of the curve to retrieve the list of Point2D instances that define the interpolation curve.
    • Computes the second derivatives (m) for each point using the Thomas algorithm to solve a tridiagonal system.
  • Boundary Conditions:
    • Natural spline boundary conditions are used, with the second derivatives on the boundary set to zero.
  • Interpolation:
    • Determines the segment [x_i, x_{i+1}] to which the input x belongs.
    • Uses the cubic spline equation to calculate the interpolated y value.
§Mathematical Formulation

Let x_i, x_{i+1}, y_i, y_{i+1} refer to the points of the segment where x lies. The cubic spline function at x is computed as follows:

S(x) = m_i * (x_{i+1} - x)^3 / (6 * h)
     + m_{i+1} * (x - x_i)^3 / (6 * h)
     + (y_i / h - h * m_i / 6) * (x_{i+1} - x)
     + (y_{i+1} / h - h * m_{i+1} / 6) * (x - x_i)

Where:

  • m_i, m_{i+1} are the second derivatives at x_i and x_{i+1}.
  • h = x_{i+1} - x_i is the distance between the two points.
  • (x_{i+1} - x) and (x - x_i) are the relative distances within the segment.
§Example Usages (Non-code)

This method is typically used for high-precision curve fitting or graphical rendering where smooth transitions between points are essential. Common applications include:

  • Signal processing.
  • Data interpolation for missing values.
  • Smooth graphical representations of mathematical functions.
  • Point2D: Represents a 2D point and is used as input/output for this function.
  • CurveError Represents any error encountered during interpolation.
§Performance
  • The function operates with O(n) complexity, where n is the number of points. The tridiagonal system is solved efficiently using the Thomas algorithm.
  • Every call solves the system again. To read one curve at many abscissas, solve it once with CurveSpline, which returns the same answers.
§Notes
  • Natural spline interpolation may introduce minor deviations beyond the range of existing data points due to its boundary conditions. For strictly constrained results, consider alternative interpolation methods, such as linear or cubic Hermite interpolation.
  • The knots must be a function of their abscissa. Several points at the requested x leave the exact-match branch with no single value to return, and any repeated abscissa collapses a knot interval, so both return InterpolationError::DegenerateInterval rather than picking an ordinate. See Curve::new for the rule.
Source§

impl StatisticalCurve for Curve

Source§

fn get_x_values(&self) -> Vec<Decimal>

Retrieves the x-axis values for the statistical curve. Read more
Source§

fn generate_statistical_curve( &self, basic_metrics: &BasicMetrics, shape_metrics: &ShapeMetrics, range_metrics: &RangeMetrics, trend_metrics: &TrendMetrics, num_points: usize, seed: Option<u64>, ) -> Result<Curve, CurveError>

Generates a statistical curve with properties that match the provided metrics. Read more
Source§

fn generate_refined_statistical_curve( &self, basic_metrics: &BasicMetrics, shape_metrics: &ShapeMetrics, range_metrics: &RangeMetrics, trend_metrics: &TrendMetrics, num_points: usize, max_attempts: usize, tolerance: Decimal, seed: Option<u64>, ) -> Result<Curve, CurveError>

Generates a refined statistical curve that iteratively adjusts to better match the target metrics. Read more
Source§

fn verify_curve_metrics( &self, curve: &Curve, target_metrics: &BasicMetrics, tolerance: Decimal, ) -> Result<bool, CurveError>

Verifies if the metrics of the generated curve match the target metrics within the specified tolerance. Read more
Source§

impl ToSchema for Curve

Source§

fn name() -> Cow<'static, str>

Return name of the schema. Read more
Source§

fn schemas(schemas: &mut Vec<(String, RefOr<Schema>)>)

Implement reference utoipa::openapi::schema::Schemas for this type. Read more

Auto Trait Implementations§

§

impl Freeze for Curve

§

impl RefUnwindSafe for Curve

§

impl Send for Curve

§

impl Sync for Curve

§

impl Unpin for Curve

§

impl UnsafeUnpin for Curve

§

impl UnwindSafe for Curve

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> DeserializeOwned for T
where T: for<'de> Deserialize<'de>,

Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self> ⓘ

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self> ⓘ

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

impl<T> PartialSchema for T
where T: ComposeSchema + ?Sized,

Source§

fn schema() -> RefOr<Schema>

Return ref or schema of implementing type that can then be used to construct combined schemas.
Source§

impl<T> Pointable for T

Source§

const ALIGN: usize

The alignment of pointer.
Source§

type Init = T

The type for initializers.
Source§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
Source§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
Source§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
Source§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<SS, SP> SupersetOf<SS> for SP
where SS: SubsetOf<SP>,

Source§

fn to_subset(&self) -> Option<SS>

The inverse inclusion map: attempts to construct self from the equivalent element of its superset. Read more
Source§

fn is_in_subset(&self) -> bool

Checks if self is actually part of its subset T (and can be converted to it).
Source§

fn to_subset_unchecked(&self) -> SS

Use with care! Same as self.to_subset but without any property checks. Always succeeds.
Source§

fn from_subset(element: &SS) -> SP

The inclusion map: converts self to the equivalent element of its superset.
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T> ToString for T
where T: Display + ?Sized,

Source§

fn to_string(&self) -> String

Converts the given value to a String. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self> ⓘ
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self> ⓘ

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more