2

マップビューを使用してオーバーレイを追加するアプリを作成しようとしています。オーバーレイデータは、ファイルから次のようなNSArrayにロードされます。...

Revier355_2_Poly, //name of the polygon (string) 
6,                //no of coordinates of polygon (int) 
47.4038673907557, //latitude of first coordinate (double)  
8.5247885145479,  //longitude of first coordinate (double)
47.4035082236459,
8.52436382148047,
47.4031174379495,
8.52493568571008,
47.403348653295,
8.52586444637587,
47.4037666977377,
8.52550468311683,
47.4038673907557,
8.5247885145479

...名前、ポイント数、座標を持つ次のポリゴン。

次に、上記のデータをMKPolygonsに変換し、NSDictionaryに配置します。そのために、ファイル内の各ポリゴンの座標を含むC配列を作成します。これには、実行時に配列内のアイテムの数を動的に設定する必要があります。これが私の問題です:私はこれをなんとかすることができません。私を助けてくれるか、正しい方向に向けてくれませんか?

これが私が書いたコードです

int i = 0;
    NSArray *data = [self loadDatafromFile];
    NSMutableDictionary *overlays = [NSMutableDictionary new];
    for ( i=0; i<data.count;i++)
    {

        if ([[data objectAtIndex: i] isKindOfClass: [NSString class]])
            //start of new Polygon called Revier
        {
            //Name of Revier
            NSString *polyName = (NSString*)[data objectAtIndex: i];               
            //PointCount is second entry after name
            int noOfPoints = [[data objectAtIndex: (i+1)] intValue];                    
            //Revier coordinates Error while setting Array size dynamically
            CLLocationCoordinate2D *coord = malloc(sizeof(CLLocationCoordinate2D) * noOfPoints);                          
            for (int j=0; j<noOfPoints+1; j+=2)
                {

                    CLLocationCoordinate2D currCoord = CLLocationCoordinate2DMake([[data objectAtIndex:j+i] doubleValue],[[data objectAtIndex:j+i+1] doubleValue]);
                     coord[j] = currCoord;

                }
            MKPolygon *p = [MKPolygon polygonWithCoordinates:coord count:noOfPoints];
            [overlays setObject: p forKey:polyName];
            free(coord);
        }

    }

これがデータをロードするためのコードです...

- (NSArray *)loadDatafromFile
{
    NSArray* myArr = [[NSArray alloc] initWithContentsOfFile:[self filePath]];
    NSLog(@"%@",[self filePath]);
    return myArr;
}

- (NSString *) filePath
{
    NSString *path = [[NSBundle mainBundle] pathForResource:@"polygone" ofType:@"txt"];
    NSLog(@"%@",path);
    return path;

}
4

1 に答える 1

2

まず、個々の要素を1つの大きなフラット配列として手動で解析している既存のコードの問題を次に示します。

for jループには次の問題があります。

  • j<noOfPoints+1j < (noOfPoints*2)ポイントごとに処理する配列要素が2つあるためです。
  • data配列から緯度と経度を取得するためのインデックスが間違っています(を設定する行でcurrCoord)。ちなみに、その行は、複数のステートメントに分割されている場合、読みやすく、理解しやすく、(特に重要ですが)デバッグしやすくなります修正されたコードは次のようになります。

    int latitudeIndex = j+i +2;     //need to add additional offset of +2
    int longitudeIndex = j+i+1 +2;  //need to add additional offset of +2
    
    CLLocationDegrees lat = [[data objectAtIndex:latitudeIndex] doubleValue];
    CLLocationDegrees lon = [[data objectAtIndex:longitudeIndex] doubleValue];
    
    CLLocationCoordinate2D currCoord = CLLocationCoordinate2DMake(lat,lon);
    
  • C配列の要素を設定するために使用されるインデックスが間違っています。行coord[j] = currCoord;では、は最初はになりますが、その後は。ずつ増加しjます。したがって、、などを設定し、奇数インデックスを初期化しないままにすることになります。代わりに、C配列を設定するためのインデックスとして別のカウンターを追加します(別のカウンターはから計算できますが、別のカウンターの方がクリーンで、理解や変更が簡単です)。02coord[0]coord[2]j

    int coordIndex = 0;  //declare and initialize before the for-j loop
    for (int j=0;...
    {
        ...  //code to set currCoord
    
        coord[coordIndex] = currCoord;
        coordIndex++;
    }
    


これらの変更により、ポリゴンオブジェクトの解析と作成が修正されるはずですが、他に2つの一般的な問題があります。

  • コードは配列内の個々の要素を手動で解析するため、記述、理解、および変更が困難になります。
  • 外側のループは内側のループがすでに処理した要素を読み取る必要があるため、コードは基本的にplistを2回読み取ります。外側のループは、要素タイプが文字列であるかどうかをチェックすることにより、これらをスキップします。

これらの両方は、より良いplist形式を使用し、組み込みのplist読み取りメソッドにハードワークを任せることで解決できます。あなたがしなければならないのは、C配列を作成することだけです。

これがあなたのための可能な代替のplistフォーマットです:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<array>
    <dict>
        <key>PolygonName</key>
        <string>Revier355_2_Poly</string>
        <key>Coordinates</key>
        <array>
            <dict><key>Latitude</key><real>47.4038673907557</real><key>Longitude</key><real>8.5247885145479</real></dict>
            <dict><key>Latitude</key><real>47.4035082236459</real><key>Longitude</key><real>8.52436382148047</real></dict>
            <dict><key>Latitude</key><real>47.4031174379495</real><key>Longitude</key><real>8.52493568571008</real></dict>
            <dict><key>Latitude</key><real>47.403348653295</real><key>Longitude</key><real>8.52586444637587</real></dict>
            <dict><key>Latitude</key><real>47.4037666977377</real><key>Longitude</key><real>8.52550468311683</real></dict>
            <dict><key>Latitude</key><real>47.4038673907557</real><key>Longitude</key><real>8.5247885145479</real></dict>
        </array>
    </dict>
    <dict>
        <key>PolygonName</key>
        <string>Revier1_Poly</string>
        <key>Coordinates</key>
        <array>
            <dict><key>Latitude</key><real>47.22012717</real><key>Longitude</key><real>8.808388346999999</real></dict>
            <dict><key>Latitude</key><real>47.2394585400515</real><key>Longitude</key><real>8.79568994231076</real></dict>
            <dict><key>Latitude</key><real>47.1394585400515</real><key>Longitude</key><real>4.89568994231076</real></dict>
        </array>
    </dict>
</array>
</plist>

このplistを読み取るためのコードは、次のようになります。

NSArray *polygonsArray = [NSArray arrayWithContentsOfFile:path];

NSMutableDictionary *overlays = [NSMutableDictionary new];

//loop through the polygon dictionaries...
for (NSDictionary *polygonDict in polygonsArray) 
{
    NSString *polyName = [polygonDict objectForKey:@"PolygonName"];
    NSArray *coordDictionaries = [polygonDict objectForKey:@"Coordinates"];

    //loop through the array of coordinate dictionaries for the 
    //current polygon to create C array of coordinates...
    int noOfPoints = coordDictionaries.count;
    CLLocationCoordinate2D *coord = malloc(sizeof(CLLocationCoordinate2D) * noOfPoints);

    int coordIndex = 0;
    for (NSDictionary *coordDict in coordDictionaries) 
    {
        CLLocationDegrees lat = [[coordDict objectForKey:@"Latitude"] doubleValue];
        CLLocationDegrees lon = [[coordDict objectForKey:@"Longitude"] doubleValue];
        CLLocationCoordinate2D currCoord = CLLocationCoordinate2DMake(lat,lon);
        coord[coordIndex] = currCoord;
        coordIndex++;
    }

    MKPolygon *p = [MKPolygon polygonWithCoordinates:coord count:noOfPoints];
    [overlays setObject:p forKey:polyName];
    [self.mapView addOverlay:p];
    free(coord);
}

処理する必要がある唯一のインデックス計算は、C配列用であることに注意してください。

より高度な形式または標準化された形式が必要な場合は、KMLも参照してください。サンプルコードはポリラインのみを解析すると思いますが、AppleのKMLViewerサンプルアプリもあります。

コメントでのあなたの質問について:

plistよりもそれを行うためのより良いメカニズムはありますか?

これは、保存する予定のデータの量によって異なります。plistがアプリに対して十分に高速でない場合は、データへのランダムアクセスを許可する方法(SQLデータベースや複数のplistなど)に切り替える必要があります。必要に応じて、それはおそらく別の質問の価値があります。

于 2012-08-27T22:06:27.650 に答える