RMPath flickers and "vibrates" while scrolling RMMapView (MapBox SDK) - ios

I'm using the MapBox SDK with an offline map. I'm adding a RMPath overlay to the mapView and everything is shown ok.
problem no. 1:
while scrolling the map the RMPath overlay is scrolled also, but sometimes it is drawn with an offset (a location where it was just a moment ago) for just a fraction of a second, after that it gets to it's normal place , and this creates a sensation of flickering. Why this happens and how can I get rid of it?
problem no. 2:
while scrolling the map the RMMarker and RMPath overlay "vibrates", it's like the overlay tries to "catch up" with it's normal position when the map is scrolled. It's just a few pixels, but when zoomed it looks pretty bad. this happens most probably because the -draw() method is called only when the map is moved more than just a pixel. How can I make the overlays scroll smoother?
My searches resulted with absolutely nothing, so any help is welcomed.
p.s. tested on iPhone3GS and iPhone4S, same problems on both.

RMPath is deprecated, try using RMShape instead.
Also do not forget to set the bounding box of your annotation before adding it to the map (setBoundingBoxFromLocations can be useful).
Example :
pathAnnotation = [[RMAnnotation alloc]initWithMapView:mapView coordinate:CLLocationCoordinate2DMake(long,lat) andTitle:#"path"];
[pathAnnotation setBoundingBoxFromLocations:pathLocations];
and then in your layerForAnnotation() :
RMShape *path = [[RMShape alloc] initWithView:mapView] ;
[path setLineColor:[UIColor colorWithRed:0.2 green:0.7 blue:1 alpha:0.7]];
[path setLineWidth:4];
// Create real coordinates from data
for(int idx = 0; idx < pathPoints.count; idx++)
{
CLLocationCoordinate2D coords = CLLocationCoordinate2DMake(pathPoints[idx].latitude,pathPoints[idx].longitude);
// First point
if( idx == 0){
[path moveToCoordinate:coord];
}else{
[path addLineToCoordinate:coord];
}
}
return path;

For your problem n°2, I think this could be relative to this issue on MapBox ios sdk
For problem n°1, I have noticed the same behavior, but only when annotations are added while the map is scrolling/zooming. After the map stabilized, the annotations go to the right position. I am still investigating for that.

Related

ArcGIS for iOS - How to stop seeing outside map

In my project, I have an AGSMapView taking up the screen that starts zoomed out to show the entire world map. I have it set to wrap around horizontally, so it works fine there.
However, vertically I can see an empty gray grid at the top and bottom of the map. The user can also scroll the map and this grid can take up at most half the screen, at any zoom level so long as you're at the edge.
Is there any way to snap the edge of the map to the edge of the view it's embedded in and not show this ugly grid?
You should look into AGSMapView.
maxEnveloppe is what you're looking for :
Limits the amount by which the map can be panned such that its anchor point (typically the center) never goes outside this envelope. By default, this is the full envelope of the basemap layer. If you set a custom extent, the envelope must have the same spatial reference as the map.
By the way, you can easily restyle the grid backgroundColor, gridLineWidth, gridLineColor and gridSize. If you want to remove the grid effect, then you have to set the gridLineWidth to 0.
Referring to forum Click here I found closer solution to this problem which worked for me. I have used method suggested by 'reedhr' which I am copying here.
- (void) removePanGesturesFromMap {
NSMutableArray * mutableGestureRecognizers = [[NSMutableArray alloc] initWithArray:MapView.gestureRecognizers];
NSMutableArray *recognizersToRemove = [[NSMutableArray alloc] init];
for (UIGestureRecognizer * gestureRecognizer in MapView.gestureRecognizers) {
if (![gestureRecognizer isKindOfClass:[UILongPressGestureRecognizer class]]
&& ![gestureRecognizer isKindOfClass:[UITapGestureRecognizer class]] ) {
[recognizersToRemove addObject:gestureRecognizer];
}
}
if (recognizersToRemove.count > 0) {
[mutableGestureRecognizers removeObjectsInArray:(NSArray*) recognizersToRemove];
MapView.gestureRecognizers = (NSArray*)mutableGestureRecognizers;
}
}

Multiple Polygon overlays from array

I have an array with polygons created from a data file with coordinates per polygon.
So when I plot them on my map I use:
[mapView addOverlays:polygonArray];
and in my viewForOverlay:
if ([overlay isKindOfClass:[MKPolygon class]]) {
MKPolygonView *polyView = [[MKPolygonView alloc] initWithPolygon:overlay];
polyView.fillColor = [[UIColor redColor] colorWithAlphaComponent:0.1];
polyView.strokeColor = [[UIColor blueColor] colorWithAlphaComponent:0.1];
polyView.lineWidth = 1;
return polyView;
}
else {
return nil;
}
The problem is that regarding my "colorWithAlphaComponent" the code seems to reuse and recreate the polyView for each Polygon. Therefore the first one is with alpha 0.1 but the second is 2x and so on.. So the last few Polygons aren't "seethrough" anymore.
Here's how it looks:
Based on the problem description and picture, it sounds like you are adding the same polygon multiple times so it gets overlapped with itself.
When overlays overlap, the map view blends their colors together resulting in a darker appearance.
If polygonArray contains unique polygons itself but addOverlays is called multiple times, you should call removeOverlays before addOverlays if the existing polygons on the map are already included in polygonArray.
Another possibility is that polygonArray itself contains duplicate polygons.
Even if addOverlays is called only once, the map will add multiple instances of the same polygon resulting in those overlays overlapping themselves giving them a darker color than expected.
To fix this, you should eliminate the duplication in polygonArray.

iOS: How to catch a tap event on a marker on a map that has a CALayer on top of it?

I have a mapView (RouteMe mapView) on which there are annotations (markers).
On the mapView there is a touchesEnded function on which I usually catch all events.
Some markers have an added layer on top of them.
That layer has some animation images and as much as I know this is the only way I can show these animation images on top of the markers.
The problem is that I don't know how I can intercept a touch on a marker that has that layer on top of it. When I test the hit on the touchesEnded I recognize a CALayer class rather than a RMMArker class (obv0iously, because the layer is on top of the marker, therefore is first to intercept the event).
How can I reach the Marker once the top CALayer is tapped?
Thanks
Hackish workaround: Create an RMMapLayer instead of a CALayer. Remember to set the annotation on the sublayer to get things like callouts to work, e.g. in your RMMapLayer subclass:
RMMapLayer *sublayer = [[RMMapLayer alloc] init];
sublayer.annotation = ann;
sublayer.contents = (id)img2.CGImage;
sublayer.contentsScale = img2.scale;
sublayer.position = CGPointMake(CGRectGetWidth(self.bounds)/2, CGRectGetHeight(self.bounds)/2);
sublayer.bounds = CGRectMake(0, 0, img2.size.width, img2.size.height);
[self addSublayer:sublayer];
I don't know how many other things this has potential for breaking though, so you can follow this issue for any updates:
https://github.com/mapbox/mapbox-ios-sdk/issues/190
You can instruct the touches to passthrough. Take a look at this question: How can I click a button behind a transparent UIView?
Since the CALayer was on top of a CALAyer, all it took was to access it ancestor blockingLayer.superlayer.
By checking on the ancestor, I could have all that I needed.
This solved the problem.

Pinching zoom a custom UIView: lines and text are pixelate, needs to be re-rasterized

I have a custom UIView. In this view I am overriding drawRect to draw some paths and some text.
When a tap is detected, the view is zooming in
- (void)tapDetected:(UITapGestureRecognizer *)sender {
float zoom = 3.;
sender.view.transform = CGAffineTransformScale(sender.view.transform, zoom, zoom);
...
}
Zoom works OK, but lines and text become pixelate as I zoom in. I want the lines width and the text size to stay the same, i.e. to be re-rasterized, so I insert a setNeedsDisplay at the end of the above method, but this has no effect, don't works.
Any help?
Thank you.
Try changing the contentScale of the layer in question. This has worked for my paths.
I was having similar problems with my map viewer, so i cooked up an isolated demo project. I got very heavy antialiasing when zoomed in. Basically, to rerasterize when zooming in, you have to play with the rasterizationScale like so:
sublayer.rasterizationScale = scale;
sublayer.contentsScale = scale;
Sample project and readme are here: https://bitbucket.org/robvanderveer/scrollviewdemo

Zooming out with RMMapView constrained to coordinates

I'm trying to setup an offline map in an iPhone app, but the result is not very good.
I'm using the route-me framework, I've got an offline file .db (created by tiles2sqlite) and the map view is constrained with coordinates (using setConstraintsSW:NE:).
My problem is appearing when zooming out (pinch gesture), this error message "Zooming will move map out of bounds: no zoom" is always present and it's very difficult to zoom out when you are not near the real center of the map.
Is there a solution to have the same result as in Offmaps (iOS app) where the map has a nice scrollview behavior?
Cheers.
Cyril
I had to edit RMMapView.m source code to make a quick fix. Find - (void)zoomByFactor: (float) zoomFactor near:(CGPoint) center animated:(BOOL)animated method (near line 300). It has constrain logic, I turned it off:
- (void)zoomByFactor: (float) zoomFactor near:(CGPoint) center animated:(BOOL)animated
{
if ( _constrainMovement && false ) // turn constraint checks off
{
//check that bounds after zoom don't exceed map constraints
//the logic is copued from the method zoomByFactor,
float _zoomFactor = [self.contents adjustZoomForBoundingMask:zoomFactor];
float zoomDelta = log2f(_zoomFactor);
...
}
...
}
Now map is zoomed smoothly, but this fix could have side effects.
Instead you can use of setting setConstraintsSW:NE: we can set RMMapview as,
RMDBMapSource *mapSrc = [[[RMDBMapSource alloc] initWithPath:#"mapDB.sqlite"] autorelease];
[[RMMapContents alloc] initWithView:mapView tilesource:mapSrc centerLatLon:mapSrc.centerOfCoverage zoomLevel:17 maxZoomLevel:18 minZoomLevel:15 backgroundImage:image screenScale:10 ];
This will enable your zooming acording to your set parameter

Resources