void testApp::draw()
{
    
    //=====================
    // 入力画像抽出処理開始
    //=====================
    if (bProcessGetDraw) {
        bool bError = false;
        mTmpWindow.grabScreen(0, 0, ofGetWidth(), ofGetHeight()); //表示中の画面を取得
        
        //----------
        // 描画がある場合は波形変換を開始
        //----------
        if (mPts.size()) {
            
            //----------
            // 図形の格子範囲を取得
            //----------
            ofRectangle scaleRect;
            float minX = ofGetWidth();
            float minY = ofGetHeight();
            float maxX = 0;
            float maxY = 0;
            for (int i=0; i < mPts.size(); i++) {
                if (mPts[i].x < minX) minX = mPts[i].x;
                if (mPts[i].y < minY) minY = mPts[i].y;
                if (mPts[i].x > maxX) maxX = mPts[i].x;
                if (mPts[i].y > maxY) maxY = mPts[i].y;
            }
            //正確に取得できたかチェック
            if (minX > maxX || minY > maxY) {
                cout << "[ERROR] 描画領域の取得に失敗しました" << endl;
                bError = true;
                goto _FAILD_GET_DRAWING;
            }
            scaleRect.set(minX, minY, maxX-minX, maxY-minY);
            mPtsRect = scaleRect;
            
            //----------
            // 格子範囲を正規化
            //----------
            scaleRect.setPosition((ofGetWidth()/2)-(scaleRect.width/2), (ofGetHeight()/2)-(scaleRect.height/2));
            float tScale = 1.0f;
            if (scaleRect.width < scaleRect.height) {
                tScale = (float)ofGetHeight() / scaleRect.height;
            } else {
                tScale = (float)ofGetHeight() / scaleRect.width;
            }
            scaleRect.scaleFromCenter(tScale);
            scaleRect.setPosition(0, 0);

            //----------
            // 正規化した格子範囲に合わせて図形の大きさを変更した座標配列を取得
            //----------
            vector<ofPoint> tPts;
            for (int i=0; i < mPts.size(); i++) {
                float tX = ofMap(mPts[i].x, minX, maxX, scaleRect.x, scaleRect.width);
                float tY = ofMap(mPts[i].y, minY, maxY, scaleRect.y, scaleRect.height);
                ofPoint tPoint = ofPoint(tX, tY);
                tPts.push_back(tPoint);
            }
            
            if (bCircleMode) {
                //----------
                // 円モードの場合は円を描画
                //----------
                if( mPts.size() > 0 ) {
                    float size = ofDist(mPts[0].x, mPts[0].y, mPts[mPts.size()-1].x, mPts[mPts.size()-1].y);
                    mVecOut.circle(mPts[0].x, mPts[0].y, size);
                }
            } else {
                //----------
                // 描いた図形をfillして描画
                //----------
                int numPts = tPts.size();
                int rescaleRes = 2;
                mVecOut.fill();
                mVecOut.beginShape();
                for(int i = 0; i < numPts; i++){
                    if(i == 0 || i == numPts -1){
                        mVecOut.curveVertex(tPts[i].x, tPts[i].y);
                    }
                    if(i % rescaleRes == 0) mVecOut.curveVertex(tPts[i].x, tPts[i].y);
                }
                mVecOut.endShape();
            }
            
            //スクリーンショット
            mGrabImage.grabScreen(0, 0, ofGetWidth(), ofGetHeight());
            mTmpWindow.draw(0, 0); //元の画面を描画
            
            bProcessGetDraw = false;
            
            
            //----------
            // フーリエ記述子の計算 - 波形変換 - OSC送信
            //----------
            calcFourier();
            
            //----------
            // Figureクラスのインスタンスを生成して輪郭座標点を渡す
            //----------
            Figure tmpF;
            
            //図形IDを設定
            if (mFMode==STATIC) {
                //STATICモードの場合はOSCで送られてくるシーケンサーの現在の数値をIDとする
                tmpF.setID(mSeqCurrentNum);
            } else if (mFMode==FLORTING) {
                tmpF.setID(0);
            } else if (mFMode==AROUND) {
                tmpF.setID(mFigures[2].size());
            }
            
            //円モードの場合は計算に使用した輪郭点を描画点として置き換える
            if (bCircleMode) {
            
                vector<ofPoint> edgePts;
                for (int i=0; i < mResizedPts.size(); i++) {
                    edgePts.push_back(mResizedPts[i]);
                }
                tmpF.setPts(edgePts);
                tmpF.setEdgePts(edgePts);
            
            } else {
            
                //計算に使用した輪郭点座標を元の大きさにスケーリングして取得
                vector<ofPoint> edgePts;
                for (int i=0; i < mEdgeBits.size(); i++) {
                    ofPoint tmpPoint;
                    tmpPoint.set(ofMap(mResizedPts[i].x, scaleRect.x, scaleRect.width, minX, maxX),
                                 ofMap(mResizedPts[i].y, scaleRect.y, scaleRect.height, minY, maxY));
                    edgePts.push_back(tmpPoint);
                }
                tmpF.setEdgePts(edgePts);
                tmpF.setPts(mPts);

            }
            //モードをセットしてモードごとの配列に格納
            //MEMO:現状、図形モードは配列の要素数とインスタンス毎のモード設定の2つで管理しているので、どっちかにしたい
            tmpF.setMode(mFMode);
            switch (mFMode) {
                case STATIC: mFigures[0].push_back(tmpF); break;
                case FLORTING: mFigures[1].push_back(tmpF); break;
                case AROUND: mFigures[2].push_back(tmpF); break;
            }
            
            //----------
            // OSCでもろもろ送信
            // 1.モードID 2.図形ID 3.全ビット 4.重心座標
            //----------
            sendModeId((int)mFMode);
            switch (mFMode) {
                case STATIC: sendBits(0, tmpF.getID()); sendPos(0, tmpF.getID(), tmpF.getCentPos()); break;
                case FLORTING: sendBits(1, mFigures[1].size()%2); sendPos(1, mFigures[1].size()%2, tmpF.getCentPos()); break;
                case AROUND: sendBits(2, mFigures[2].size()-1); break;
            }
            
            mPts.clear();
        }
    
    _FAILD_GET_DRAWING:
        if (bError) {
            cout << "[ERROR] 画像の取得に失敗しました" << endl;
        }
        
    //====================
    // 入力画像抽出処理終了
    //====================
        
    } else {
        
        //----------
        // ルーラー
        //----------
        ofPushStyle();
        ofSetColor(40);
        for (int i=0; i < ofGetWidth(); i += 10){
            if (i%100 == 0) {
                ofSetLineWidth(2);
                ofLine(i, 0, i, ofGetHeight());
            } else {
                ofSetLineWidth(1);
                ofLine(i, 0, i, ofGetHeight());
            }
        }
        for (int i=0; i < ofGetHeight(); i += 10){
            if (i%100 == 0) {
                ofSetLineWidth(2);
                ofLine(0, i, ofGetWidth(), i);
            } else {
                ofSetLineWidth(1);
                ofLine(0, i, ofGetWidth(), i);
            }
        }
        
        //描画中
        if (bDrawing) {
            ofSetLineWidth(1);
            ofSetColor(255);
            for (int i=0; i < ofGetWidth(); i += 10){
                if (i%100 == 0)
                    ofLine(i, 0, i, 15);
                else
                    ofLine(i, 0, i, 10);
            }
            for (int i=0; i < ofGetHeight(); i += 10){
                if (i%100 == 0)
                    ofLine(0, i, 15, i);
                else
                    ofLine(0, i, 10, i);
            }
            ofSetColor(120, 150, 120);
            ofLine(mouseX, 0, mouseX, ofGetHeight());
            ofLine(0, mouseY, ofGetWidth(), mouseY);
            ofSetColor(220);
            ofDrawBitmapString(ofToString(mouseX, 2), mouseX+10, 25);
            ofDrawBitmapString(ofToString(mouseY, 2), 15, mouseY+10);
        }
        ofPopStyle();
        
        //----------
        // 形態を描画
        //----------
        for (int i=0; i < mFigures.size(); i++) {
            for (int j=0; j < mFigures[i].size(); j++) {
                mFigures[i][j].draw();
                if (bDebugMode) {
                    mFigures[i][j].debugDraw();
                }
            }
        }
        
        if (bCircleMode) {
            //----------
            // 円モードの場合は円を描画
            //----------
            if( mPts.size() > 0 ) {
                float size = ofDist(mPts[0].x, mPts[0].y, mPts[mPts.size()-1].x, mPts[mPts.size()-1].y);
                mVecOut.circle(mPts[0].x, mPts[0].y, size);
            }
        } else {            
            //----------
            // 自由線画像を描画
            //----------
            if( mPts.size() > 0 ) {
                int numPts = mPts.size();
                int rescaleRes = 2;
                mVecOut.noFill();
                mVecOut.beginShape();
                for(int i = 0; i < numPts; i++){
                    if(i == 0 || i == numPts -1){
                        mVecOut.curveVertex(mPts[i].x, mPts[i].y);
                    }
                    if(i % rescaleRes == 0) mVecOut.curveVertex(mPts[i].x, mPts[i].y);
                }
                mVecOut.endShape();
                
                //もし開始点に近い場合はマークを表示
                if (ofDist(mPts[0].x, mPts[0].y, mouseX, mouseY) < 20 && mPts.size() > 10) {
                    ofPushStyle();
                    ofSetColor(255, 0, 0);
                    ofNoFill();
                    ofSetLineWidth(2);
                    ofCircle(mPts[0], 20);
                    ofPopStyle();
                }
            }
        }
    }
    
    if (bDebugMode) {
        debugDraw();
    }
}