How to create a static, actual width MKOverlayPathRenderer subclass?

513 views Asked by At

I've been working on a simple path overlay to an existing MKMapView. It takes a CGMutablePath and draws it onto the map. The goals is that the path is drawn representing an actual width. e.g. The subclass takes a width in meters and converts that width into a representative line width. Here is the one version of the code that calculates the line width:

- (void)drawMapRect:(MKMapRect)mapRect zoomScale:(MKZoomScale)zoomScale inContext:(CGContextRef)context
float mapPoints = meterWidth * MKMapPointsPerMeterAtLatitude(self.averageLatitude);
float screenPoints = mapPoints * zoomScale; // dividing would keep the apparent width constant 
self.lineWidth = ceilf(screenPoints * 2);

CGContextAddPath(context, _mutablePath);

[self applyStrokePropertiesToContext:context atZoomScale:zoomScale];

CGContextStrokePath(context);

Here we first find the number of map points that correspond to our line width and then convert that to screen points. We do the conversion based on the header comments in MKGeometry.h:

// MKZoomScale provides a conversion factor between MKMapPoints and screen points.
// When MKZoomScale = 1, 1 screen point = 1 MKMapPoint.  When MKZoomScale is
// 0.5, 1 screen point = 2 MKMapPoints.

Finally, we add the path to the context, apply the stroking properties to the path and stroke it.

However this gives exceedingly flakey results. The renderer often draws random fragments of line in various places outside the expected live area or doesn't draw some tiles at all. Sometimes the CPU is pegged redrawing multiple version of the same tile (as best I can tell) over and over. The docs aren't much help in this case.

I do have a working version, but it doesn't seem like the correct solution as it completely ignores zoomScale and doesn't use -applyStrokePropertiesToContext:atZoomScale:

float mapPoints = meterWidth * MKMapPointsPerMeterAtLatitude(self.averageLatitude);
self.lineWidth = ceilf(mapPoints * 2);

CGContextAddPath(context, _mutablePath);
CGContextSetStrokeColorWithColor(context, self.strokeColor.CGColor);
CGContextSetLineWidth(context, self.lineWidth);
CGContextSetLineJoin(context, kCGLineJoinRound);
CGContextSetLineCap(context, kCGLineCapRound);

CGContextStrokePath(context);

Anyone have pointers on what is wrong with this implementation?

0

There are 0 answers