2013년 4월 30일 화요일

xbox360 간단리뷰

우리 아들 은준이 생일선물 xbox360 스타워즈 한정판

사실 키넥트 스타워즈를 엄청 좋아 할 줄 알았는데 은준이가 아직 잘 하지 못한다.
그리고 컨트롤러를 이용하는 게임에 아직 관심을 갖지 않는다.
하지만 언젠가는 아빠랑 같이 놀아 줄거라 믿는다.

현재 6살 은준이에게는 조금 어려운 키넥트다.

한 1년이나 몇 개월은 더 있어야 스타워즈를 잘 할거 같다.
조금은 이른감이있다.
내가 게임을 하는것을 옆에서 구경 하며 좋아 하는데
나는 제다이 수업을 마치고 실전에 들어가니 너무 힘들다.

키넥트 스포츠나 댄스센트럴 등을 데모로 해 보았는데 괞찮다.
구매 하고 싶을 정도다.

엑스박스의 외관은 생각보다 크기가 좀 크다.
무선 컨트롤러는 아주 훌륭했다.
콘솔 게임기를 처음 접해본 나에겐 엄청 신기하고 이렇게 많은 키와 컨트롤이 필요한가 했지만
추억에 고스트리콘 어드벤스 워파이터2 데모를 실행해 보니 모두 필요 했다.
총을 맞으면 진동이 오는게 게임에 몰입도가 한층올라간다. 정말 즐겁다.
은준이 생일 선물인데 내가 더 즐겁다.

하드디스크를 연결하니 어라 인식을 못하는지 아무것도 안보인다.
설정에서 디스크를 구성하고 나니까 30기가로 인식이된다.
맥미니에 연결해 보니 그대로 80기가 하드이고 FAT32로 포멧이 되어 있는데
히든 디렉토리가 몇개 구성되어 있다.

동영상 몇개를 복사해서 엑스박스에 연결하니 훌륭한 미디어 재생기가 된다.
요즘 LED TV는 머 USB디스크로 영화 감상이 되지만 우리집 LCD TV 는 구형이라서 안된다.
IPTV세탑도 여러번 교체 했지만 불안한 플레이, 지원안되는 파일은 갑자기 재부팅도 된다.
해서 구형 맥미니를 xbmc머신으로 TV에 연결해 두었는데 이제 그 일을  엑스박스가 할 듯 하다.

엑스박스로 베를린이라는 영화를 감상했다. 영화도 아주 재미있게 잘 보았다.
영화를 보다 손을 휘저으면 키넥트가 리모컨 역할을 해준다. 정말 편리 하다.


엑스박스를 평가 하자면 게임 재미, 소프트웨어의 완성도, 하드웨어 외관, 그리고 컨트롤러 모든 점에서
나는 매우 만족한다.
다음 세대 엑스박스가 나오기 때문에 지금 시점에서 엑스박스360이라...
그냥 나는 머 지난 게임들 천천히 싸게 구매해서 하고
은준이가 자라면서 아빠랑 같이 FIFA같은 2인 게임을 같이 하며 즐거워 할날을 기다린다.
아직은 키넥트 게임도 제대로 못하고 잊지만.... 언젠가는 아빠 한게임 해요!!!!
하겠지....

2013년 4월 29일 월요일

iOS 프로그래밍 팁 - fastpdfkit 사용하기

ALTIBASE HDB Manual app
https://itunes.apple.com/us/app/altibase-hdb-manual/id597190444?l=ko&ls=1&mt=8

처음 만들때는 QuartzCore 이용해서 pdf를 다루는 API를 직접 이용해서 작성해 보았다.

확대 축소 부 터 해서 제스처에 의한 페이지 컨트롤
모든 게 부 자연스러웠고

인터넷에서 PDF 를 다루는 코드 들을 조합해서 나름 만들었지만 매우 불안정했다.

특히 검색 속도는 너무 느렸다.

http://support.fastpdfkit.com/kb/how-to/three-minutes-implementation-guide

fastpdfkit이라는 라이브러를 이용해서 바로 프로그램을 업데이트 했다.

성능 속도 모든 면에서 우수하다.

단 무료 버전에 경우 로고가 잠시 뜨지만

간단한 PDF를 보여주어야 할 경우에 이를 이용하는 것이 좋은 듯 하다.

위 링크 3분 가이드를 그대로 한다면 어렵지 않게 구현 가능 할 것이다.


실제로 ALTIBASE HDB Manual app에서

ManualViewController.h

ManualViewController.m


#import <UIKit/UIKit.h>
#import <FastPdfKit/FastPdfKit.h>
@class MFDocumentManager;

@interface ManualViewController : UIViewController <UITableViewDataSource, UITableViewDelegate, MFDocumentViewControllerDelegate>
{
    UITableView * tableView_;
    NSArray *keys_;
    NSDictionary * datasource_;
    NSDictionary * filename_;
}

-(void)actionOpenPlainDocument:(NSString *)docName withPage:(NSInteger)pageNum;

@end

ManualViewController.m

테이블 뷰 선택 시 파일이름과 페이지 번호만 넘기면 된다.!!


/테이블 선택
- (void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {

    
    
//    PDFViewController * pdfviewController = [[[PDFViewController alloc] init]autorelease];
    
    id key = [keys_ objectAtIndex:indexPath.section];
    NSString * filename = [[filename_ objectForKey:key] objectAtIndex:indexPath.row];
    
    //pdfviewController.filename = filename;
    
    //현재 페이지 번호 전달
    NSUserDefaults *userDefault = [NSUserDefaults standardUserDefaults];
    NSInteger pageNum = [userDefault integerForKey:filename];
    if (pageNum == 0) {
        pageNum = 1;
    }
    
    [self actionOpenPlainDocument:filename withPage:pageNum];

    //pdfviewController.currentPage = pageNum;

    //[self.navigationController pushViewController: pdfviewController animated:YES];
    
    [tableView deselectRowAtIndexPath:indexPath animated:YES];
}





-(void)actionOpenPlainDocument:(NSString *)docName withPage:(NSInteger)pageNum{
    /** Set document name */
    NSString *documentName = docName;
    
    /** Get temporary directory to save thumbnails */
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    
    /** Set thumbnails path */
    NSString *thumbnailsPath = [[paths objectAtIndex:0] stringByAppendingPathComponent:[NSString stringWithFormat:@"%@",documentName]];
    
    /** Get document from the App Bundle */
    NSURL *documentUrl = [NSURL fileURLWithPath:[[NSBundle mainBundle]pathForResource:documentName ofType:@"pdf"]];
    
    /** Instancing the documentManager */
    MFDocumentManager *documentManager = [[MFDocumentManager alloc]initWithFileUrl:documentUrl];
    
    
    
    /** Instancing the readerViewController */
    ReaderViewController *pdfViewController = [[ReaderViewController alloc]initWithDocumentManager:documentManager];
    
    /** Set resources folder on the manager */
    documentManager.resourceFolder = thumbnailsPath;
    
    /** Set document id for thumbnail generation */
    pdfViewController.documentId = documentName;
    

    
    pdfViewController.startingPage = pageNum;
    //pdfViewController.page = pageNum;

    
    /** Present the pdf on screen in a modal view */
    //[self presentModalViewController:pdfViewController animated:YES];
    [self.navigationController pushViewController: pdfViewController animated:YES];
    
    //현재 페이지 번호 저장
    NSUserDefaults *userDefault = [NSUserDefaults standardUserDefaults];
    [userDefault setInteger:pdfViewController.page forKey:docName];
    [userDefault synchronize];

    
    /** Release the pdf controller*/
    
    [pdfViewController release];
}


2013년 4월 27일 토요일

iOS 프로그래밍팁 - XCode Analyze 이용하기 (정적 분석)



XCode 에서 Product -> Analyze

static analyze 기능이 포함 되어 있다.


ARC option이 설정된 프로젝트를 ARC 설정을 제거 하고 
이 기능을 이용해서 문제점을 찾아 작업을 할 수도 있다.

Codesonar 나 SPARROW 같은 정적 분석툴을 XCode에서는 사용할 필요가 없겠다.
아주 훌륭한 정적 분석기가 내장되어 있는 XCode 정말 아름답다.


이 기능을 모르던 시절에 작업한 프로젝트를 돌려 보니 다양한 문제점을 보여준다.
아래는 그러한 유형을... 
이걸 보면 코드를 아름답게 다시 작성 할수 있다.


1. Memory Potential leak : 잠재적 메모리 누수


request 객체가 잠재적인 메모리 누수가 있음을 알려준다.
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:
                                    [NSURL URLWithString:[NSString 
.... 생략
--> autorelease를 추가 해야 한다.


2. Logic error : 논리 오류

if 문 ~ else if 의 else가 없다. rowCount는 초기화 되지 않고 리턴 될수 있음을 알린다.


3. Optimization 사용하지 않는 객체를 Class  선언시 멤버로 가지고 있다.


4. Dead Store : 설정만 하고 사용하지 않는 변수





iOS 프로그래밍 팁 - Objective - C 메모리 관리

ARC  옵션을 끄고 프로그래밍을 했고
수동으로 메모리 관리를 했는데
그래도 알고 넘어 가자

Objective-C  의 수동 메모리 관리 관련 메서드


retainCount : 객체 혹은 인스턴스의 변수가 특정 메모리 공간을 참조 하고 있는가를 나타내는 정수

alloc :  생성된 객체에 메모리 공간을 할장한다.

retain : 객체가 메모리 공간을 참조 하고 있다는 사실을 iOS에 알린다. reationCount를 1증가 시킨다.

release : retainCount 1감소 시킨다.

dealloc : 메모리 공간을 참조하고 있는 모든 객체가 더는 해당 메모리 공간을 사용하지 말라는 명령을 내린다. retainCount = 0


retainCount 값이 1또는 그이상이면 iOS는 메모리 공간을 소유하고 사용할수 있다.
retainCount 값이 0이 될경우 공간에 대한 소유권을 반환받아 할당되었던 메모리 공간을 회수 한다.



약한 참조 (weak reference)
Foo * myFooOne = [[Foo alloc[ initWithName:@"James"];
Foo * myFooTwo = myFooOne       //<--- 약한 참조
[myFooOne release];
//myFooTwo  사용시 런타임 에러 발생



Foo * myFooOne = [[Foo alloc[ initWithName:@"James"];
Foo * myFooTwo = myFooOne       //<--- 약한 참조
[myFooTwo retain]; //<-- 해주어야
[myFooOne release];

//myFooTwo 이용가능


자동 메모리 관리 ARC


ARC는 Automatic Reference Counting의 약자로 기존에 수동(MRC라고 함)으로 개발자가 직접 retain/release를 통해 reference counting을 관리해야 하는 부분을 자동으로 해준다.

1. retain/release/autorelease 키워드 사용금지
2. C 구조체 내에 Object 타입 사용 금지
3. Core Foundation은 Objective-C의 Object 타입이 아니므로 Core Foundation 과 Object 간의 명시적인 타입 캐스팅이 필요 하다.


프로퍼티 속성
strong --> retain 과 거의 같다.

weak 는 assign 키워드 처럼 retainCount를 증가 시키지 않는다.
assign과는 다르게 참조하는 객체가 해제(deallocated)되면 weak로 선언된 프로퍼티는 자동으로 nil이 대입된다

ARC가 없던시절
reain --> strong
assing --> weak 
라고 이해 하면
weak가 assign과 차이점이라면
음 assign은 int float 등등 primitive타입에 사용하는 것이고 weak는 객체에 사용한다고 생각하면 
될듯 하다.

그래도 역시 ARC보단 ARC off가 편할듯 하다.


2013년 4월 25일 목요일

iOS 프로그래밍 팁 - XMLParser


XML 파싱을 위해서는 NSXMLParserDelegate를 구현해야 한다.

헤더 파일에 아래와 같이 <NSXMLParserDelegate>를 추가 한다.

@interface AlumnusViewController : UIViewController <UITableViewDataSource, UITableViewDelegate, NSXMLParserDelegate>


그리고 NSXMLParserDelegate 함수를 구현 한다.
#pragma mark XMLParse delegate methods

- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict {
    
   //xml 엘리먼트 종류 별로 분류 elementType 변수에 설정 한다....
.....
    [_xmlValue setString:@""];
}

- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName {
    
    if (elementType != kBOARDXML)
        return;
    
    if ([elementName isEqualToString:@"boardName"]) {
        [boardData setValue:[NSString stringWithString:_xmlValue] forKey:elementName];
    }
 
//위와 같은 방법으로 엘리먼트 문자열을 비교하여 boardData와 같은 파싱에 결과가 되는
//NSMutableDictionary 에 값을 설정 한다.

}

- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string {

//파서에 들어오는 string을 NSMutableString *_xmlValue에 추가하는 작업을 한다.

    if (elementType == kBOARDXML) {
        if (!_xmlValue) {
            _xmlValue = [[NSMutableString alloc]initWithCapacity:0];
        }
        [_xmlValue appendString:string];
    }
    
 
}



 통신에 결과로  XML데이터를 수신 하였을 경우


- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
    NSXMLParser* parser = [[[NSXMLParser alloc] initWithData:receiveData] autorelease];
    [parser setDelegate:self];
    [boardData removeAllObjects];
    [boardParseData removeAllObjects];
    BOOL success = [parser parse];
    if (success) {
        NSLog(@"XML parse success");
        //테이블 작업....

//파싱에 결과로 생성된 baoradData, boardParseData의 키 밸류를 적절히 활용한다.


        
    }else {
        NSLog(@"XML parse ERROR");
    }



connectionDidFinishLoading 메서드에서 receiveData를 parser로 할당 하고
[parser parse] 메세지가 성공하면 xml 파싱이 성공한 것이다.

success 가 YES일때 파싱 성공에 의해 생성된  NSMutableDictionary 객체 boardData, boardParseData 를 이용한다.

이상 간단하게 XML파서를 이용하는 방법이다.




iOS 프로그래밍 팁 - NSThread 사용하기

알티베이스 메뉴얼 앱을 최초 개발 할 때의 일이다.
기본 아이디어가 알티베이스 메뉴얼 pdf 파일이 여러 개이고
사용자는 이 여러 개의 pdf 파일에서 검색어 하나로 찾고 싶어 할 것이라는 가정 하에

찾을 대상에 pdf 파일 선택 화면을 만들고
선택된 pdf 파일에서 검색어로 키워드를 찾는 것이다.

 pdf에서 text 를 검색하는 것은 상당한 시간이 걸리는 작업이고
이를 여러 파일에 대해서 하려니 UI가 그동안 얼어 버린다.

해서 thread로 구현 해야 했다.


- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar
{
    [searchBar resignFirstResponder];
    [self.view bringSubviewToFront:webActInd];

    [webActInd startAnimating];
    [resultFilename removeAllObjects];
    [resultThumbImg removeAllObjects];
    [resultPageNum removeAllObjects];
    
    [tableView_ reloadData];
    //스레드
    searchText = [NSString stringWithString:searchBar.text];
    [NSThread detachNewThreadSelector:@selector(searchDoJob) toTarget:self withObject:nil];
    
    
    //[webActInd stopAnimating];
}


알티베이스 메뉴얼 버젼 1.0에서 검색 버튼을 눌렀을 때 코드이다.
NSThread 를 사용하여 구동 될 메서드 searchDoJob을 설정 한다.




- (void) searchDoJob
{
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
    
    //pdfSearch = [[[PDFSearch alloc]init]autorelease];
    
    NSUserDefaults *userDefault = [NSUserDefaults standardUserDefaults];
    
    NSString *text = [NSString stringWithString:searchText];
    
    //모든 파일이름을 루프로 돌려 검색 한다.
    
    for (NSInteger j = 0; j< [filename_ count]; j++)
    {
        NSString * filename = [filename_ objectAtIndex:j];
        if ([userDefault boolForKey:filename])
        {
//            NSURL *pdfURL = [[NSBundle mainBundle] URLForResource:filename withExtension:@"pdf"];
//            
//            MFDocumentManager *documentManager = [[MFDocumentManager alloc]initWithFileUrl:pdfURL];



            
            
//            CGPDFDocumentRef document =  CGPDFDocumentCreateWithURL(( CFURLRef)pdfURL);
//            for (NSInteger i=1; i< CGPDFDocumentGetNumberOfPages(document); i++ )
//            {
//                CGPDFPageRef PDFPage = CGPDFDocumentGetPage(document, i);
//                
//                if ([pdfSearch page:PDFPage containsString:text] )
//                {
//                    NSString * pageNumStr= [NSString stringWithFormat:@"%i",i];
//                    [resultFilename addObject:filename];
//                    [resultPageNum addObject:pageNumStr];
//                    
//                    [resultThumbImg addObject:[self imageFromPDFWithDocumentRef:document andPageNum:i]];
//                    
//                    if ([resultFilename count] > 100)
//                        break;
//                    
//                    [tableView_ reloadData];
//                }
//                
//            }
//            CGPDFDocumentRelease(document);
        }
        
        if ([resultFilename count] > 100)
            break;
        
    }
    [webActInd stopAnimating];
    [pool release];
}

선택된 파일들 (filename_ ) array에서 CGPDocuemntRef를 이용해서 주석처리된 부분이 실제로 PDF파일에서 문자열 검색을 하는 부분이고 결과로 pdf 파일 명과 페이지 번호 그리고 썸네일 이미지를 생성하는 부분이다.

현재 1.5버젼 이상 부 터는 fastpdfkit 라이브러리를 사용하기 때문에 관련 코드는 모두 주석 처리 되었다.

이렇게 수행 시간이 오래 걸리는 작업을 처리 하기 위해서는 NSThread가 필요하다.

2013년 4월 24일 수요일

parallels desktop 제거 후 런치패드에 남아 있는 windows7 Applications 폴더 제거 하기

parallels desktop 8 trial을 설치해보았다.

역시 Virtual Box보다 한수위 인 듯 하다.
VirtualBox의 seamless 모드는 시작 메뉴와 바가 mac os 상단에 떡하니 표시 되는것이 거슬려서
사용 하지 않았는데 parallels의 기본 모드는 완전히 통합되어 windows 응용 프로그램이 마치
mac용 응용프로그램과 같이 되고 너무 좋은 듯 했다.

하지만 90000원, 적어도 84000원 이라는 금액의 압박

바로 언인스톨
그냥 Applications 폴더에서 제거 했다.

dock에 남아 있는 windows7 Applications폴더는 그냥 제거 했다.
그럼 끝인 줄 알았는데......

Launchpad 화면에 떡하니 남아 있는 windows7 Applications

헐.....

이거 어떻게 지우지

http://macnews.tistory.com/385
런치패드에 finder 넣기에서 맨 아래 제거 하기...

해서 이 방법으로 잘된다.

sudo sqlite3 ~/Library/Application\ Support/Dock/*.db "DELETE from apps WHERE title='windows7 Applications';" && killall Dock

터미널에서 위와 같이 입력하면 windows7 Applications 폴더를 제거 할 수 있다.

2013년 4월 16일 화요일

iOS 프로그래밍 팁, jSON 객체를 주고 받는 클라이언트 개발

서버 <-----> iOS 클라이언트 관에 데이터 통신을 하는 앱 개발에 필요한 방법을 정리한다.



1. jSON 객체를 주고 받는다.
2. HTTP 프로토콜을 이용한다.
3. jSON 객체 string은 다음에 과정을 거친다.
jSON string --> base64Enc --> AES256Enc --> byte2Hex String --> HTTP 통신 --> 서버
서버 --> HTTP 통신 ---> hex2byte --> AES256Dec --> base64Dec --> JSON string


4. 필요한 모듈
이를 위해 필요한 것은 아래의 NSString 및 NSData 카테고리 클래스를 구해야 한다.



NSString+Base64.m / h

https://github.com/kyoshikawa/ZUtilities/blob/master/NSData%2BAES256.m

NSData+AES25.m / h

https://github.com/nicklockwood/Base64

NSData+Base64.m / h


5. 인크립트 디크립트 함수를 구현 하는 crypto클래스를 작성한다.
... 생략 ....



//string -> base64Enc -> aes256Enc -> byte2hex
- (NSString *) encryptString:(NSString *)textString {
    NSString * base64Enc = [self base64Encode:textString];
    NSData * aes256enc = [self encryptString:base64Enc withKey:[self generateKey]];
    return [self byteToHexString:aes256enc];
}

// hex2byte-> aes256Dec --> Base64Dec --> string
- (NSString *) decryptString:(NSString *)textString {
    NSData * data = [self hexToBytes:textString];
    NSString * aes256dec = [self decryptData:data withKey:[self generateKey]];
    return [self base64Decode:aes256dec];
}

... 생략 ...



6. jSON객체를 핸들링 하기 위한 모듈을 준비한다.
json 객체를 이용하기 위해서는 

http://superloopy.io/json-framework/

에서 jSON 모듈이 필요하다.


7. 서버에 요청 하기 위한 jSON객체 생성과 인크립트를 한다.


NSArray *keys = [NSArray arrayWithObjects:@"graduateNo", @"name", @"alumniName", nil];
    NSArray *objects = [NSArray arrayWithObjects:txtFieldNumber.text, txtFieldName.text, txtFiledAlumiName.text, nil];
    NSDictionary *jsonDictionary = [NSDictionary dictionaryWithObjects:objects forKeys:keys];
    
    NSString *jsonString =[jsonDictionary JSONRepresentation];



위와 같이 key와 key값을 NSArray와 NSDictionary 를 이용하여 jsonString을 얻어 낼수 있다.

인크립트 메서드를 가지고 있는 crypto클래스를 이용해서 전송에 필요한 데이터를 구성한다.


8. 서버에 전송
NSMutableURLRequest,  NSURLConnection 을 이용해서 서버에 전송한다.

NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:
                                    [NSURL URLWithString:[NSString stringWithFormat: @"%@/api/xxxx.api",
                                                          SERVER_URL]]
                                                                cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:5.0];
    
    [request addValue:@"application/x-www-from-urlencoded" forHTTPHeaderField:@"content-type"];
    [request setHTTPBody:jsonData];
    [request setHTTPMethod:@"POST"];
    [request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
    [request setValue:[NSString stringWithFormat:@"%d",[jsonData length]] forHTTPHeaderField:@"Content-Length"];
    
    NSURLConnection *connection = [[[NSURLConnection alloc] initWithRequest:request delegate:self] autorelease];
        
    if(connection) {
receiveData = [[NSMutableData alloc] init];
}

9. 서버로 부터 응답 처리


- (void)connection:(NSURLConnection *)connection didReceiveResponse:

- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error

- (void)connectionDidFinishLoading:(NSURLConnection *)connection

응답에 관련된 메서드를 각각 구현한다.

서버에 응답 데이터에 대해서는
didReceiveResponse 에서 NSData 를 append 하고

connectionDidFinishLoading
에서 완성된 데이터를 crypto 클래스의 decryp 메서드를 이용해서 json 스트링으로 변환 한다.

마지막으로 JSONValue 를 통해서 NSDictionary로 변환 하여 
필요한 값을 valeuForKey로 얻어 낸다.











2013년 4월 15일 월요일

디바이스 좌표계를 OpenGL 좌표계로 변환


OpenGL의 좌표계는 화면에 중심에 0,0 으로 부터 좌측 -1.0 우측 +1.0
위로 +1.0 아래로 -1.0 이더라

마치 수학시간 좌표계

이게 지금까지 컴퓨터 그래픽 좌표계와 달라서 혼돈스럽다.


gwidth
gheight

가 설정되어 있다고 가정 하고 아래에 함수를 이용해서 x,y를 입력하면
OpenGL에서 사용하는 화면에 중앙을 기준으로 float -1.0 ~ +1.0까지의 x, y
좌표 체계로 변환 하는 함수이다.

  void convertDeviceXY2OpenglXY(int x, int y, float * ox, float  * oy)
  {
      int w = gwidth;
      int h = gheight;
      *ox = (float)((x - (float)w/2.0)*(float)(1.0/ (float)(w/2.0)));
      *oy = -(float)((y - (float)h/2.0)*(float)(1.0/ (float)(h/2.0)));
  }

를 이용 할수 있다.


https://github.com/sparrowapps/CohenSutherlandLineClipp

코헨서덜런드 라인클립핑 알고리즘을 mac os에서 OpenGL로 구현할때 
이함수를 이용 하였다.