I'm trying to convert coordinates from any given coordinate system (be they the coordinates of a graph figure or a map, meaning they can span across both negative and positive values across any of the four +- quadrants), over to screen coordinates. I also want an easy way as part of the solution to be able to zoom to a small area within the coordinate system.
I already tried an algorithm of my own, which was overly complicated and would fail on occasion (for simplicity I have now removed it from the post).
Thanks to the helpful answers below, especially by Martin F, I now have a solution that works as expected with all types of coordinate systems, be they drawing, geographical, negative, flipped, etc. Specifically this has been a great addition to three Python libraries I've been working on: for autozooming to a geographical entity in Shapy, for drawing any kind of coordinates on an image in PyDraw, and for map zooming in GeoVis.
Martin's answer describes the theoretical ideal of how to do it, but here's how I did it for my case. The user specifies the topleft and bottomright xy corners in the coordinate system of their data which they want to appear in the same corners on a graphical image, thus allowing zooming and flipping sides/updown. In my case the graphics drawer has its 0,0 coordinate in the topleft corner. To prepare the equation I just needed a single scalex/y variable.
I also added how I constrained the dimensions to keep them the same size, which can be useful in many cases.
#input IMG = ... XLEFT,YTOP,XRIGHT,YBOTTOM = ... CONSTRAIN = True #constrain dimensions to avoid distortion if CONSTRAIN: xwidth = max(XLEFT,XRIGHT) - min(XLEFT,XRIGHT) yheight = max(YTOP,YBOTTOM) - min(YTOP,YBOTTOM) if xwidth > yheight: YBOTTOM = YTOP+xwidth elif yheight > xwidth: XRIGHT = XLEFT+yheight #prepare scale values imgwidth = float(IMG.width) imgheight = float(IMG.height) scalex = imgwidth / (XRIGHT - XLEFT) scaley = 0 - imgheight / (YTOP - YBOTTOM)
With that, the coordinate conversion of
iny is calculated as:
newx = scalex * (inx - XLEFT) newy = imgheight + scaley * (iny - YBOTTOM)