手动将坐标转换为点到视图
Manual convertCoordinate toPointToView
不知道有没有人手工计算过将WGS84坐标映射到UIView坐标系?事实上,我将 WGS84 转换为类似于笛卡尔 (x,y,z) 坐标系的 ENU 坐标系。
我知道 MKMapView 中有一个方法可以在预期的 UIView 中获取 CLLocationCoordinate2D 和 returns CGPoint,但我想在空白 UIView 而不是地图上绘制 CGPoint。因此我想跳过初始化 MKMapView 对象只是为了使用这个方法。
必须有一种简单的方法可以将坐标从笛卡尔坐标系缩小到设备坐标系。我想我还需要某种形式的 rotation/transformation 作为系统原点(笛卡尔-> UIView),因为 UIView 的原点位于左上角。
缩小坐标应该是直截了当的。
假设您有一组坐标围绕着一个荒谬的点 (32000, 192033)。这是该特定集群的中心点。
显然我们要移动它们,使它们以原点 (0, 0) 为中心。
所以取每一点并使用...转换它
newPoint = CGPointMake(oldPoint.x - 32000, oldPoint.y - 192033)
这将使它们全部相距相同的相对距离,但现在以原点为中心。
接下来,假设 X 的最小值是 -9345,X 的最大值是 8455。
您希望 X 范围大约为 640(以适合整个屏幕)。
所以...
currentXRange = 8455 + 9345; // maxX - minX = 17800
requiredXRange = 640;
xScale = requiredXRange / currentXRange; // 0.0359...
现在您有了 x 刻度,您可以通过将 x 坐标乘以 xScale
值来转换点数。
您拥有的最小 X 值将为...
-9345 * xScale; // -335.4...
最大 X 值将为...
8455 * xScale; // 303.5...
编辑,使它们出现在屏幕上
为了让它们都大于 0。(即它们都在屏幕上)只需从每个点中减去最小的 X 和 Y 坐标值。
-335.4 - (-335.4) = 0 // minimum X value
303.5 - (-335.4) = 638.9 // maximum X value
这使它们都在范围内,以便它们适合屏幕。
编辑颠倒 Y 轴
为了确保它们以正确的方式向上显示,只需通过从视图高度中减去它们来创建点。
如果视图大小为 (100, 100),则 iOS 中的点 (50, 10) 将位于视图顶部附近的中间。
但正常使用应该在底部附近。
因此使用...创建转换点...
convertedPoint = CGPointMake(originalPoint.x, view.height - originalPoint.y)
这将创建点 (50, 90),它将把它放在中间,并根据需要从底部开始十个点。
注意
只要对集合中的每个点进行相同的操作,那么它们都会在相同的相对位置,数据仍然有效。
棘手的部分是计算操作,但我想我已经涵盖了所有内容。
@Fogmeister,尽管你的回答在论文中是有道理的,但我不知道为什么我不能让它工作。我在 enus 数组中有位置。我首先找到了 minx, miny, maxx, maxy
let sortX = enus.sort({ [=10=].epos < .epos })
let sortY = enus.sort({ [=10=].npos < .npos })
let minx = sortX.first?.epos
let maxx = sortX.last?.epos
let miny = sortY.first?.npos
let maxy = sortY.last?.npos
然后我找到了范围:
let xrange = abs(maxx!-minx!)
let yrange = abs(maxy!-miny!)
然后我找到比例因子:
let xscale = self.frame.size.width.asDouble / xrange
let yscale = self.frame.size.height.asDouble / yrange
let factor = (xscale <= yscale ? xscale : yscale)
然后在一个循环中,我使用 factor 和 minx 和 miny 来缩小和移动我的 enu 位置:
points.removeAll()
let minx_scaled = minx * factor
let miny_scaled = miny * factor
for enu in enus {
let e_scaled = enu.epos * factor
let n_scaled = enu.npos * factor
let x = e_scaled - minx_scaled
var y = n_scaled - miny_scaled
y = self.frame.size.height.asDouble - y
let point = CGPointMake(x.asCGFloat,y.asCGFloat)
points.append(point)
}
这里我要点:
private let path1 = UIBezierPath()
var moved = false
override func drawRect(rect: CGRect) {
if points.count == 0 { return}
if moved == false {
path1.moveToPoint(points.first!)
moved = true
}else{
path1.addLineToPoint(points.last!)
}
path1.lineWidth = 3
path1.lineJoinStyle = .Round
UIColor.whiteColor().setStroke()
path1.stroke()
}
下图是我在其中绘制 UIBezierPath 的空白 UIView。我用了一点mapview作为参考。
不知道有没有人手工计算过将WGS84坐标映射到UIView坐标系?事实上,我将 WGS84 转换为类似于笛卡尔 (x,y,z) 坐标系的 ENU 坐标系。
我知道 MKMapView 中有一个方法可以在预期的 UIView 中获取 CLLocationCoordinate2D 和 returns CGPoint,但我想在空白 UIView 而不是地图上绘制 CGPoint。因此我想跳过初始化 MKMapView 对象只是为了使用这个方法。
必须有一种简单的方法可以将坐标从笛卡尔坐标系缩小到设备坐标系。我想我还需要某种形式的 rotation/transformation 作为系统原点(笛卡尔-> UIView),因为 UIView 的原点位于左上角。
缩小坐标应该是直截了当的。
假设您有一组坐标围绕着一个荒谬的点 (32000, 192033)。这是该特定集群的中心点。
显然我们要移动它们,使它们以原点 (0, 0) 为中心。
所以取每一点并使用...转换它
newPoint = CGPointMake(oldPoint.x - 32000, oldPoint.y - 192033)
这将使它们全部相距相同的相对距离,但现在以原点为中心。
接下来,假设 X 的最小值是 -9345,X 的最大值是 8455。
您希望 X 范围大约为 640(以适合整个屏幕)。
所以...
currentXRange = 8455 + 9345; // maxX - minX = 17800
requiredXRange = 640;
xScale = requiredXRange / currentXRange; // 0.0359...
现在您有了 x 刻度,您可以通过将 x 坐标乘以 xScale
值来转换点数。
您拥有的最小 X 值将为...
-9345 * xScale; // -335.4...
最大 X 值将为...
8455 * xScale; // 303.5...
编辑,使它们出现在屏幕上
为了让它们都大于 0。(即它们都在屏幕上)只需从每个点中减去最小的 X 和 Y 坐标值。
-335.4 - (-335.4) = 0 // minimum X value
303.5 - (-335.4) = 638.9 // maximum X value
这使它们都在范围内,以便它们适合屏幕。
编辑颠倒 Y 轴
为了确保它们以正确的方式向上显示,只需通过从视图高度中减去它们来创建点。
如果视图大小为 (100, 100),则 iOS 中的点 (50, 10) 将位于视图顶部附近的中间。
但正常使用应该在底部附近。
因此使用...创建转换点...
convertedPoint = CGPointMake(originalPoint.x, view.height - originalPoint.y)
这将创建点 (50, 90),它将把它放在中间,并根据需要从底部开始十个点。
注意
只要对集合中的每个点进行相同的操作,那么它们都会在相同的相对位置,数据仍然有效。
棘手的部分是计算操作,但我想我已经涵盖了所有内容。
@Fogmeister,尽管你的回答在论文中是有道理的,但我不知道为什么我不能让它工作。我在 enus 数组中有位置。我首先找到了 minx, miny, maxx, maxy
let sortX = enus.sort({ [=10=].epos < .epos })
let sortY = enus.sort({ [=10=].npos < .npos })
let minx = sortX.first?.epos
let maxx = sortX.last?.epos
let miny = sortY.first?.npos
let maxy = sortY.last?.npos
然后我找到了范围:
let xrange = abs(maxx!-minx!)
let yrange = abs(maxy!-miny!)
然后我找到比例因子:
let xscale = self.frame.size.width.asDouble / xrange
let yscale = self.frame.size.height.asDouble / yrange
let factor = (xscale <= yscale ? xscale : yscale)
然后在一个循环中,我使用 factor 和 minx 和 miny 来缩小和移动我的 enu 位置:
points.removeAll()
let minx_scaled = minx * factor
let miny_scaled = miny * factor
for enu in enus {
let e_scaled = enu.epos * factor
let n_scaled = enu.npos * factor
let x = e_scaled - minx_scaled
var y = n_scaled - miny_scaled
y = self.frame.size.height.asDouble - y
let point = CGPointMake(x.asCGFloat,y.asCGFloat)
points.append(point)
}
这里我要点:
private let path1 = UIBezierPath()
var moved = false
override func drawRect(rect: CGRect) {
if points.count == 0 { return}
if moved == false {
path1.moveToPoint(points.first!)
moved = true
}else{
path1.addLineToPoint(points.last!)
}
path1.lineWidth = 3
path1.lineJoinStyle = .Round
UIColor.whiteColor().setStroke()
path1.stroke()
}
下图是我在其中绘制 UIBezierPath 的空白 UIView。我用了一点mapview作为参考。