読者です 読者をやめる 読者になる 読者になる

プログラムdeタマゴ

nodamushiの著作物は、文章、画像、プログラムにかかわらず全てUnlicenseです

GeneralPathとPathIteratorの諸注意

去年の10月に書いた記事マウスをShape(PathIterator)の形にドラッグ(移動)させようNI-Lab.さんの記事をdisったら、まさか本人さんからうんこ喰らえやゴルァと………、すいません、嘘です


別にCloseするときに移動しなくても正しい結果出てね〜、と言われたので、厚かましい顔してちょっと解説です。

GeneralPathやPathIteratorにおける単語の意味は以下の様になります

セグメント 説明
move to 現在の点を変更する。ラインは引かない。
鉛筆を上げて移動するイメージ。
注意点として、最後にmove toした点は記憶する
line to 現在の点から次の位置までラインを引き、現在の点も変更する。
鉛筆で書きながら移動するイメージ
ちなみに、close toの直後に出てきても良い。
close to 現在のパスを閉じる。
最後にmove toした位置へline toをすると思えばいい。
close toした後に次のパスを書くためにmove toを必ずしもしなければならないわけではない。
故にclose toの後にclose toが来ても問題はないが、同じ点から同じ点へ線を引くので意味ない。
cubic to line to の(ペジェ)曲線版。指定する点は三つ(現在の点*1、目的地、パラメタ1)
quad to line to の(ペジェ)曲線版。指定する点四つ(現在の点*2、目的地、パラメタ1、パラメタ2)



で、NI-Lab.さんに、close toでわざわざ点を追加しなくても、正しい出力結果が出てるよ、と言われちゃいました。
ただしい結果が出てるのは、このソースコードの為です

  private static Shape createPolygon2() {
 
    // 9の字
    //パスの内部を決める偶奇屈曲規則
    GeneralPath p = new GeneralPath(GeneralPath.WIND_EVEN_ODD);
    // 外側
    p.moveTo(10, 10);
    p.lineTo(50, 10);
    p.lineTo(50, 60);
    p.lineTo(10, 60);
    p.lineTo(10, 50);
    p.lineTo(40, 50);
    p.lineTo(40, 40);
    p.lineTo(10, 40);
    p.lineTo(10, 10);//ここで自前で閉じているのに(by nodamushi)
    p.closePath();//再び閉じている(by nodamushi)
    // 内側
    p.moveTo(20, 20);
    p.lineTo(40, 20);
    p.lineTo(40, 30);
    p.lineTo(20, 30);
    p.lineTo(20, 20);//これで閉じている(by nodamushi)
    p.closePath();//のにまた閉じている(by nodamushi)
 
    return p;
  }



p.lineTo(10,10);とp.closePath();およびp.lineTo(20,20);とp.closePath();
のどちらかが不要です。

実際にlineToの方を外してGrahpics2Dのdraw(Shape)で描画してみます

きちんと閉じた図が得られました。
ですが、この外した状態ではNI-Lab.さんのコードでは最後の閉じるための点を取得できません。


というわけで、NI-Lab.さんのPathIterator解読部分のソースコードを修正すると以下の様な感じになります。

      case PathIterator.SEG_CLOSE:
        if (currentPoints.size() > 0) {
          Point2D.Double d = currentPoints.get(0);
          currentPoints.add(new Point2D.Double(d.x,d.y));
          //ここまでで最後にmoveToされた点の追加が終了
          pointsList.add(currentPoints.toArray(new Point2D[currentPoints.size()]));
          currentPoints = new ArrayList();
          //次にlineToが来るときの為に現在の点を追加しておきます
          currentPoints.add(new Point2D.Double(d.x,d.y));
        }
        break;




(´◉◞౪◟◉)ドヤァ〜


∵(´ε(○=(・∀・*)

*1:すでにこの点はあります

*2:すでにこの点はあります