2012-07-01 4 views
2

패턴 이미지로 MKMapView에 선을 그려 봅니다. 그림은 사용자 정의 MKMapOverlay보기를 추가하여 수행됩니다.패턴 이미지로 MKMapView에 선을 그립니다.

나는 선을 그릴 수는 있지만, 그림은 전체 이미지 대신에 패턴 이미지의 왼쪽 위 픽셀 만 사용하는 것으로 보인다. 뭐가 잘못

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

어떤 생각 : 여기

내 드로잉 루틴?

고맙습니다.

답변

5

완전히 다른 전략으로 마무리되었습니다. 자체 오버레이로 추가하는 대신 이제 MKPolyLine에 의존합니다.

다음 코드를 사용하여 MKMapView의 점 A에서 점 B까지 가상의 애니메이션 선을 추가 할 수 있습니다.

코드는 애니메이션

아니 가장 아름다운 솔루션의 인상을주는, 약간의 지연으로 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

애플 리케이션이 좋아 보인다. 그러나 위에 붙여진 코드에 따르면. 어떻게 든지도를 확대하면'points'의 수는'intEnd' 이상이됩니다. 왜 그런 일이 일어나고 어떻게 처리 할 것인가? CLLocation * loc2 = (CLLocation *) [points objectAtIndex : intEnd]; 충돌이 발생합니다! – turtle