Xcode - 谷歌街景api 3D全景

时间:2012-10-29 07:48:48

标签: iphone objective-c ios xcode photos

我的目标是使用Google街景API向用户显示完整的全景可滚动街景图像。基本上API提供了许多图像,我可以改变方向,高度,缩放,位置等。我可以检索所有这些,并希望将它们拼接在一起并查看它。第一个问题是,你知道任何资源可以破坏这个完整的谷歌街景视图演示吗?用户可以在周围移动以移动街景,就像在旧的iOS 5 Map街景中一样,我相信我们都会错过...

如果没有,我将基本上下载数百张垂直和水平方向不同的照片。是否有图书馆或API或资源或方法,我可以将所有这些照片拼接在一起制作一个大的全景图并使其成为用户可以滑动以在iPhone小屏幕上查看大全景图片?

感谢大家!

3 个答案:

答案 0 :(得分:4)

我汇总了一个快速实现,为您做了很多这样的演示。有一些优秀的开源库,使得StreetView的业余版本变得非常简单。您可以在GitHub上查看我的演示:https://github.com/ocrickard/StreetViewDemo

您可以使用Google StreetView API中的标题和音高参数来生成切片。 Bilal和Geraud.ch建议,这些瓷砖可以安排在UIScrollView中。但是,我真的很喜欢JCTiledScrollView,因为它包含一个非常好的注释系统,用于在像Google这样的图像上添加引脚,并且它的数据源/委托结构可以实现一些非常直接的图像处理。

我实施的内容如下:

- (UIImage *)tiledScrollView:(JCTiledScrollView *)scrollView imageForRow:(NSInteger)row column:(NSInteger)column scale:(NSInteger)scale
{
    float fov = 45.f / scale;

    float heading = fmodf(column*fov, 360.f);
    float pitch = (scale - row)*fov;

    if(lastRequestDate) {
        while(fabsf([lastRequestDate timeIntervalSinceNow]) < 0.1f) {
            //continue only if the time interval is greater than 0.1 seconds
        }
    }

    lastRequestDate = [NSDate date];

    int resolution = (scale > 1.f) ? 640 : 200;

    NSString *path = [NSString stringWithFormat:@"http://maps.googleapis.com/maps/api/streetview?size=%dx%d&location=40.720032,-73.988354&fov=%f&heading=%f&pitch=%f&sensor=false", resolution, resolution, fov, heading, pitch];
    NSError *error = nil;
    NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:path] options:0 error:&error];
    if(error) {
        NSLog(@"Error downloading image:%@", error);
    }
    UIImage *image = [UIImage imageWithData:data];

    //Distort image using GPUImage
    {
        //This is where you should try to transform the image.  I messed around
        //with the math for awhile, and couldn't get it.  Therefore, this is left
        //as an exercise for the reader... :)

        /*
        GPUImagePicture *stillImageSource = [[GPUImagePicture alloc] initWithImage:image];
        GPUImageTransformFilter *stillImageFilter = [[GPUImageTransformFilter alloc] init];
        [stillImageFilter forceProcessingAtSize:image.size];

        //This is actually based on some math, but doesn't work...
        //float xOffset = 200.f;

        //CATransform3D transform = [ViewController rectToQuad:CGRectMake(0, 0, image.size.width, image.size.height) quadTLX:-xOffset quadTLY:0 quadTRX:(image.size.width+xOffset) quadTRY:0.f quadBLX:0.f quadBLY:image.size.height quadBRX:image.size.width quadBRY:image.size.height];
        //[(GPUImageTransformFilter *)stillImageFilter setTransform3D:transform];

        //This is me playing guess and check...
        CATransform3D transform = CATransform3DIdentity;
        transform.m34 = fabsf(pitch) / 60.f * 0.3f;

        transform = CATransform3DRotate(transform, pitch*M_PI/180.f, 1.f, 0.f, 0.f);
        transform = CATransform3DScale(transform, 1.f/cosf(pitch*M_PI/180.f), sinf(pitch*M_PI/180.f) + 1.f, 1.f);
        transform = CATransform3DTranslate(transform, 0.f, 0.1f * sinf(pitch*M_PI/180.f), 0.f);

        [stillImageFilter setTransform3D:transform];


        [stillImageSource addTarget:stillImageFilter];
        [stillImageFilter prepareForImageCapture];
        [stillImageSource processImage];

        image = [stillImageFilter imageFromCurrentlyProcessedOutput];
         */
    }

    return image;
}

现在,为了获得Google拥有的完整360度,无限滚动效果,您必须在observeValueForKeyPath方法中做一些技巧,您可以在其中观察UIScrollView的contentOffset。我已经开始实现这个,但没有完成它。这个想法是当用户到达视图的左侧或右侧时,scrollView的contentOffset属性被推送到scrollView的另一侧。如果你可以让内容正确对齐,并且你正确设置了contentSize,那么这应该可行。

最后,我应该注意到Google StreetView系统的每秒限制为10张图像,因此您必须限制您的请求,否则设备的IP地址将被列入黑名单一段时间(我的家庭互联网是现在因为接下来几个小时的StreetView请求而变黑了,因为我起初并不理解这一点。

答案 1 :(得分:1)

您需要使用UIScrollView,将其clipSubviews属性设置为true,根据图像将所有图像添加到UIScrollView和UIScrollView的contentsOffset。

答案 2 :(得分:1)

您应该使用此帖子中描述的方法:http://mobiledevelopertips.com/user-interface/creating-circular-and-infinite-uiscrollviews.html

您必须制作一些工厂才能将图像转换为适合的大小和视口(iPhone / iPad)。然后添加一些按钮,您可以点击这些按钮转到下一个位置。

不幸的是,如果你想去一个地球版本(而不是一个管道版本),我认为你需要使用完整的openGL在这个3D表面上显示图像。