0

CATiledLayerを使用してマップタイルを描画していますが、ズームすると、精度の問題が原因であると思われるアーティファクトがいくつか表示され始めます。

CATiledLayerを2^18(262'144x)までスケールすると、アーティファクトが約15'000xで表示され始めます。

CoreAnimationは、これらの大規模なものを処理するのに十分スマートだと思いましたが、明らかにそうではありません。

これを処理するためにタイルエンジンの実装を最初から書き始める前に、何か提案があるかどうか疑問に思いました。

これが私のレイヤーのセットアップ方法です:

self.tiledLayer.tileSize = CGSizeMake(256, 256);
self.tiledLayer.levelsOfDetail = 1;
self.tiledLayer.levelsOfDetailBias = 10000;

私の例では、コードの描画は本当に簡単です。

- (void)drawLayer:(CATiledLayer *)layer inContext:(CGContextRef)context
{
    CGRect rect = CGContextGetClipBoundingBox(context);
    CGContextSetFillColorWithColor(context, [NSColor colorWithCalibratedRed:((CGFloat)rand() / (CGFloat)RAND_MAX) green:((CGFloat)rand() / (CGFloat)RAND_MAX) blue:0 alpha:1].CGColor);
    CGContextFillRect(context, rect);
}

これが私がレイヤーにスケールを設定する方法です:

CGAffineTransform t = CGAffineTransformIdentity;

CGFloat scale = pow(2, self.zoomLevel); // self.zoomLevel ranges from 0 to 18
t = CGAffineTransformScale(t, scale, scale);

NSLog(@"%g", scale);

self.tiledLayer.affineTransform = t;

注:アーティファクトはレイヤーの「原点から遠く」にしか表示されないことを発見しました。原点の近くでタイルを見ると、変形していません。原点から遠くで見ると(中央からの場合はスクリーンショット)、悪化します。

これが私が見るアーティファクトの例です:

アーティファクト

4

1 に答える 1

0

OK、調理中に非常に簡単な解決策を見つけました。スケールを適切なものにモジュロし、描画コードへのヒントを使用してループするだけです。たとえば、縮尺が 64 に達した場合は、1 にリセットして描画コードに 64 を指定します。縮尺が 2 の場合、描画コードは 128 のズーム用のタイルを選択します。

明日これを試して、CATiledLayer キャッシュ メカニズムを使用してスムーズなエクスペリエンスを確保する方法を確認します。

編集:このメソッドを試すのに数分かかりましたが、スケールをプレビュー値に戻すと、drawInContext が再度呼び出されないため、事実上キャッシュに問題が発生しました。setNeedsDisplay を呼び出してみましたが、ズームの滑らかさが失われ、すべてが非常に遅くなります。

編集 2:このソリューションを数時間いじった後、スムーズなズームとパンを行うことができませんでした。単一の NSView drawRect: でタイルを描画する単純なアプローチを試みましたが、これは機能しますが、スムーズかつ高速にするにはかなりの作業が必要になります。したがって、私はこの質問を提案に対して開いたままにしています。

編集 3:私は最終的に、このバグのない独自の実装をゼロから作成しました。

于 2012-10-19T17:41:54.483 に答える