使用图案图像在MKMapView上绘制线条 [英] draw line on MKMapView with pattern image

查看:98
本文介绍了使用图案图像在MKMapView上绘制线条的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我尝试使用图案图像在 MKMapView 上画一条线。
通过添加自定义 MKMapOverlay 视图完成绘图。

I try to draw a line on a MKMapView with a pattern image. The drawing is done by adding a custom MKMapOverlay view.

我能够绘制线条,但似乎只使用图案图像的左上角像素而不是整个图像来完成绘图。

I'm able to get the line drawn, but it seems that the drawing is done using only the left, topmost pixel of the pattern image, instead of the whole 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!

推荐答案

我最终采用了完全不同的策略。
我现在依靠 MKPolyLine 而不是通过自己的叠加添加。

I ended up with a completely different strategy. Instead of adding by own overlay I now rely on MKPolyLine.

使用以下代码我'能够在 MKMapView 上添加从A点到B点的伪动画线。

Using the following code I'm able to add a pseudo animated line from point A to point B on a MKMapView.

代码为MKMapViews添加了几个叠加层,稍有延迟,给人一种动画效果

The code adds several overlays to the MKMapViews with a slight delay, giving the impression of an animation

不最美的解决方案! - 但它看起来相当不错: - )

Not the most beautiful solution! - but it looks pretty good in action :-)

/*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];
    }

}

这篇关于使用图案图像在MKMapView上绘制线条的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆