Skip to main content

infinite_math_plot 0.1.1 copy "infinite_math_plot: ^0.1.1" to clipboard
infinite_math_plot: ^0.1.1 copied to clipboard

A Flutter package that renders interactive mathematical graphs on a simulated infinite coordinate plane.

Changelog #

All notable changes to this package will be documented here.

The format follows Keep a Changelog, and this project uses Semantic Versioning.


0.1.1 - 2026-05-20 #

This release fixes two rendering bugs that showed up during real-world testing with the example app.

Fixed #

Zoom applies cumulative scale instead of per-frame delta

Flutter's ScaleUpdateDetails.scale is a cumulative value measured from the start of the gesture — it goes 1.0 → 1.5 → 2.0 → 2.5 as you pinch. The previous code passed this directly to the zoom math, so every frame re-applied the full accumulated zoom from scratch. The result was that the viewport would explode or collapse in a single gesture, and the Y axis behaved worse than X because the math-to-screen ratio differs between axes on non-square screens.

The fix: GestureHandler now tracks _lastScale and computes the incremental delta each frame (delta = cumulative / lastScale). Only this small per-frame factor is applied to the viewport. onScaleStart() resets _lastScale = 1.0 at the beginning of each gesture, and the widget calls it via GestureDetector.onScaleStart.

Because _lastScale is mutable state, the GestureHandler constructor is no longer const. The instance is now kept at the widget state level so the scale tracking persists across frames within a gesture.

Steep continuous functions incorrectly broken into fragments

The asymptote detector used a single condition: |next - prev| > viewportHeight * 2. For y = x³ zoomed out to x ∈ [-10, 10], consecutive y-values near the edges (e.g. 729 and 1000) have a jump of 271, which easily exceeded the threshold of 40. The function is perfectly continuous — it's just steep and off-screen on the same side. This caused the curve to be broken into fragments with visible gaps.

The fix: isAsymptote now requires both conditions to be true:

  1. The jump exceeds viewportHeight * 2 — values are far apart in math space.
  2. The values straddle the viewport — one is above yMax and the other is below yMin (or inside). This is the signature of a true asymptote like 1/x or tan(x).

Steep-but-continuous functions like x³ have both consecutive values on the same side of the viewport, so they are no longer broken. isAsymptote now accepts optional yMin and yMax named parameters; the SampleGenerator passes the current viewport bounds when calling it.

Changed #

  • GestureHandler constructor is no longer const (required by the mutable _lastScale field)
  • DiscontinuityDetector.isAsymptote signature extended with optional yMin and yMax named parameters (defaults to double.negativeInfinity / double.infinity for backward compatibility)
  • GestureHandler is now instantiated once in initState and stored in widget state, rather than being recreated on every build
  • pubspec.yaml updated with repository and issue_tracker fields pointing to the GitHub project

0.1.0 - 2026-05-12 #

First public release.

Added #

Core widget

  • InfiniteMathPlot — a StatefulWidget that accepts an equation string and renders an interactive graph
  • Single-equation mode via the equation parameter
  • Multi-equation mode via the equations parameter (list of EquationConfig)
  • Mutual exclusion assertion: providing both equation and equations, or neither, throws at construction time
  • xMin, xMax, yMin, yMax parameters to set the initial viewport (default: -10 to 10 on both axes)
  • showGrid, showAxes, enableZoom, enablePan boolean flags, all defaulting to true
  • graphColor and strokeWidth for single-equation styling
  • samplingPrecision to control sample density (default: 2.0 points per logical pixel)
  • Adaptive layout via LayoutBuilder — fills available space and maintains math aspect ratio on resize

Equation parser

  • Parses Cartesian (y = f(x)), implicit (F(x,y) = 0), parametric (x = f(t), y = g(t)), and polar (r = f(θ)) equations from plain strings
  • Supported functions: sin, cos, tan, asin, acos, atan, sqrt, abs, exp, log, pow
  • Supported constants: pi, π, e, theta, θ
  • ParseException with a human-readable message and character position on invalid input
  • Canonical serialization via serialize(Expression) — stable across round-trips

Sampling

  • Cartesian sampling: iterates x over the viewport, evaluates y = f(x)
  • Polar sampling: iterates θ from 0 to 2π, computes x = r·cos(θ), y = r·sin(θ)
  • Parametric sampling: iterates t from 0 to 2π, evaluates x = f(t) and y = g(t) independently
  • Implicit sampling: marching squares over a 50×50 grid, linear interpolation of zero-crossings
  • Sample cache keyed on (equation, viewport, samplingPrecision, screenWidth) — no recomputation when nothing changes

Discontinuity detection

  • isUndefined: classifies NaN, +Infinity, -Infinity as undefined — path is lifted at these points
  • isAsymptote: detects true vertical asymptotes without breaking steep-but-continuous functions

Rendering

  • GraphPainter (CustomPainter) draws grid → axes → curves in that order
  • Grid interval snaps to "nice" numbers (1, 2, 5, 10, 20, 50, …) based on the current viewport scale
  • Axes drawn only when x=0 or y=0 is within the viewport
  • Tick marks with numeric labels on both axes
  • shouldRepaint returns false when nothing has changed

Gesture handling

  • Pinch-to-zoom centered on the focal point
  • Scroll-wheel zoom centered on the pointer position
  • Drag-to-pan
  • All gestures respect enableZoom and enablePan flags

Coordinate transformer

  • toScreen(x, y) and toMath(screenOffset) with round-trip accuracy < 1e-10

Data models

  • Viewport, ParsedEquation, ParseException, EquationConfig, SampleCacheKey, GraphState, EquationType

Tests

  • 241 tests covering all components, including property-based round-trip tests and widget tests

Upcoming #

  • Configurable parametric t-range (currently fixed at 0 to 2π)
  • Tap-to-inspect: show the y-value at a tapped x position
  • Isolate-based sampling for very high precision or many simultaneous equations
  • Animation support for time-varying equations
  • Export to image

1
likes
130
points
12
downloads

Documentation

API reference

Publisher

unverified uploader

Weekly Downloads

A Flutter package that renders interactive mathematical graphs on a simulated infinite coordinate plane.

Repository (GitHub)
View/report issues

License

MIT (license)

Dependencies

flutter, math_expressions

More

Packages that depend on infinite_math_plot