Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enable Setting of Domain for X & Y Parametric Plots #166

Merged
merged 5 commits into from
Jul 21, 2024
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 9 additions & 5 deletions src/display/Plot/OfX.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,24 @@ import { usePaneContext } from "../../context/PaneContext"
import { Parametric, ParametricProps } from "./Parametric"
import { vec } from "../../vec"

export interface OfXProps extends Omit<ParametricProps, "xy" | "t"> {
export interface OfXProps extends Omit<ParametricProps, "xy" | "domain" | "t"> {
y: (x: number) => number
domain?: {min?: number, max?: number}
svgPathProps?: React.SVGProps<SVGPathElement>
}

export function OfX({ y, ...props }: OfXProps) {
export function OfX({ y, domain, ...props }: OfXProps) {
const {
xPaneRange: [xMin, xMax],
xPaneRange: [xpMin, xpMax],
} = usePaneContext()
// Determine the most restrictive range values (either user-provided or the pane context)
const xMin = Math.max(xpMin, domain?.min ?? -Infinity)
const xMax = Math.min(xpMax, domain?.max ?? Infinity)

const xy = React.useCallback<ParametricProps["xy"]>((x) => [x, y(x)], [y])
const t = React.useMemo<vec.Vector2>(() => [xMin, xMax], [xMin, xMax])
const parametricDomain = React.useMemo<vec.Vector2>(() => [xMin, xMax], [xMin, xMax])

return <Parametric xy={xy} t={t} {...props} />
return <Parametric xy={xy} domain={parametricDomain} {...props} />
}

OfX.displayName = "Plot.OfX"
14 changes: 9 additions & 5 deletions src/display/Plot/OfY.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,24 @@ import { usePaneContext } from "../../context/PaneContext"
import { Parametric, ParametricProps } from "./Parametric"
import { vec } from "../../vec"

export interface OfYProps extends Omit<ParametricProps, "xy" | "t"> {
export interface OfYProps extends Omit<ParametricProps, "xy" | "domain" | "t"> {
x: (y: number) => number
domain?: {min?: number, max?: number}
mark-fitzgerald marked this conversation as resolved.
Show resolved Hide resolved
svgPathProps?: React.SVGProps<SVGPathElement>
}

export function OfY({ x, ...props }: OfYProps) {
export function OfY({ x, domain, ...props }: OfYProps) {
const {
yPaneRange: [yMin, yMax],
yPaneRange: [ypMin, ypMax],
} = usePaneContext()
// Determine the most restrictive range values (either user-provided or the pane context)
const yMin = Math.max(ypMin, domain?.min ?? -Infinity)
const yMax = Math.min(ypMax, domain?.max ?? Infinity)

const xy = React.useCallback<ParametricProps["xy"]>((y) => [x(y), y], [x])
const t = React.useMemo<vec.Vector2>(() => [yMin, yMax], [yMin, yMax])
const parametricDomain = React.useMemo<vec.Vector2>(() => [yMin, yMax], [yMin, yMax])

return <Parametric xy={xy} t={t} {...props} />
return <Parametric xy={xy} domain={parametricDomain} {...props} />
}

OfY.displayName = "Plot.OfY"
34 changes: 31 additions & 3 deletions src/display/Plot/Parametric.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,18 @@ import { Stroked } from "../Theme"
import { useTransformContext } from "../../context/TransformContext"
import { sampleParametric } from "./PlotUtils"

export interface ParametricProps extends Stroked {
// TODO: In 1-year's time from this change (written 6/26/2024),
// remove the Legacy interface and just have the new props interface (renamed, of course).
// Also, remove the `t` property at that time.
// The 1 year timeline gives consumers time to update their code.
stevenpetryk marked this conversation as resolved.
Show resolved Hide resolved
interface ParametricPropsLegacy extends Stroked {
/** A function that takes a `t` value and returns a point. */
xy: (t: number) => vec.Vector2
/** The domain `t` between which to evaluate `xy`. */
/** The domain between which to evaluate `xy`. */
domain?: never
/**
* @deprecated - use the `domain` prop.
*/
t: vec.Vector2
/** The minimum recursive depth of the sampling algorithm. */
minSamplingDepth?: number
Expand All @@ -17,8 +25,28 @@ export interface ParametricProps extends Stroked {
svgPathProps?: React.SVGProps<SVGPathElement>
}

interface ParametricPropsNew extends Stroked {
/** A function that takes a `t` value and returns a point. */
xy: (t: number) => vec.Vector2
/** The domain between which to evaluate `xy`. */
domain: vec.Vector2
/**
* @deprecated - use the `domain` prop.
*/
t?: never
/** The minimum recursive depth of the sampling algorithm. */
minSamplingDepth?: number
/** The maximum recursive depth of the sampling algorithm. */
maxSamplingDepth?: number

svgPathProps?: React.SVGProps<SVGPathElement>
}

export type ParametricProps = ParametricPropsNew | ParametricPropsLegacy

export function Parametric({
xy,
domain,
t,
color,
style = "solid",
Expand All @@ -33,7 +61,7 @@ export function Parametric({
// Negative because the y-axis is flipped in the SVG coordinate system.
const pixelsPerSquare = -vec.det(viewTransform)

const [tMin, tMax] = t
const [tMin, tMax] = domain || t
const errorThreshold = 0.1 / pixelsPerSquare

const svgPath = React.useMemo(
Expand Down
Loading