This math is not platform specific and I'll take any language as an answer. This is difficult to explain why I'm doing this, but I'll try to include images.
I have a view (View A) that overlays a map as a container. The purpose is to contain our content while remaining fixed to the map as the user drags the map. That view has a coordinate system where it's origin is in the top left of the screen. It will be our absolute coordinate system, where we are trying to convert the positions to and from.
Next, we have a Rectangle that is formed in the intersection between View A and what is visible on the screen. I achieved that with the following property in my UIView:
var visibleRect: CGRect {
guard let superview = self.superview?.superview else {
return CGRect(x: 0, y: 0, width: 0, height: 0)
}
// Convert the superview's coordinate system to the current view's coordinate system and find the intersecting rectangle. This is so we don't have to render excessive particles.
let val = self.bounds.intersection(
self.convert(superview.frame, from: superview)
)
return val
}
This returns said Rectangle with an origin relative to the origin of View A. The purpose of this Rectangle is that Metal View cannot be too large, so I limited Metal View to drawing within what is visible exclusively while maintaining the exact coordinates of where Metal View will be drawn in relation to View A.
I've been able to verify that the relative origin of the Rectangle within View A is accurate, and I've verified that Metal View fits within the Rectangle.
Here's what I keep banging my head on: Metal vertex functions have a center coordinate system that spans from -1
to 1
for the entire width and height as shown in the following figure (except I'm only using it in 2D space so ignore z position):
Now my question is:
If I have a point found in the top left quadrant of the Metal View (-0.002, 0.5), how would I take the given information to find it's position in View A? How would I return the point's position in View A to Metal View accounting for the relatively positioned Rectangle?
Visual
Here's a visual for hopeful clarification:
Edit
I was able to convert from View A to Metal View if Metal View takes up the entire span of View A with the following text code:
def normalizedToViewA(x, y):
x *= 1.0
y *= -1.0
x = 1.0
y = 1.0
return ((x / 2.0) * width, (y / 2.0) * height)
def viewAToNormalized(x, y):
normalizedX = x / (width / 2.0)
normalizedY = y / (height / 2.0)
normalizedX -= 1.0
normalizedY -= 1.0
normalizedX *= 1.0
normalizedY *= -1.0
return (normalizedX, normalizedY)
But now I need to calculate as if Metal View fills the Rectangle which is only a portion of View A.
CodePudding user response:
I found the answer and have used Python for legibility.
View A is 1270*680.
# View A (Top Left Origin)
width = 1270
height = 680
# Visible Rectangle (Top Left Origin)
# with an origin as a position in View A
subOriginX = 1000
subOriginY = 400
subWidth = 20
subHeight = 20
# Centered origin converted to top left origin
# where origin is (0,0)
def normalizedToSubview(x, y):
x *= 1.0
y *= -1.0
x = 1.0
y = 1.0
return ((x / 2.0) * subWidth, (y / 2.0) * subHeight)
# Top Left origin to centered origin
def subviewToNormalized(x, y):
normalizedX = x / (subWidth / 2.0)
normalizedY = y / (subHeight / 2.0)
normalizedX -= 1.0
normalizedY -= 1.0
normalizedX *= 1.0
normalizedY *= -1.0
return (normalizedX, normalizedY)
# Relative position of a point within subview
# but on View A's plane
def subviewToViewA(x, y):
return (x subOriginX, y subOriginY)
# Relative position of a point within View A
# but on the subview's plane
def viewAToSubView(x, y):
return (x - subOriginX, y - subOriginY)
# Position within Metal View to a position within View A
normalizedCoord = (0.0, 0.0)
toSubview = normalizedToSubview(*normalizedCoord)
viewACoord = subviewToViewA(*toSubview)
print(f"Converted {normalizedCoord} to {toSubview}")
print(f"Converted {toSubview} to {viewACoord}")
# Converted (0.0, 0.0) to (10.0, 10.0)
# Converted (10.0, 10.0) to (1010.0, 410.0)
# Position within View A to Metal View
backToSubview = viewAToSubView(*viewACoord)
backToNormalized = subviewToNormalized(*backToSubview)
# Converted (1010.0, 410.0) to (10.0, 10.0)
# Converted (10.0, 10.0) to (0.0, -0.0)
print(f"Converted {viewACoord} to {backToSubview}")
print(f"Converted {backToSubview} to {backToNormalized}")
This is an extremely niche problem, but please comment if you are facing something similar and I will try to expand the best that I can.