2

ここに画像の説明を入力

こんにちは、私はこの画像を持っており、2 点間に線「パス」を描きたいと思っています。

私が試したこと:

データベースに保存されている主要なポイントを使用して、パスを描画します。「x,y for the point」と入力し、終点に到達するまでマルチポイント間に線を引きます。画像番号2のように ここに画像の説明を入力

私が考えているのは、画像をたとえば 15*15 などの正方形のグリッドに分割し、各正方形の x、y、タグを 0,1 にすることができる場合です。 1 できます。お風呂を動的に作成します。

それが今のところ私が持っているすべてのアイデアです:)他に方法があれば、私はそれを知りません。助けてください:)

更新

-ユーザーはズームイン/アウトできます。-私がやろうとしていることは、このようなものです

4

7 に答える 7

3

SurfaceViewビットマップを直接変更するか、ビットマップの上に を配置して に描画することができますSurfaceView。このシナリオで行う必要があるのは、 のonDrawメソッドで線を引くことだけSurfaceViewです。

私はTurtle Drawアプリでたくさんの線を描きます...これが私が拡張する方法ですSurfaceView

public class DrawView extends SurfaceView {

    Paint paint = new Paint();

    List < float[] > lines = new ArrayList < float[] > ();
    List < Integer > colors = new ArrayList < Integer > ();
    int curColor = Color.WHITE;
    int bgColor = Color.BLACK;

    Bitmap mBitmap;

    ImageView turtle;

    float curX, curY, curTurn = 0f;

    Matrix transform = new Matrix();

    public DrawView(Context context, AttributeSet attrs) {
        super(context, attrs);
        mBitmap = getBitmapFromDrawable(context);
        paint.setColor(Color.BLACK);
        paint.setStrokeWidth(DpiUtils.getPxFromDpi(getContext(), 2));
        setScrollContainer(true);
        // clear();
    }

    public DrawView(Context context) {
        super(context);

    }

    public void addLine(float...l) {
        synchronized(lines) {
            lines.add(l);
            colors.add(curColor);
        }
    }

    public List < float[] > getLines() {
        return lines;
    }

    public List < Integer > getColors() {
        return colors;
    }

    @Override
    public void onDraw(final Canvas canvas) {

        synchronized(lines) {
            super.onDraw(canvas);
            int i = 0;
            for (float[] l: lines) {
                paint.setAntiAlias(true);
                paint.setColor(colors.get(i++));
                canvas.drawLines(l, paint);
                curX = l[2];
                curY = l[3];
            }

            transform.setTranslate(curX - 13, curY - 13);
            transform.preRotate(360 - curTurn, 13, 13);

            paint.setColor(Color.BLACK);
            canvas.drawBitmap(mBitmap, transform, paint);
        }
    }

    public void setTurn(float turn) {
        this.curTurn = turn;
    }

    public void clear() {
        lines.clear();
        colors.clear();
        DisplayMetrics metrics = DpiUtils.getDisplayMetrics(getContext());

        curX = metrics.widthPixels / 2f;
        curY = (metrics.heightPixels / 2f) - DpiUtils.getPxFromDpi(getContext(), 50);
        curTurn = 0;

        scrollTo(0, 0);
    }

    public static Bitmap getBitmapFromAsset(Context context, String strName) {
        AssetManager assetManager = context.getAssets();

        InputStream istr;
        Bitmap bitmap = null;
        try {
            istr = assetManager.open(strName);
            bitmap = BitmapFactory.decodeStream(istr);
        } catch (IOException e) {
            return null;
        }

        return bitmap;
    }

    public static Bitmap getBitmapFromDrawable(Context context) {
        Bitmap icon = BitmapFactory.decodeResource(context.getResources(), R.drawable.turtle_26);
        return icon;
    }

    public void setDrawColor(int color) {
        paint.setColor(color);
        curColor = color;
    }

    public int getDrawColor() {
        return curColor;
    }

    int x, y = 0;
    int scrollByX, scrollByY = 0;

    @Override
    public boolean onTouchEvent(MotionEvent event) {

        int action = (event.getAction() & MotionEvent.ACTION_MASK);

        if (action == MotionEvent.ACTION_DOWN) {
            x = (int) event.getX() + scrollByX;
            y = (int) event.getY() + scrollByY;
        } else if (action == MotionEvent.ACTION_MOVE) {
            scrollByX = x - (int) event.getX();
            scrollByY = y - (int) event.getY();
            scrollTo(scrollByX, scrollByY);
        }

        return true;
    }

    @Override
    public void scrollTo(int x, int y) {
        // TODO Auto-generated method stub
        super.scrollTo(x, y);
        scrollByX = x;
        scrollByY = y;
    }

    @Override
    public void setBackgroundColor(int color) {
        // TODO Auto-generated method stub
        super.setBackgroundColor(color);
        bgColor = color;
    }

    public int getBackgroundColor() {
        return bgColor;
    }

}
于 2013-09-26T23:55:44.640 に答える
2

Dijkstra's_algorithmを使用して、最短パスを見つけることができます。

ここに画像の説明を入力

A*アルゴリズムのようにこれを行うにはもっと効率的な方法がありますが、ダイクストラの方法が最も簡単に実装できると思います。

于 2013-10-29T14:08:43.353 に答える
2

Pathクラスを利用できます。幸運を!

于 2013-09-26T23:51:21.577 に答える
2

私がよく理解していれば、あなたの主な問題は画像の上に線を引くことではありません。あなたは与えられたマップをどのパスに入れるかを動的に探しています。これは正しいです?

この場合は、A* 検索アルゴリズムを探しています。これは経路探索のよく知られた方法であり、この種の AI を必要とするゲームやその他のアプリケーションでは非常に一般的です。

ニーズに合わせてこのアルゴリズムの独自の実装を開発するか、サードパーティの API を使用してみることができます。

これは、Googleコードから使用できるものです。シンプルな Java と Apache のライセンスなので、Android アプリで使用できます。

でも待ってください、私も github を簡単に見てみましたが、すぐに使用できる実装が他にもたくさんあるようです!

ウェブを検索すると、多くの記事、チュートリアル、論文も見つかります...

幸運を!

編集

以下のコメントで説明したように、主な問題は、「マップ」を動的に処理して「壁」を見つけて、A * 検索を適用し、最後にその上に線を引くことです。

まあ、画像を動的に処理するには、サードパーティのライブラリが必要です。そこにはたくさんありますが、おそらくより良い解決策はOpenCVを使用することです。Android と互換性があり、優れたドキュメントとそれに関する多くの記事があります。これは、画像内の「線」を見つけるための例を含むチュートリアルです。これは、マップにも適用できます。おそらく、壁の太い線だけが検出されるまで、しきい値を調整する必要があります。

于 2013-10-23T14:14:02.567 に答える
0

これは、OpenGL を使用しないと不可能だと思います (そして、線の X/Y 位置を画面上の実際の X/Y 位置に変換する仕事をさせます)。

OpenGL では、フロアプラン イメージを 2D 平面にレンダリングします。線を描画する各交点のワールド空間位置 (x、y、z) を事前に計算し、各位置が接続できる他の位置の配列を持つコレクションを作成する必要があります。次に、(再帰的な) ロジックを実行して、始点と終点の間にあるポイントを特定し、それぞれの間に 2D 線を描画する必要があります。

したがって、可能性は非常に高いですが、パンとズームの必要性により、OpenGL の出番となるカメラの必要性がほとんどなくなります。

パンとズームは、(選択した FOV に基づいて) 画像の端を超えて (過度に) 表示されないように、カメラを事前に定義された範囲内に保ちながら移動することで処理されます。

于 2013-10-28T23:06:06.273 に答える
0

画像内の白いピクセルを検索してみてください(それはあなたが投げることができるあなたの道です)

于 2013-10-28T12:46:41.243 に答える
0

私の答えは、誰かが黒い円から赤い円に移動するための最も簡単な経路を計算しようとしていると仮定しています. 実際の線の描画に関するヘルプのみを探している場合は、この回答を無視してください。また、事前にすべての交点を定義できると仮定しています。写真からプログラムでそれらを導出する必要がある場合は、おそらく新しい質問から始める必要があります。

あなたが提案している(x、y)ポイントから始めますが、タグ値は省略します。次に、タグ値よりも詳細を追加する関連オブジェクトとして、これらのポイント間の接続を追加します。各ポイントには、他の隣接するポイントへの一連の接続があります。接続ごとに、距離、障害物、特権などのその他の拡張機能など、計算に使用する属性の束を配置します。距離は簡単です (ヒント: ピタゴラスの定理を使用してください)。障害物には、ドア、階段、エレベーターなどが含まれる場合があります。特権には、アクセスが制限されたエリアが含まれる場合があります (図の上部にある斜めの通路が制限されているように見えます)。

黒いスタート地点は東西どちらにも行けるようです。それは2つの異なるパスになります。東への最初のポイントは、4 つの選択肢を提供します: 北へのドア、南へのドアを通過するか、東に進むか、西に戻ります。西のオプションは、パスがループとして無視できる元のポイントに戻ります。南へのオプションは、ループとして無視できるこのポイントに戻るだけです。北へのオプションは興味深いものです。なぜなら、それは斜めの回廊を通って続き、最終的には目的地への道を提供するからです。ただし、明らかに最適な道ではありません。東へのオプションが続き、最終的にいくつかのオプションが返されます。パスが目的地に到達すると、通過した接続 (距離、

これを実装するには、通過したポイントのリストと、それらのポイントに沿った各接続の累積された難易度を含むパスを導入する必要があります。原点から始めて、すべてのパスを完全にトラバースしようとするのではなく、すべての方向に 1 つのステップを分岐するものを作成しようとします。各ステップで累積された難易度に追加します。ポイントが目的地である場合、成功したパスがあります (ただし、最も効率的なパスではない可能性があります)。ポイントがすでにパス内にある場合はループなので、そのパスのトラバースを停止します。パスの累積された難易度が、既に見つかっている別のパスよりも大きい場合は、そのパスをたどるのをやめます。

于 2013-10-28T16:09:36.243 に答える