int HeuristicPacker::bottomLeft(int width, int height, vector<Item>& items) {
	#ifdef BOTTOMLEFT_LOG
	cout << "Starting BottomLeft algorithm (" << 
		items.size() << "):" << endl;
	#endif
	
	sortItems(items.begin(), items.end());
	
	#ifdef BOTTOMLEFT_LOG
	cout << "Sorted Input List (" << items.size() << "):" << endl;
	for (size_t i = 0; i < items.size(); i++) {
		cout << items[i] << endl;
	}
	#endif

	int iteration = 0, bestSol = INF;
	do {	
		#ifdef BOTTOMLEFT_COST_LOG
		cout << "starting iteration (" << iteration << ")" << endl;
		cout << "bestSol: " << bestSol << endl;
		#endif

		int currentSol = 0;

		vector<Point> contourPoints;
		Point p;
		vector<Item> packed;
	
		for (size_t i = 0; i < items.size(); i++) {
			#ifdef BOTTOMLEFT_LOG
			cout << "Trying to pack: " << items[i] << endl;
			#endif

			getContourPoints(width,
					 height,
					 items[i],
					 packed,
					 contourPoints);

			#ifdef BOTTOM_LEFT_LOG
			cout << "Contourpoints:" << endl;
			for (size_t i = 0; i < contourPoints.size(); i++)
				cout << contourPoints[i] << endl;
			#endif
		
			if (choosePoint(contourPoints, packed, items[i], p)) {
				#ifdef BOTTOMLEFT_LOG
				cout << "Selected Point: " << p << endl;
				#endif
				pack(items[i], packed, p, currentSol);
			} else {
				#ifdef BOTTOMLEFT_LOG
				cout << "No valid points." << endl;
				#endif
				currentSol = INF;
				break;
			}		
		}
		
		#ifdef BOTTOMLEFT_COST_BEST
		if (currentSol != INF) {
			cout << "(" << currentSol << ")" << endl;
		} else {
			cout << "." << endl;
		}
		#endif

		bestSol = min(bestSol, currentSol);
		randomlySwap(items);

		if (bestSol <= height)
			break;
	} while ((++iteration) < this->_nIter);
	
	#ifdef BOTTOMLEFT_COST_LOG
	cout << endl << "Best solution Found:" << bestSol << endl;
	#endif
	
	return bestSol;
}
/**
 フーリエ記述子などの計算
 */
void testApp::calcFourier()
{
    //既に計算した輪郭座標配列は削除
    mEdgeBits.clear();
    mResizedPts.clear();
    
    //周波数変換
    if (mGrabImage.isAllocated()) {
        ofPixels px;
        ofPoint tPos;
        
        px.allocate(mGrabImage.width, mGrabImage.height, 1);
        
        //----------
        // 入力画像から2値画像を生成
        //----------
        mGrabImage.setImageType(OF_IMAGE_GRAYSCALE);
        px.set(0);
        for (int i=0; i < (mGrabImage.width * mGrabImage.height); i++) {
            if (mGrabImage.getPixels()[i] > 0) {
                px.getPixels()[i] = 255;
            } else {
                px.getPixels()[i] = 0;
            }
        }
        
        //----------
        // 2値画像を輪郭追跡メソッドに引き渡して描く輪郭点を取得
        //----------
        vector<ofPoint> pts = getContourPoints(px);
        if (pts.empty()) return;
        
        //----------
        // 指定した間隔毎のポイントから開始点との角度を取得
        //----------
        //開始点の0を追加
        mEdgeBits.push_back(0.0f);
        tPos.set(pts[0]);
        
        //一周分指定した間隔で前角度を計算
        for (int i=0; i < pts.size(); i++) {
            double dstWave;
            //開始点との(輪郭線上の)距離を計算
            //もし間隔が一定以上出ない場合はその点を除外
            double tDist = ofDist(tPos.x, tPos.y, pts[i].x, pts[i].y);
            if (tDist < mInterval) continue;
            //角度を計算
            double rnd = atan2((double)(pts[i].y - tPos.y),(double)(pts[i].x - tPos.x));
            dstWave = sin(rnd);
            //波形ビット配列に代入
            mEdgeBits.push_back(dstWave);
            //値を保持
            tPos = pts[i];
            
            //描画線座標配列からインターバルをとった座標配列にセット
            mResizedPts.push_back(pts[i]);
        }
        
        //debug print
//        if (mEdgeBits.size()) {
//            cout << "size" << mEdgeBits.size() << endl;
//            for (int i=0; i < mEdgeBits.size(); i++) cout << mEdgeBits[i].dist << ", " << mEdgeBits[i].bit << endl;
//            cout << "\n\n";
//        }
    }
}