iPhoneのサンプルプログラム

エレベータの識別

disp2.lua(SATCHのスクリプト)
local MLTPlugin = getMLTPluginManager()
local scene = getCurrentScene()
local msg = Text2D(scene:getObjectByName("msg"))

local targetDirectory = getUserAppDataDirectory()
local targetJpg = targetDirectory .. "c1.jpg"

local mode = 1
local isCommand = nil
local command = nil
local componentInterface = getComponentInterface()
local mainView = RenderTarget(scene:getMainView())

msg:setText("")

coroutine.yield()

repeat
	if mode == 1 then
		if componentInterface then
			isCommand, command = componentInterface:pullCommand()
			if isCommand then
				if command["CommandName"]=="capture" then
					mainView:dump(targetJpg)
					mode = 2
				end
			end
		end
	elseif mode == 2 then
		if componentInterface then
			componentInterface:executeAppFunc("setCaptureFilename", targetJpg);
		end
		mode = 3
	end

until coroutine.yield()

AppDelegate.h
#import <Foundation/Foundation.h>

@class ViewController;

@interface AppDelegate : UIResponder 

@property (strong, nonatomic) UIWindow *window;

@property (strong, nonatomic) ViewController *viewController;

@property (strong, nonatomic) UINavigationController *navController;

@property (retain, nonatomic) NSString *capName;

@end

AppDelegeta.mm
#import "AppDelegate.h"

#import "ViewController.h"

@implementation AppDelegate

@synthesize window = _window;
@synthesize viewController = _viewController;
@synthesize navController = _navController;
@synthesize capName;

- (void)dealloc
{
    [_window release];
    [_viewController release];
    [super dealloc];
}

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
    // Override point for customization after application launch.
    self.viewController = [[[ViewController alloc] initWithNibName:@"ViewController" bundle:nil] autorelease];
    self.navController = [[UINavigationController alloc] 
                          initWithRootViewController:self.viewController];
    
    self.window.rootViewController = self.navController;
    [self.window makeKeyAndVisible];
    return YES;
}

- (void)applicationWillResignActive:(UIApplication *)application
{
    // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
    // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
}

- (void)applicationDidEnterBackground:(UIApplication *)application
{
    // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 
    // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
}

- (void)applicationWillEnterForeground:(UIApplication *)application
{
    // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
}

- (void)applicationDidBecomeActive:(UIApplication *)application
{
    // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
}

- (void)applicationWillTerminate:(UIApplication *)application
{
    // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
}

@end

ViewController.h
#import <UIKit/UIKit.h>
#import "satchARViewer.h"


@interface ViewController : UIViewController {
    SatchARViewer *mPlayer;
}

@property (retain, nonatomic) IBOutlet UIView *mRender;
@property (retain, nonatomic) IBOutlet UIButton *btnCapture;

- (IBAction)pushCapture:(id)sender;

- (void)start;
- (void)stop;

@end

ViewController.m
#import "AppDelegate.h"
#import "ViewController.h"
#import "CaptureController.h"

@interface ViewController ()

@end

@implementation ViewController
@synthesize mRender;
@synthesize btnCapture;

- (void)viewDidLoad
{
    [super viewDidLoad];
    self.title = @"メイン画面";
    
	// Do any additional setup after loading the view, typically from a nib.
    //メッセージのローカライズ
    [SatchARViewer        setDialogMessageLoading:@"ローディング..."];
    [SatchARViewer        setToastMessageNoNetworkConnection:@"ネットワークに接続されていません。"];
    [SatchARViewer        setToastMessageNetworkError:@"通信中にエラーが発生しました。"];
    [SatchARViewer        setToastMessageLicenceError:@"認証に失敗しました"];
    
    mPlayer = [[[SatchARViewer alloc] init] initialize:mRender];
    [self start];
}

- (void)viewDidUnload
{
    [self setMRender:nil];
    [self setBtnCapture:nil];
    [super viewDidUnload];
    // Release any retained subviews of the main view.
}

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
    return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
}

- (void)dealloc {
    if (mPlayer) {
        [mPlayer terminate];
        [mPlayer release];
        mPlayer = nil;
    }
    
    [mRender release];
    [btnCapture release];
    [super dealloc];
}

- (IBAction)pushCapture:(id)sender 
{
    [mPlayer enqueueCommand:@"capture" args:nil];
}

- (void)start
{
    if (mPlayer) {
        [mPlayer loadScenario:@"Color1_iphone/Color1.dpd"
                     callback:@selector(callback:)
                          obj:self];
    }
}


- (void)callback:(NSNumber*)num
{
    switch ([num intValue]) {
        case LOAD_SCENARIO_STATUS_COMPLETE:
            [mPlayer registerCommunicationCallback:@"setCaptureFilename" 
                                    callbackObject:self 
                                    callbackMethod:@"TI_SetCapNotification"];
            [[NSNotificationCenter defaultCenter] addObserver:self
                                                     selector:@selector(setCaptureFilename:) 
                                                         name:@"TI_SetCapNotification" 
                                                       object:nil];
            [mPlayer playScenario];
            break;
    }
}

- (void)stop
{
    if (mPlayer && ![mPlayer isScenarioPaused]) {
        [mPlayer pauseScenario];
    }    
}

- (void)setCaptureFilename:(NSNotification *)notification
{
    self.btnCapture.enabled = NO;
    
    AppDelegate *delegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
    
    NSDictionary* l_userInfo = [notification userInfo];
    NSString *s1 = (NSString *)[l_userInfo objectForKey:@"arg0"];
    
    delegate.capName = s1;

    CaptureController *cap = [[CaptureController alloc] init];
    [delegate.navController pushViewController:cap animated:YES];
}

@end

CaptureController.h
#import <UIKit/UIKit.h>

@interface CaptureController : UIViewController

@property (retain, nonatomic) IBOutlet UIImageView *imgView;

@property (retain, nonatomic) IBOutlet UILabel *labMsg;

@end

CaptureController.m
#import "AppDelegate.h"
#import "CaptureController.h"
#import "HSI.h"
#import "ColorInfo.h"

@interface CaptureController ()

@end

@implementation CaptureController
@synthesize imgView;
@synthesize labMsg;

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {
        // Custom initialization
    }
    return self;
}

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view from its nib.
    AppDelegate *delegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
    
    UIImage *img0 = [UIImage imageWithContentsOfFile:delegate.capName];
    if (img0 == nil) {
        NSLog(@"img0 is nil!");
    }
    else {
        NSLog(@"%f %f", img0.size.width, img0.size.height);
    }
    self.imgView.image = img0;
    
    CGImageRef cgImage = img0.CGImage;
    size_t width = CGImageGetWidth(cgImage);
    size_t height = CGImageGetHeight(cgImage);
    size_t bytesPerRow = CGImageGetBytesPerRow(cgImage);
    CGDataProviderRef dataProvider = CGImageGetDataProvider(cgImage);
    CFDataRef data = CGDataProviderCopyData(dataProvider);
    UInt8 *buffer = (UInt8 *)CFDataGetBytePtr(data);
    int i, j;

    int hist[72];
    for (i = 0; i < 72; i++) {
        hist[i] = 0;
    }
    int div = 360 / 72;
    for (j = 0; j < height; j++) {
        for (i = 0; i < width; i++) {
            UInt8 *tmp = buffer + j * bytesPerRow + i * 4;
            
            UInt8 rr = *(tmp + 0);
            UInt8 gg = *(tmp + 1);
            UInt8 bb = *(tmp + 2);
            
            int rrr = (int)rr;
            int ggg = (int)gg;
            int bbb = (int)bb;
            
            HSI *c2 = [[HSI alloc] initWithRed:rrr green:ggg blue:bbb];
            
            if (c2.S >= 0.1) {
                int Hangle = (int)(c2.H * 45 / atan(1.0));
                if (Hangle < 0) {
                    Hangle += 360;
                }
                
                hist[Hangle / div]++; 
            }
            
            [c2 release];
        }
    }

    int maxBin = 0;
    int maxF = hist[0];
    for (i = 1; i < 72; i++) {
        if (maxF < hist[i]) {
            maxF = hist[i];
            maxBin = i;
        }
    }
  
    NSLog(@"maxBin = %d, angle = %f", maxBin, (maxBin + 0.5)*5.0);
    
    NSArray *cand = [[NSArray alloc] 
                     initWithObjects:[[ColorInfo alloc] initWithAngle:237.5 title:@"エレベータA(青)"],
                     [[ColorInfo alloc] initWithAngle:337.5 title:@"エレベータB(赤)"],
                     [[ColorInfo alloc] initWithAngle:22.5 title:@"エレベータC(オレンジ)"],
                     [[ColorInfo alloc] initWithAngle:187.5 title:@"エレベータD(緑)"],nil];
    
    id cur;
    i = 0;
    int i_min = 0;
    double dist_min = 0.0;
    NSString *found_title;
    
    for (cur in cand)
    {
        ColorInfo *info = (ColorInfo *)cur;
        if (i == 0) {
            i_min = 0;
            dist_min = [info calcDistance:(maxBin + 0.5)*5.0];
            found_title = info.title;
        }
        else {
            double dist2 = [info calcDistance:(maxBin + 0.5)*5.0];
            if (dist_min > dist2) {
                i_min = i;
                dist_min = dist2;
                found_title = info.title;
            }
        }
        i++;
    }
    labMsg.text = found_title;
    
    [cand release];
    CFRelease(data);
}

- (void)viewDidUnload
{
    [self setImgView:nil];
    [self setLabMsg:nil];
    [super viewDidUnload];
    // Release any retained subviews of the main view.
    // e.g. self.myOutlet = nil;
}

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
    return (interfaceOrientation == UIInterfaceOrientationPortrait);
}

- (void)dealloc {
    [imgView release];
    [labMsg release];
    [super dealloc];
}
@end

HSI.h
#import <UIKit/UIKit.h>

@interface HSI : NSObject {
    double H, S, I;
}

@property (nonatomic, assign) double H;
@property (nonatomic, assign) double S;
@property (nonatomic, assign) double I;

- (id)initWithRed:(int)_r green:(int)_g blue:(int)_b;

@end

HSI.m
#import "HSI.h"

@implementation HSI
@synthesize H;
@synthesize S;
@synthesize I;

- (id)initWithRed:(int)_r green:(int)_g blue:(int)_b
{
    if (self = [super init]) {
        double R = _r / 255.0;
        double G = _g / 255.0;
        double B = _b / 255.0;
        
        double _pi_3 = atan(1.0) * 4 / 3;
        double _2_pi = atan(1.0) * 8;
        
        double maxI = [self max3:R p2:G p3:B];
        double minI = [self min3:R p2:G p3:B];
        
        I = (maxI + minI)/2;
        
        if (I <= 0.5) {
            S = (maxI - minI)*(maxI + minI);
        }
        else {
            S = (maxI - minI)*(2 - (maxI + minI));
        }
        
        if (maxI != minI) {
            double rr = (maxI - R)/(maxI - minI);
            double gg = (maxI - G)/(maxI - minI);
            double bb = (maxI - B)/(maxI - minI);
            
            if (R == maxI) {
                H = _pi_3 * (bb -gg);
            }
            else if (G == maxI) {
                H = _pi_3 * (2 + rr - bb);
            }
            else {
                H = _pi_3 * (4 + gg - rr);
            }
            
            if (H < 0) {
                H += _2_pi;
            }
        }
        else {
            H = 0;
        }
    }
    
    return self;
}

- (double)max2:(double)v p2:(double)v2
{
    if (v >= v2) return v;
    return v2;
}

- (double)max3:(double)v p2:(double)v2 p3:(double)v3
{
    return [self max2:[self max2:v p2:v2] p2:v3];
}

- (double)min2:(double)v p2:(double)v2
{
    if (v <= v2) return v;
    return v2;
}

- (double)min3:(double)v p2:(double)v2 p3:(double)v3
{
    return [self min2:[self min2:v p2:v2] p2:v3];
}

@end

ColorInfo.h
#import <UIKit/UIKit.h>

@interface ColorInfo : NSObject {
    double H_angle;
    NSString *title;
}

@property (nonatomic, assign) double H_angle;
@property (nonatomic, assign) NSString *title;

- (id)initWithAngle:(double)_a title:(NSString *)_t;

- (double)calcDistance:(double)angle;

@end

ColorInfo.m
#import "ColorInfo.h"

@implementation ColorInfo

@synthesize H_angle;
@synthesize title;

- (id)initWithAngle:(double)_a title:(NSString *)_t
{
    if (self = [super init]) {
        H_angle = _a;
        title = _t;
    }
    
    return self;
}

- (double)calcDistance:(double)angle
{
    double H_rad = H_angle * atan(1.0) / 45.0;
    double x0 = cos(H_rad);
    double y0 = sin(H_rad);
    
    double _rad = angle * atan(1.0) / 45.0;
    double x1 = cos(_rad);
    double y1 = sin(_rad);
    
    double v = sqrt((x1-x0)*(x1-x0) + (y1-y0)*(y1-y0));
    
    NSLog(@"(%f, %f) - (%f, %f) : %f",
          x0, y0, x1, y1, v);
    
    return v;
}

@end