1

ボクセルから楕円体を作成していて、実装がありますが、正しく機能していません。過去数時間、試行錯誤を繰り返してきましたが、成功しませんでした。

仕組みは次のとおりです。

  • Bresenham円アルゴリズムを使用してZ軸に2D楕円を描画します
  • 前方の円と左右に向かう円の座標を計算します
  • これらの座標をXとYの半径として使用します

動作するものは次のとおりです。

  • 球は完璧です
  • 楕円体は次の場合に最適です
    • z>xおよびz>y
    • x == y

そうでないものは次のとおりです。

毎回中央から前にスライスを描いているので推測していますが、わかりません。以下は私の実装です、それは混乱です。すぐに少しクリーンアップしたので、ある程度理解できます。また、後で使用するために最適化を保存しています。今すぐ機能させたいだけです。

サークルアルゴリズム自体の実装については説明しません。これは、サークルアルゴリズムが機能することを知っており、この質問が長くなるだけだからです。そこで、代わりに2つの機能について説明します。

private List<Integer> getSlice(int rx, int ry)Bresenham円アルゴリズムの実行から生の結果を取得します。対称性は必要ありません。結果をx、yの結果のリストとしてこの順序で返します。

public void generateEllipse(int z, int cx, int cy, int cz, int rx, int ry)与えられた情報で楕円を生成し、対称性を使用して座標をプロットします。これらは画面にレンダリングされます。

ArrayList<Integer> s = getSlice(rz, rx);
ArrayList<Integer> s2 = getSlice(rz, ry);

int cap = Math.max(s2.size(), s.size());

while (s.size() > 1)
{
    int x = 0;
    int z = 0;
    int z2 = 0;
    int y2 = 0;

    int i = cap - 2;

    if (s.size() > i)
    {
        z = s.get(i);
        x = s.get(i + 1);

        s.remove(i + 1);
        s.remove(i);
    }

    if (s2.size() > i)
    {
        z2 = s2.get(i);
        y2 = s2.get(i + 1);

        s2.remove(i + 1);
        s2.remove(i);
    }

    if (x != 0 && y2 != 0)
        generateEllipse(z, cx, cy, cz, x, y2);

    cap = Math.max(s2.size(), s.size());

私は1、2週間前に同様の質問をしました(ええ、私は長い間問題を抱えていました:()そして答えを得ました、私はそれを実装しました、そしてそれはうまくいきました、しかし私は満足しませんでした、私は浮動小数点数を避けたいです個別のユニットからの3D楕円体を参照してください。

それで、数字を四捨五入して不均一なスライスを取得するのに問題があったので、球は不可能でした。皮肉なことに、現在可能なのは球だけです(前から後ろへの楕円を除く)。

編集:

追加することでx>yが機能するようになりました

else if (y2 < x && ry - y2 != 0)
    generateEllipse(z, cx, cy, cz, x, ry - y2);

一番下の|| r - y2 == 0最初のテストに。

なぜそれがうまくいったのかよくわかりません、私は今それを理解しています。しかし、私はまだy>xの問題を抱えています。誰?

EDIT2:

これを見てみると、y = x楕円体とは異なり、製図板に戻ります。

EDIT3:

昨夜私はこれについて考えていました、そして私はそれを理解したと思います、これは私自身の質問への答えではありません、しかし私は私が間違っていると見ているものを指摘していると思います。最初のリストをテストし、最大のリストのサイズから徐々に座標を描画しています。

2つのリストが同じ長さであることが保証されていないため、これは悪いことです。これは、アルゴリズムを急がせようとした私の側の失敗です。

写真では見えませんが、小さな楕円は実際には大きな楕円から数ブロック離れています。これは、楕円が描画されていない場合に発生します。これは、リストにデータがないことが原因です。実際の小さな楕円の大きな楕円は、アルゴリズムが2つの八分円を描画するために発生します。これらは両方とも、からリストに格納されgetSlice(...)ます。

では、どうすればこの問題を解決できますか?私はまだ何も実装しておらず、おそらくしばらくは実装しないでしょう(それは早いです)が、これは私の脳がクランクアウトしたものです。繰り返しますが、これは質問に対する答えではなく、単なる考えです。

while(!s.isEmpty())ループの外側で2つの新しい値を繰り返し定義します。incX = s.sizeそしてincY = s1.size、それらのz値が一致するかどうかをテストし、一致しない場合は修正します。値を取得し、最大のリストをテストし、それらが一致しない場合は、最小のリストのinc値を2つ減らして、古い値を取得すると思います。

!s.isEmpty()2つのリストが同時に空になるため、テストします。また、楕円を描画する場合は、どちらか1つのz値を使用します。これも、両方が等しくなければならないためです。

それが間違っている場合は、私が見つけたこのドキュメントを持っていると思います:http ://www.cs.sunysb.edu/vislab/wordpress/pdf/398.pdf 。

4

1 に答える 1

2

これをご覧いただきありがとうございます(返信はありませんでしたが:()、問題が解決したのでこの回答を設定します。コードは次のとおりです。

    ArrayList<Integer> s = getSlice(rz, rx);
    ArrayList<Integer> s2 = getSlice(rz, ry);

    boolean yMax = Math.max(s2.size(), s.size()) == s2.size();

    int decX = s.size() - 1;
    int decY = s2.size() - 1;

    boolean done = false;

    while (!done)
    {

        int x = 0;
        int z = 0;
        int z2 = 0;
        int y = 0;

        y = s2.get(decY--);
        z2 = s2.get(decY--);

        x = s.get(decX--);
        z = s.get(decX--);

        if (z != z2)
        {
            if (yMax)
            {
                decX += 2;
                x = s.get(decX);

                s2.remove(decY + 2);
                s2.remove(decY + 1);    
            }
            else
            {
                decY += 2;
                y = s2.get(decY);

                s.remove(decX + 2);
                s.remove(decX + 1); 
            }

            z = z < z2 ? z : z2;
        }
        else
        {
            s.remove(decX + 2);
            s.remove(decX + 1);             

            s2.remove(decY + 2);
            s2.remove(decY + 1);    
        }

        if (y != 0 && x != 0)
            generateEllipse(z, cx, cy, cz, x, y);

        done = yMax ? s2.isEmpty() : s.isEmpty();
    }

今やらなければならないのは最適化だけです。私はまだその論文を読むつもりです、それは私のプログラムにとって興味深くそして役に立つ他のトピックをカバーしています:)。

問題は、各リストのさまざまなサイズを考慮していなかったことです。曲線が他の曲線よりも急勾配でない場合は、座標が多くなります。rx == ryの場合、Zは常に同じになります。これにより、球体を描画し、楕円体を前方から後方に描画することができました。

それらが同じでない場合、曲線が速く/遅くなるため、zが変化します。私が最初のリストをテストしているときにこれが起こったとき、反復がそれらに到達する前に停止するため、それらを無視していました。

大きな楕円、小さな楕円は後方に描画されたために発生したため、最初に外側のオクタントが描画されましたが、合計値が少なくなっています。

近い将来、私ははるかに詳細な答えとはるかにエレガントな実装を提示する予定です。問題が解決したことを通行人に知らせるために、この回答を提示しています。このすべてを理解しようとして私がした欲求不満を誰にも経験させたくありません!最も困難な問題が最も愚かなことによって引き起こされるのは驚くべきことです。

于 2012-04-05T14:26:46.527 に答える