-
Notifications
You must be signed in to change notification settings - Fork 39
Add Support for Coordinate Conversion #88
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
Add Support for Coordinate Conversion #88
Conversation
|
Ok, overhauled all of the annotations to have an array of |
|
Ok, now I'm very confused on how I'm supposed to write the function in Some things I am wondering:
|
|
@WilliamHYZhang I think currently the origin for the plot bounding box is shifted/unshifted by a set amount. But the origin of the actual plot is calculated at Line 227 of LineChart.swift. The absolute point shouldn't depend on the renderer. The scaling logic should be in the calculateMarkers() function on Line 271 of LineChart.swift if I understand correctly. Why do you have an array of Coordinates in the annotation? Instead replace the location with a Coordinate. Add a coordinate space parameter to the constructor and then you can initialize the location. You can then process the Coordinate accordingly. If you need the available width and height that is calculated in the boundsDidChange() function on Line 216 of LineChart.swift. If you're thinking about the shifting/unshifting of the origin of the plot bounding box, I think you can simply scale the points and draw them using renderer.withAdditionalOffset on Line 473 of GraphLayout.swift. This is what I could understand by a brief look at the updated code. I haven't had a chance to go through it in detail. @karwa can you please confirm? |
|
@KarthikRIyer thanks for the detailed comments, appreciate it very much. I'll look through the parts of LineChart.swift where you specified. I was under the impression that this conversion was to be done in GraphLayout.swift. Some annotations don't have location, such as arrow, which has start and end. In order to generalize the conversion we can add these to an array and just have GraphLayout.swift iterate through it and convert all of the coordinates. |
Although this might work, but it will make the code a lot harder to read and understand. I'd recommend having separate variables. For drawing simple stuff like boxes/arrows I don't think the overhead would be too much. In case we come across a situation where we need to draw many polylines/polygons we could think of a something like EBOs in OpenGL. But for now it would be better to keep it simple. |
|
So have a separate case for dealing with arrows? My main concern is that the GraphLayout.swift doesn't know the specific annotation, just the fact that it is of type Annotation. Will we have to downcast it? |
|
I'm not sure I understand you correctly. I was thinking could have some HelperFunction that takes in a Coordinate/Coordinates and returns the Point/Points in image space. So we convert the locations or points to image space, do the necessary calculations and use the result to draw the annotations. The type of annotation wouldn't matter. The annotation protocol wouldn't change. We do stuff specific to each annotation inside it's struct. |
|
So this conversion would take place in the specific annotation itself? Previously I was told to convert it in GraphLayout.swift, in which case the type of the annotation isn't known. |
I might have forgotten or overlooked this discussion. Could you please point me to where this was discussed? |
From #76 |
|
Oh ok. @karwa any thoughts? |
This reverts commit 5bcf936.
|
Hmm... well we need some way to inject the coordinate conversion logic in to the annotation, so it knows where to draw its points. One idea might be to have a protocol, let's call it a We could have I think this makes sense: plots shouldn't draw outside of their bounding rectangle, so they're only given a size and don't know about their location inside the figure. Annotations definitely do want to draw inside or outside of the figure, so they need this additional information whereas the plots don't. (of course, plots can draw outside of their rectangle -- we don't clip them. But the border, axes markers, labels, etc might be drawn on top of their data if they do that) |
|
Thank you for your ideas! They are very helpful. I like the idea of a function to resolve the coordinate, but I'm a bit confused why this has to be a protocol.
Could you provide some psuedocode for how we would implement this part? |
|
@WilliamHYZhang I'm not sure how a protocol might help, maybe if we have a protocol we could have a customized implementation if we require it someplace else. You could have GraphLayout.Result conform to this protocol and as @karwa said it knows everything abouy where the plot is drawn in the figure. In the drawForeground function where you've called the drawAnotations function you could have something like: drawAnnotations(results: results, renderer: renderer)In GraphLayout.Results you need to implement the function resolve that will return a Point in the image space based on the data available in the Coordinate. And in draw Annotation you'll resolve each point before drawing like In the resolve function it could be something like this: struct Results {
...
func resolve(_ coordinate: Coordinate) -> Point{
switch(coordinate.coordinateSpace){
case .ndc:
//code to convert
return point
...
}
}
} |
|
Yes, basically this. The annotations should have a method: and then we pass in the results object or whatever as our resolver. As for why it's a protocol - because it's useful to abstract the resolving function. It documents exactly what we need from the layout object and allows us to maybe use different resolvers or layout objects in the future. One thing that we'll need to think about is how we deal with data coordinates. Technically, our chart data is defined in terms of We might eventually have to make |
|
Alright, I'll try to scrape together a proof of concept first, and then we can work on the details with the coordinate dealing stuff. |
|
Tried to implement the basic structure of the idea, however builds failing saying there are undeclared types, is this because I defined them in another file? Confused with these errors, don't know what I'm doing wrong. Also, how would the arguments/variables used in From what I've been able to gather, it seems as if Thanks for clarification. |
|
With regards to how to calculate the coordinates:
Referring to the coordinate spaces in matplotlib: Using this, you should be able to implement 4 of these relatively easily ( |
|
Regarding the coordinate space, I thought we only had two? Update: Fixed build errors and, all there is left to do is implement the resolver. |
|
Implemented the resolve function cases for both The most important coordinate case, however, is |
|
We don't really have a distinction between points and pixels at the moment. Typically, points are the high-level coordinates that you use to lay things out, and then they get converted to pixels based on how you render the image (e.g. if you render at 2x, like for a Retina display, each 1x1 square of points contains 4 pixels). You don't need to worry about data coordinates right now IMO - that's significantly more complicated, because our data is defined using generic types. Eventually we'll need the |
|
Ah, ok. I'll leave the current cases in this PR as they are. This skeletal coordinate implementations should be good to merge once the build fix PR is merged. In the meantime, is there any way we can scale the points just for the annotations, so we don't have to essentially "guess and check" to find the correct locations to pass? |
Do you mean for the points/pixel thing? I think we should just leave that out for now. We can add it once it's actually supported, but for now there isn't any point to adding it. The only changes I would make to this PR are to implement the |
I was referring to a workaround of the I'll update the PR with the |
|
@WilliamHYZhang have you tried merging the latest commits ? It allows the tests to pass. |
…to coordinate_conversion
|
Yep, thanks @karwa for test fixes. |
|
Alright, added resolving for fraction support as well. @KarthikRIyer @karwa should be good to merge on your review. |
|
Looks good @WilliamHYZhang ! Thanks for your work! Merging. |
This is going to be an in-progress PR for coordinate conversion. Note that at some points, the PR build is going to fail. Resolves #76