leva icon indicating copy to clipboard operation
leva copied to clipboard

Feature : custom user functions for the plot plugin interpreter.

Open tcoppex opened this issue 2 years ago • 7 comments

Hey everyone,

So I'm interested into adding custom functions - like smoothstep - to the plot plugin using the import function of the underlying mathjs library.

Here is a proof of concept implementation which allow the user to provide an imported attribute to the plot function accepting a dictionnary of functions.

For example :

plot( { 
  expression: 'mix(0, 1, x)',
  imported: {
    mix: (a: number, b: number, x: number) => {
      return a + (b - a) * x
    })

The idea is to define the functions in a general dictionnary once and pass it to a plot wrapper for the whole app, as each plot will instanciate mathjs before evaluation to import its custom functions (a bit of a caveat I suppose).

Here's a simplified clojurescript version of what I'm using for example :

(def custom-mathjs-functions {:smoothstep #(.smoothstep THREE/MathUtils %3 %1 %2)})

(defn plot-expr
  [expr]
  (plot (clj->js {:expression expr
                  :boundsX [0 1] 
                  :boundsY [0 1]
                  :graph true
                  :imported custom-mathjs-functions})

So it might become cumbersome for larger functions dictionnaries.

tcoppex avatar Apr 29 '22 21:04 tcoppex

⚠️ No Changeset found

Latest commit: 89d4eb96e4dbb583c611c96fdb41084c1d8d9e2f

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

changeset-bot[bot] avatar Apr 29 '22 21:04 changeset-bot[bot]

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Updated
leva ✅ Ready (Inspect) Visit Preview May 7, 2022 at 4:56PM (UTC)

vercel[bot] avatar Apr 29 '22 21:04 vercel[bot]

This pull request is automatically built and testable in CodeSandbox.

To see build info of the built libraries, click here or the icon next to each commit SHA.

Latest deployment of this branch, based on commit 89d4eb96e4dbb583c611c96fdb41084c1d8d9e2f:

Sandbox Source
pmndrs/leva Configuration
pmndrs/leva Configuration
leva-scroll Configuration
pmndrs/leva Configuration
leva-ui Configuration
leva-theme Configuration
leva-transient Configuration
leva-plugin-plot Configuration
pmndrs/leva Configuration
leva-plugin-spring Configuration
leva-custom-plugin Configuration

codesandbox-ci[bot] avatar Apr 29 '22 21:04 codesandbox-ci[bot]

This is very cool! I don't see the clunkyness as a big problem 🤔

What would happen if the user tried to import the same expression twice? If it fails silently, we can just leave that to the user - assuming they'd read docs

gsimone avatar Apr 30 '22 10:04 gsimone

Hi @gsimone and thanks for you review.

Yes as mentionned above multiple imports on the same symbols fails (the plot also fails to render properly). I guess if we want to avoid recreating an instance we can check symbols on a map / set but it seems overkill.

Also we might want to discuss the proper keyword to use for this, imported is a bit broad but does the job also.

Cheers.

tcoppex avatar May 07 '22 17:05 tcoppex

@tcoppex

Maybe we could think of an alternate api where we extend the plot fn? eg.

// imagine using it in a setup file

plot.extend({ mix: ... }) 
// calling this again would not fail as we can in an object wether we already extend 

gsimone avatar May 09 '22 08:05 gsimone

Good idea that might be worth a try. Looking into it I'm not sure how to go about it though, do you have an idea for the actual implementation ?

It seems the advantage of the current implementation is to be able to extend plots individually, for example by giving previous functions / symbols to the next plot (à la graphtoy).

So maybe we can go with both ideas : a default extend initialization and a per-plot assignement.

tcoppex avatar May 14 '22 12:05 tcoppex