# Manual convertCoordinate toPointToView

I wonder if anyone has done manual calculation to map a WGS84 coordinate to the UIView coordinates system? Indeed I convert WGS84 to ENU coordinate system which is similar to Cartesian (x,y,z) coordinate system.

I know there is a method in MKMapView which gets a CLLocationCoordinate2D and returns a CGPoint in an expected UIView, but I want to draw the CGPoints on a blank UIView rather than on a map. Therefore I'd like to skip initializing MKMapView object just to use this method.

There must be a simple way to scale down the coordinates from Cartesian to device coordinate system. I guess I also need to have some form of rotation/transformation for origin of the system (Cartesian -> UIView) as the origin point for UIView sits on top-left.

Shrinking down the coordinates should be straight forward.

Lets say you have a cluster of coordinates around a ridiculous point (32000, 192033). This is the centre point of that particular cluster.

Obviously we want to shift them so that they are centred around the origin (0, 0).

So take every point and convert it using...

```newPoint = CGPointMake(oldPoint.x - 32000, oldPoint.y - 192033)
```

This will bring them all so that they are all the same relative distance apart but now centred on the origin.

Next, say the minimum X value is -9345 and the maximum X value is 8455.

You want your X range to be something like 640 (to fit all of them across the screen).

So...

```currentXRange = 8455 + 9345; // maxX - minX = 17800
requiredXRange = 640;
xScale = requiredXRange / currentXRange; // 0.0359...
```

Now that you have an x scale you can convert your points by multiplying the x coordinate by the xScale value.

The minimum X value you have will be...

```-9345 * xScale; // -335.4...
```

Maximum X value will be...

```8455 * xScale; // 303.5...
```
##### EDIT so they are on screen

To bring them all so they are greater than 0. (i.e. so they are all on the screen) just subtract the smallest X and Y coordinate values from each of the points.

```-335.4 - (-335.4) = 0 // minimum X value
303.5 - (-335.4) = 638.9 // maximum X value
```

That brings them all in range so that they fit on the screen.

##### EDIT upside down Y axis

To make sure they are displayed the right way up just create the points by subtracting them from the height of the view.

If the view size is (100, 100) then a point (50, 10) in iOS will be in the middle near the top of the view.

But in normal use it should be near the bottom.

So create the converted point using...

```convertedPoint = CGPointMake(originalPoint.x, view.height - originalPoint.y)
```

This will create the point (50, 90) which will put it in the middle and ten points from the bottom like you wanted.

##### NOTE

As long as you do the same operation to every point in the set then they will all be in the same relative place and the data will still be valid.

The tricky part is working out the operation but I think I've covered everything.

@Fogmeister, eventhough your answer makes sense on the paper I don't know why I can't get it to work. I have positons in enus array. I first found the minx, miny, maxx, maxy

```    let sortX = enus.sort({ \$0.epos < \$1.epos })
let sortY = enus.sort({ \$0.npos < \$1.npos })
let minx = sortX.first?.epos
let maxx = sortX.last?.epos
let miny = sortY.first?.npos
let maxy = sortY.last?.npos
```

Then I found the ranges:

```        let xrange = abs(maxx!-minx!)
let yrange = abs(maxy!-miny!)
```

Then I found the scale factor:

```        let xscale = self.frame.size.width.asDouble / xrange
let yscale = self.frame.size.height.asDouble / yrange
let factor = (xscale <= yscale ? xscale : yscale)
```

Then in a loop I use the factor and minx and miny to scale down and shift my enu positions:

```    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)
}
```

and here I draw the points:

```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.lineWidth = 3
path1.lineJoinStyle = .Round
UIColor.whiteColor().setStroke()
path1.stroke()
}
```

The image below is a blank UIView where I draw my UIBezierPath. I used a little mapview as a reference.