Mathematics & Utilities
Relevant source files
The following files were used as context for generating this wiki page:
SwiftDitherKit relies on a robust mathematical foundation to translate raw data points into dithered visual marks. This module handles coordinate scaling, geometry calculation for various chart types, hit-testing for interactivity, and value formatting for accessibility and UI display.
The utility layer ensures that data is normalized correctly according to the chosen DitherStacking mode and that visual elements like "sparkles" are placed accurately relative to the chart's data bands.
Geometry and Band Calculation
The core of the charting logic resides in DitherGeometry, which transforms DitherDatum and DitherSeries into a series of DitherBand objects. These bands define the lower and upper bounds of a mark in data space.
Stacking Logic
SwiftDitherKit supports three primary stacking modes that dictate how bands are computed:
- Overlaid: Each series starts at a baseline of zero.
- Stacked: Series are piled on top of each other, with positive values stacking upward and negative values downward from zero.
- Percent: Like stacked, but normalized so that the total positive or negative magnitude equals 1.0.
Sources: DitherTypes.swift:54-62, DitherMath.swift:23-32
The following flowchart illustrates the high-level logic for band computation:
This diagram shows the decision path for transforming raw input data into geometric bands based on the stacking configuration. Sources: DitherMath.swift:23-32
Cartesian Mapping
Utility functions handle the mapping of indices to physical coordinates on the screen:
nearestIndex: Finds the closest data point index based on a horizontal touch/mouse location.xCenter: Calculates the horizontal center of a mark (used for line and area charts).barBand/barSlot: Determines the specific X-coordinate and width for bars, accounting for padding and subdivisions in grouped bar charts.
Sources: DitherMath.swift:34-80
Coordinate Scaling
The DitherLinearScale struct converts values from the data domain to the view's pixel range. It automatically calculates "nice" numbers for axis ticks to ensure readability.
Scale Parameters
| Parameter | Type | Description |
|---|---|---|
lowerBound | Double | The calculated minimum value of the scale (inclusive of 0). |
upperBound | Double | The calculated maximum value of the scale. |
height | CGFloat | The available vertical space in the plot area. |
Sources: DitherMath.swift:277-293
The scaling mechanism ensures that the chart always includes zero in the domain and adjusts the step size based on a niceNumber algorithm, which rounds intervals to powers of 10 or common multipliers (1, 2, 5).
Sources: DitherMath.swift:302-321
Interactivity and Hit-Testing
Interactivity is managed via the DitherSelectionHitTester. It uses geometric calculations to determine which series a user is interacting with based on a CGPoint.
Continuous vs. Discrete Hit-Testing
- Continuous (Area/Line): Uses linear interpolation between data points to check if the touch point falls between the
lowerandupperbounds of a specific series band at that X-position. - Discrete (Bar): Iterates through defined bar rectangles (slots) to check if the point is contained within the rendered bar's boundaries.
Sources: DitherMath.swift:145-234
This sequence diagram describes the flow of identifying a selected series when a user taps or drags across the chart surface. Sources: DitherMath.swift:145-168
Value Formatting
The DitherValueFormat enum provides localized formatting for numeric values across axes, tooltips, and accessibility labels.
| Format Case | Description | Example (en_US) |
|---|---|---|
.automatic | Compacts large values (1K+) and preserves 2 decimals for small values. | 1.2K or 123.45 |
.number | Standard numeric formatting with specified precision. | 1.23 |
.percent | Multiplies by 100 and adds the percent symbol. | 25% |
.currency | Formats according to ISO 4217 currency codes. | $12.50 |
Sources: DitherFormatting.swift:6-60
Sparkle Generation
For Area, Line, and Sparkline charts, the DitherSparkleField utility generates decorative "sparkles" that follow the contour of the data.
Generation Logic
- Band Sampling: The utility samples the upper and lower bands of the data.
- Resampling: Data points are resampled to match the pixel width of the raster.
- Placement: Sparkles are placed at pseudo-random positions (seeded for stability) between the top and floor of each series' band.
- Motion: The
DitherSparkleMotionutility calculates twinkle intensity and "flare" alpha based on a time interval (tickIntervalof 0.1s).
Sources: DitherSparkles.swift:22-68, DitherSparkles.swift:110-149
Conclusion
The Mathematics & Utilities module provides the deterministic logic required to render complex charts as simple rasters. By separating coordinate scaling, geometric band computation, and hit-testing into specialized utilities, SwiftDitherKit maintains high performance and accuracy while supporting diverse chart types and interactive states.