2012-07-01 2 views
2

Я пытаюсь нарисовать линию на MKMapView с рисунком. Рисунок сделан путем добавления пользовательского вида MKMapOverlay.рисовать линию на MKMapView с рисунком image

Я могу получить черту, но кажется, что рисунок выполняется с использованием только левого, верхнего пикселя изображения шаблона, а не всего изображения.

Вот мой рисунок рутина:

void drawPatternCellCallback(void *info, CGContextRef cgContext) 
{ 
    UIImage *patternImage = [UIImage imageNamed:@"tmpLine"]; 
    CGContextDrawImage(cgContext, CGRectMake(0, 0, patternImage.size.width, patternImage.size.height), patternImage.CGImage); 

} 

- (void)drawMapRect:(MKMapRect)mapRect 
      zoomScale:(MKZoomScale)zoomScale 
      inContext:(CGContextRef)context 
{ 
    float alpha = 1;   
    float tileW = 6.0f; 
    float tileH = 4.0f; 
    CGFloat lineWidth = MKRoadWidthAtZoomScale(zoomScale)*2; 
    CGMutablePathRef path = CGPathCreateMutable(); 


    if (path != nil) 

    { 
     //setup styles 
     CGContextSetRGBStrokeColor(context, 0.0f, 0.0f, 1.0f, 0.5f); 

     const CGPatternCallbacks kPatternCallbacks = {0, drawPatternCellCallback, NULL}; 
     CGPatternRef strokePattern = CGPatternCreate(
                NULL, 
                CGRectMake(0, 0, tileW, tileH), 
                CGAffineTransformIdentity, 
                tileW, // horizontal spacing 
                tileH,// vertical spacing 
                kCGPatternTilingConstantSpacing, 
                true, 
                &kPatternCallbacks); 
     //color sapce 
     CGColorSpaceRef patternSpace = CGColorSpaceCreatePattern(NULL); 
     CGContextSetStrokeColorSpace(context, patternSpace); 

     //pattern 
     CGContextSetStrokePattern(context, strokePattern, &alpha); 

     //joins/ends 
     CGContextSetLineJoin(context, kCGLineJoinMiter); 
     CGContextSetLineCap(context, kCGLineCapButt); 
     CGContextSetLineWidth(context, lineWidth); 

     //OK, let's draw it 
     CGPoint firstCGPoint = [self pointForMapPoint:self.point1];  
     CGPoint lastCGPoint = [self pointForMapPoint:self.point2]; 
     CGPathMoveToPoint(path, NULL, lastCGPoint.x, lastCGPoint.y);  
     CGPathAddLineToPoint(path, NULL, firstCGPoint.x, firstCGPoint.y); 
     CGContextAddPath(context, path); 
     CGContextStrokePath(context); 

     //house hold 
     CGPathRelease(path); 
     CGPatternRelease(strokePattern); 
     CGColorSpaceRelease(patternSpace); 
    } 
} 

Любая идея, что это не так?

Thanx!

ответ

5

Я закончил с совершенно другой стратегией. Вместо того, чтобы добавлять собственные оверлея, я теперь полагаюсь на MKPolyLine.

Используя следующий код, я могу добавить псевдоанимированную линию от точки A до точки B на MKMapView.

код добавляет несколько наложений к MKMapViews с небольшой задержкой, создавая впечатление анимации

Не самое красивое решение! - но это выглядит довольно хорошо в действии :-)

/*start the animation*/ 
-(void)plotRouteOnMap 
{ 
    [self.mapView removeOverlays:self.mapView.overlays]; 
    //calculate a number locations between the two locations 
    self.points = [self getPointsOnRouteFrom:<FROM_LOCATION> 
              to:<TO_LOCATION> 
            onMapView:self.mapView]; 
    [self addOverlaysFromPointsWithStartFrom:[NSNumber numberWithInt:1]]; 
} 

/*convert a CGPoint to a CLLocation according to a mapView*/ 
- (CLLocation*)pointToLocation:(MKMapView *)mapView fromPoint:(CGPoint)fromPoint 
{ 
    CLLocationCoordinate2D coord = [mapView convertPoint:fromPoint toCoordinateFromView:mapView]; 
    return [[[CLLocation alloc] initWithLatitude:coord.latitude longitude:coord.longitude] autorelease]; 
} 

/*get a list of Location objects between from and to*/ 
-(NSArray*)getPointsOnRouteFrom:(CLLocation*)from to:(CLLocation*)to onMapView:(MKMapView*)mapView 
{ 
    int NUMBER_OF_PIXELS_TO_SKIP =10; //lower number will give a more smooth animation, but will result in more layers 
    NSMutableArray *ret = [NSMutableArray array]; 
    CGPoint fromPoint = [mapView convertCoordinate:from.coordinate toPointToView:mapView]; 
    CGPoint toPoint = [mapView convertCoordinate:to.coordinate toPointToView:mapView]; 

    NSArray *allPixels = [self getAllPointsFromPoint:fromPoint toPoint:toPoint]; 
    for (int i = 0 ; i < [allPixels count] ; i+=NUMBER_OF_PIXELS_TO_SKIP) { 
     NSValue *pointVal = [allPixels objectAtIndex:i]; 
     [ret addObject:[self pointToLocation:mapView fromPoint:[pointVal CGPointValue]]]; 
    } 
    [ret addObject:[self pointToLocation:mapView fromPoint:toPoint]]; 
    return ret; 
} 

/*calulate alle pixels from point to toPint*/ 
-(NSArray*)getAllPointsFromPoint:(CGPoint)fPoint toPoint:(CGPoint)tPoint 
{ 
    /*Simplyfied implementation of Bresenham's line algoritme */ 
    NSMutableArray *ret = [NSMutableArray array]; 
    float deltaX = fabsf(tPoint.x - fPoint.x); 
    float deltaY = fabsf(tPoint.y - fPoint.y); 
    float x = fPoint.x; 
    float y = fPoint.y; 
    float err = deltaX-deltaY; 

    float sx = -0.5; 
    float sy = -0.5; 
    if(fPoint.x<tPoint.x) 
     sx = 0.5; 

    if(fPoint.y<tPoint.y) 
     sy = 0.5; 
    do { 
     [ret addObject:[NSValue valueWithCGPoint:CGPointMake(x, y)]]; 
     float e = 2*err; 
     if(e > -deltaY) 
     { 
      err -=deltaY; 
      x +=sx; 
     } 
     if(e < deltaX) 
     { 
      err +=deltaX; 
      y+=sy; 
     } 
    } while (round(x) != round(tPoint.x) && round(y) != round(tPoint.y)); 
    [ret addObject:[NSValue valueWithCGPoint:tPoint]];//add final point 
    return ret; 

} 

/*add a poly line overlay to mapview which start at position 0 and end in 'end' in the array points*/ 
-(void)addOverlaysFromPointsWithStartFrom:(NSNumber*)end 
{ 
    int intEnd = [end intValue]; 

    //construct polyline view from start 
    CLLocationCoordinate2D *locations = malloc(sizeof(CLLocationCoordinate2D)*2); 
    CLLocation *loc1 = (CLLocation*)[points objectAtIndex:0]; 
    CLLocation *loc2= (CLLocation*)[points objectAtIndex:intEnd]; 
    locations[0] = loc1.coordinate; 
    locations[1] = loc2.coordinate; 
    MKPolyline *line = [MKPolyline polylineWithCoordinates:locations count:2]; 
    [self.mapView addOverlay:line]; 


    if((intEnd+1) < [points count])//add more overlays after delays unless this is the endpoint 
    {   
     [self performSelector:@selector(addOverlaysFromPointsWithStartFrom:) withObject:[NSNumber numberWithInt:intEnd + 1] afterDelay:0.01]; 
    } 

} 
+0

Что происходит, когда вы увеличиваете масштаб карты! – turtle

+0

MKPolyLine не масштабируется, но расстояние между каждой точкой увеличивается. Вы можете увидеть это в действии в этом приложении: https://itunes.apple.com/us/app/city-distance/id561422939?mt=8 – EsbenB

+0

App выглядит хорошо. Но в соответствии с приведенным выше кодом. Так или иначе, подсчет «точек» становится больше, чем «intEnd», когда вы приближаете карту. Почему это происходит, и как вы справитесь с этим. CLLocation * loc2 = (CLLocation *) [указывает объектAtIndex: intEnd]; вызывает крах! – turtle

Смежные вопросы