0

アップルマップにパスを描画するためにMKOverlayViewを使用しています。他の値に応じてトラックに色を付ける必要があるため、多くの短いパスを描画したいと思います。しかし、私はそれをそのように行うことでいくつかの素晴らしい効果を得ています...また私の開始点と終了点は接続されていますが、理由はわかりません。ズームイン/ズームアウトすると、ファンシーエフェクトパターンが変化し、大きく/小さくなります。私の道にリンゴの地図タイルが見えるようです...

これは私のコードであり、オーバーレイビューのdrawMapRectメソッド内で呼び出されます。

for(int i = 0; i < tdpoints.pointCount-1; i++ ){
    CGPoint firstCGPoint = [self pointForMapPoint:tdpoints.points[i]];
    CGPoint secCGPoint = [self pointForMapPoint:tdpoints.points[i+1]];

    if (lineIntersectsRect(tdpoints.points[i], tdpoints.points[i+1], clipRect)){            

        double val1 = (arc4random() % 10) / 10.0f;
        double val2 = (arc4random() % 10) / 10.0f;
        double val3 = (arc4random() % 10) / 10.0f;


        CGContextSetRGBStrokeColor(context, val1 ,val2, val3, 1.0f);
        CGContextSetLineWidth(context, lineWidth);

        CGContextBeginPath(context);
        CGContextMoveToPoint(context,firstCGPoint.x,firstCGPoint.y);

        CGContextAddLineToPoint(context, secCGPoint.x, secCGPoint.y);

        CGContextStrokePath(context);
        CGContextClosePath(context);

    }
}

http://imageshack.us/photo/my-images/560/iossimulatorbildschirmf.jpg/

http://imageshack.us/photo/my-images/819/iossimulatorbildschirmf.jpg/

そのようにGPSポイントを追加しています。(Breadcrumbs Appleの例から)

CLLocationCoordinate2D coord = {.latitude = 49.1,.longitude =12.1f}; 
[self drawPathWithLocations:coord];

CLLocationCoordinate2D coord1 = {.latitude = 49.2,.longitude =12.2f}; 
[self drawPathWithLocations:coord1];

CLLocationCoordinate2D coord2 = {.latitude = 50.1,.longitude =12.9f}; 
[self drawPathWithLocations:coord2];

これは追加方法です:

-(void) drawPathWithLocations:(CLLocationCoordinate2D)coord{
if (!self.crumbs)
{

    // This is the first time we're getting a location update, so create
    // the CrumbPath and add it to the map.
    //
    _crumbs = [[CrumbPath alloc] initWithCenterCoordinate:coord];
    [self.trackDriveMapView addOverlay:self.crumbs];

    // On the first location update only, zoom map to user location
    [_trackDriveMapView setCenterCoordinate:coord zoomLevel:_zoomLevel animated:NO];

}   else
{
    // This is a subsequent location update.
    // If the crumbs MKOverlay model object determines that the current location has moved
    // far enough from the previous location, use the returned updateRect to redraw just
    // the changed area.
    //
    // note: iPhone 3G will locate you using the triangulation of the cell towers.
    // so you may experience spikes in location data (in small time intervals)
    // due to 3G tower triangulation.
    //

    MKMapRect updateRect = [self.crumbs addCoordinate:coord];

    if (!MKMapRectIsNull(updateRect))
    {

        // There is a non null update rect.
        // Compute the currently visible map zoom scale
        MKZoomScale currentZoomScale = (CGFloat)(self.trackDriveMapView.bounds.size.width / self.trackDriveMapView.visibleMapRect.size.width);
        // Find out the line width at this zoom scale and outset the updateRect by that amount
        CGFloat lineWidth = MKRoadWidthAtZoomScale(currentZoomScale);
        updateRect = MKMapRectInset(updateRect, -lineWidth, -lineWidth);
        // Ask the overlay view to update just the changed area.
        [self.crumbView setNeedsDisplayInMapRect:updateRect];
    }
}

これはaddCoordinateメソッドです。

    - (MKMapRect)addCoordinate:(CLLocationCoordinate2D)coord
{
   pthread_rwlock_wrlock(&rwLock);

    // Convert a CLLocationCoordinate2D to an MKMapPoint
    MKMapPoint newPoint = MKMapPointForCoordinate(coord);
    MKMapPoint prevPoint = points[pointCount - 1];

    // Get the distance between this new point and the previous point.
    CLLocationDistance metersApart = MKMetersBetweenMapPoints(newPoint, prevPoint);

    NSLog(@"PUNKTE SIND %f METER AUSEINANDER ... ", metersApart);

    MKMapRect updateRect = MKMapRectNull;

    if (metersApart > MINIMUM_DELTA_METERS)
    {
        // Grow the points array if necessary
        if (pointSpace == pointCount)
        {
            pointSpace *= 2;
            points = realloc(points, sizeof(MKMapPoint) * pointSpace);
        }    

        // Add the new point to the points array
        points[pointCount] = newPoint;
        pointCount++;

        // Compute MKMapRect bounding prevPoint and newPoint
        double minX = MIN(newPoint.x, prevPoint.x);
        double minY = MIN(newPoint.y, prevPoint.y);
        double maxX = MAX(newPoint.x, prevPoint.x);
        double maxY = MAX(newPoint.y, prevPoint.y);

        updateRect = MKMapRectMake(minX, minY, maxX - minX, maxY - minY);
    }

    pthread_rwlock_unlock(&rwLock);

    return updateRect;
}

ヒント

私の更新アルゴリズムは、画面上のマップ全体の1つのタイルのみを更新し、この特定の領域に対してdrawMapRectメソッドが呼び出されるたびに、新しいランダムな色が生成されるためだと思います。(パスの残りの部分はクリップされ、オーダーカラーは残ります...)。

4

3 に答える 3

0

パスを描くときはいつでもそれを閉じる必要があるからです。パスを閉じると、lastPointとfirstPointの間に自動的に線が引かれます。

パス描画の最後の線を削除するだけです

CGContextClosePath(context);
于 2013-03-25T15:28:17.343 に答える
0

の目的CGContextClosePathは、文字通りパスを閉じることです-開始点と終了点を接続します。あなたはそれを必要としない、StrokePathすでに道を描いた。行を削除します。またCGContextStrokePath、ループの外側に移動します。アプローチは、線を移動/追加/線を移動/追加...そしてストロークします(これを行うと、色を変更できます)。

CGContextSetLineJoin「ファンシー効果」(傾斜した線の結合)については、可能なパラメーターとCGContextSetLineCap呼び出しパラメーターの効果を調査します。

于 2013-03-25T15:29:06.393 に答える
0

表示される「ファンシーエフェクト」は、MKMapViewがdrawMapRectを呼び出す方法と、描画するたびにランダムな色を使用するという決定の組み合わせです。ユーザーがマップをパンしたときに表示を高速化するために、MKMapViewはオーバーレイからタイルをキャッシュします。1つのタイルが画面から消えた場合、捨てたり、別のキャッシュなどに保存したりできますが、画面に残っているタイルは移動するだけで、再描画する必要はありません。描画するとデータへの移動が発生する可能性があるためです。供給または他の長い計算。それがあなたが呼ぶ理由ですsetNeedsDisplayInMapRect、それはそれらのタイルをフェッチするだけでよく、すべてを再描画する必要はありません。

これは私が見たすべてのアプリで機能し、全体として優れたシステムです。ランダムな色のように、毎回同じになることのないものを描く場合を除いて。本当にそのようなパスに色を付けたい場合は、ハッシュまたはランダムに見えるが実際には繰り返し可能なものに基づいているものを使用する必要があります。たぶん、ポイントが置かれているインデックスにポイント座標を掛け、MD5edしてから、5番目の文字などを取ります。それが何であれ、何度呼び出されても同じ線に対して同じ色を生成する必要があります。個人的には、線は一色、多分破線でしたかったのです。しかし、それはあなたとあなたのユーザーの間です。

于 2013-03-25T21:27:28.430 に答える