Closed samreid closed 2 years ago
I made good progress creating an Interval
type, but after discussion with @pixelzoom we are wondering if this can be accomplished in the transform.
Here's a patch that uses Interval
:
Instead, we are wondering if we can accomplish this by keeping the same Range in the model, but specifying the transform function so that it can accomplish this flip. I'll take a look.
@pixelzoom also indicated that this isn't critical to implement immediately, but will be good to do before we have a sim that needs this feature.
I think I have a better understanding of what is happening here. There are 2 transforms at play. The first, such as xTransform
is a model-based transform that specifies a mapping for the data. The second is a linear transform which is currently hardcoded like so:
// For vertical, +y is usually up
return axisOrientation === Orientation.HORIZONTAL ?
Util.linear( transform.evaluate( modelRange.min ), transform.evaluate( modelRange.max ), 0, viewDimension, transformedValue ) :
Util.linear( transform.evaluate( modelRange.max ), transform.evaluate( modelRange.min ), 0, viewDimension, transformedValue );
Note that (in the x-direction) the linear functions map the minimum (transformed) model value to the left edge and the maximum (transformed) model value to the right edge. We can flip the axis if we invert this linear transform like so:
// Map the minimum of the transformed model range to the right edge
Util.linear( transform.evaluate( modelRange.min ), transform.evaluate( modelRange.max ), viewDimension, 0, transformedValue )
To summarize, there are 2 transforms:
Would it be possible to somehow combine these? How would that even look? If we keep them separate, what should the API be for allowing the client to customize the latter transform?
Having 2 places where the transform is handled is definitely problematic. What we seem to need is something like ModelViewTransform2 that handles non-linear transforms. bamboo will be significantly disadvantaged if we're constrained to linear mappings with +x left and +y up. Let's add @jonathanolson to the discussion to see if he has any ideas.
What do you need out of the transforms? Do we NEED to know when it's linear, for optimizations? Could you just accept any invertible function (presumably specifying a function and its inverse?)
Please review https://github.com/phetsims/bamboo/issues/39#issuecomment-862602848 which describes the nonlinear model-oriented transform (which is supported by function + inverse), and the subsequent linear view-oriented transform (which "sizes" the transformed data to fit the chart view). It makes sense to separate these 2 transforms, so that the nonlinear model transform can be specified independently of the size of the chart.
So if we have separate transforms, the potentially non-invertible one could presumably just have a similar API to LinearFunction?
e.g. accept
export type InvertibleFunction = {
evaluate( n: number ): number;
inverse( n: number): number;
};
so then LinearFunction would satisfy it automatically?
I've also used map/inverse before.
ModelViewTransform2's API would be fairly difficult to generalize to arbitrary nonlinear mappings. It would require a few derivatives to be computed, for shape/bounds it would probably require discretization (or custom logic), etc.
I don't think we want a fully general nonlinear API for the view transform. (That is already supported in the model transform). Instead, we would like to say that instead of the chart going from (-4,4) we want it to go from (4,-4). However, if we also want to power it with our Range class that won't be possible since range requires min<max. Instead, I added booleans:
public modelXRangeInverted: boolean;
public modelYRangeInverted: boolean;
And tested that both are working well in the demos. I left an example of the x one committed, and it looks like this:
For the y one I tested temporarily and confirmed it was working nicely, but decided not to commit since I feel the upside-up one is a better initial demo.
@pixelzoom would you like to review?
I guess that's sufficient. We'll see how it works out when someone needs an inverted range in practice. Closing.
From https://github.com/phetsims/bamboo/issues/27#issuecomment-861887346 @pixelzoom said:
I can imagine that we would need a chart which has decreasing values going up vertically. (Not sure about decreasing values going to the left), but I think we should add support for both.