Add a label in the center of a polygon in MapKit

3.3k Views Asked by At

There are similarly named questions, like this one, but that is not what I'm looking for.

Basically I'm drawing a bunch of MKPolygons on a standard map giving them a stroke, a random colour etc.. I'd like to be able to "name" them, adding a label or perhaps a UIView with a label so it looks nice. Is this possible?

Here's how my map looks like

enter image description here

And here's the implementation

func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {

    if overlay is MacaronMKPolygon {

        let macaronOverlay = overlay as! MacaronMKPolygon

        let polygonView = MKPolygonRenderer(overlay: macaronOverlay)
        polygonView.strokeColor = UIColor.gray
        polygonView.lineWidth = 1
        polygonView.alpha = shouldShowMacaron ? 1.0 : 0.0
        polygonView.fillColor = macaronOverlay.color
        return polygonView

    }

    return MKOverlayRenderer()
}
2

There are 2 best solutions below

0
On

So one of the nice things with MKPolygon is that at its heart is really a type of MKMultiPoint, which inherits from MKShape, Which is a subclass of MKAnnotation. Just follow the docs all the way down from MKPolygon.

So the best part of all of this is that MKPolygon is required to conform to MKAnnotation and thus define the property for coordinate. Which is defined as the center of the annotation.

polygonView.coordinate

So this will give you the center of the polygon as defined by Apple. Now unfortunately with the odd shapes from your polygons it may not be the true center but should be close enough. Nice when we get some stuff for free from Apple.

Using this coordinate you can create an MKAnnotation and MKAnnotationView to lay onto of your overlays.

0
On

1.Find center point of polygon coordinates

 func getCenterCoord(_ LocationPoints: [CLLocationCoordinate2D]) -> CLLocationCoordinate2D{
        var x:Float = 0.0;
        var y:Float = 0.0;
        var z:Float = 0.0;
        for points in LocationPoints {
            let lat = GLKMathDegreesToRadians(Float(points.latitude));
            let long = GLKMathDegreesToRadians(Float(points.longitude));

            x += cos(lat) * cos(long);

            y += cos(lat) * sin(long);

            z += sin(lat);
        }
        x = x / Float(LocationPoints.count);
        y = y / Float(LocationPoints.count);
        z = z / Float(LocationPoints.count);
        let resultLong = atan2(y, x);
        let resultHyp = sqrt(x * x + y * y);
        let resultLat = atan2(z, resultHyp);
        let result = CLLocationCoordinate2D(latitude: CLLocationDegrees(GLKMathRadiansToDegrees(Float(resultLat))), longitude: CLLocationDegrees(GLKMathRadiansToDegrees(Float(resultLong))));
        return result;
    }

2.After getting center place label at that point in MKAnnotationView in viewforAnnotation

 func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {

        if (annotation.isKind(of: MKUserLocation.self)) {
            return nil
        }
//annotation class
  if annotation.isKind(of: ZoneNameAnnotationModal.self) {
            let anView = MKAnnotationView(annotation: annotation, reuseIdentifier: "zoneNameInMiddle")
            let ann = annotation as! ZoneNameAnnotationModal
            let height = 30
            let altitudeVw = UIView(frame: CGRect(x: 0, y: 0, width: 100, height: height))
            let lblTitle = UILabel(frame: CGRect(x: 0, y: 0, width: 100, height: height))
            lblTitle.font = lblTitle.font.withSize(10)
            lblTitle.text = ann.title
            lblTitle.numberOfLines = 10
            lblTitle.textAlignment = NSTextAlignment.center
            lblTitle.textColor = UIColor.black
            lblTitle.backgroundColor = UIColor.clear
            altitudeVw.layer.cornerRadius = 6.0
            altitudeVw.layer.borderWidth = 1.0
            altitudeVw.layer.borderColor = UIColor.black.cgColor
            altitudeVw.backgroundColor =  UIColor(red: 255.0/255, green: 255.0/255, blue: 255.0/255, alpha: 0.70)
            altitudeVw.addSubview(lblTitle)
            anView.addSubview(altitudeVw)
            return anView
        }
return nil
}