0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

p5.jsとlibtessを使って文字をスライスする

Last updated at Posted at 2025-09-13

はじめに

 文字をスライスする。libtessの機能を使って実行する。これが無いと大変だろう。
 元のcontoursはこんなの:

wdfwcwcwcfwc.png

これをこんな感じで真っ二つにする:

erteegege.png

断面は、別に直線である必要は無く、曲がっていても実行できる。要は面白いかどうかだが、それについては不問とする。技術を淡々と紹介するだけのアカウントです。よろしく。

コード全文

slice text

let font;
const {initTessy, triangulate} = fisce.foxTess;

// https://beta.p5js.org/reference/p5.font/texttocontours/

async function setup() {
  createCanvas(400, 400);
  font = await loadFont('https://inaridarkfox4231.github.io/assets/KosugiMaru-Regular.ttf');
  textAlign(CENTER,CENTER);
  textSize(280);
  const prepreContours = font.textToContours('', width/2, height/2, { sampleFactor: 0.5 });

  const preContours = [];
  for(const ctr of prepreContours){
    const contour = [];
    for(let k=0; k<ctr.length; k++){
      contour.push(ctr[k].x, ctr[k].y);
    }
    preContours.push(contour);
  }

  initTessy(libtess);
  const rawContours = triangulate(preContours, {rule:"nonzero", boundaryOnly:true});

  // ここでcontourを追加する
  const lowerContour = [400,0,400,400,0,400];
  const upperContour = [0,0,400,0,0,400];

  // rawに三角を加えてabs_geq_twoを使う
  const lower = triangulate([...rawContours, lowerContour], {rule:"abs_geq_two", boundaryOnly:true});
  // additiveを逆向きにしてabs_geq_twoを使う
  const upper = triangulate([...rawContours, upperContour], {rule:"abs_geq_two", boundaryOnly:true});

  const ctx = drawingContext;
  ctx.fillStyle = "white";
	
  const drawContours = (contours) => {
    ctx.beginPath();
    for(const contour of contours){
      for(let k=0; k<contour.length; k+=2){
        if(k===0){
          ctx.moveTo(contour[0], contour[1]);
        }else{
          ctx.lineTo(contour[k], contour[k+1]);
        }
      }
    }
    ctx.closePath();
    ctx.fill();
    ctx.stroke();
  }

  draw = () => {
    background(64);
    strokeWeight(4);

    const t = frameCount%60;
    const shift = Math.pow(t/60, 0.5)*60;
    translate(2+shift,2-shift);
    ctx.strokeStyle = "red";
    drawContours(lower);
    translate(-4-shift*2,-4+shift*2);
    ctx.strokeStyle = "blue";
    drawContours(upper);
  }
}

p5.jsのバージョンは最新版の2.0.5です。あ、ライブラリ使ってるわこれ...まあいいか。以前紹介した方法と同じことをやってるので特に問題ないですね。ついでにもちろん1.2.2のlibtessも使ってますね。関数の内容は一緒です。

エッセンスだけ理解できればこっちを改変したバージョンで実行できるので問題ないですね。

nonzero

 まずいつものようにtextToContoursでcontourを取得して、nonzeroで加工する。フォントによってはこれをしないとcontourがつながってくれないので。今回はKosugiMaruなので不要だけど。あの漢字に特に意味は無いけど漢字って穴がたくさん開いてるからテストに便利なんですよね。

追加contour/abs_geq_two

  // ここでcontourを追加する
  const lowerContour = [400,0,400,400,0,400];
  const upperContour = [0,0,400,0,0,400];

  // rawに三角を加えてabs_geq_twoを使う
  const lower = triangulate([...rawContours, lowerContour], {rule:"abs_geq_two", boundaryOnly:true});
  // additiveを逆向きにしてabs_geq_twoを使う
  const upper = triangulate([...rawContours, upperContour], {rule:"abs_geq_two", boundaryOnly:true});

lowerとupperは右上から左下に向かう線で分かれた2つの直角二等辺三角形の外周です。これを2つ用意して、それぞれともとの文字のcontourを組み合わせます。んで、どこを取るかというと、abs_geq_twoを使います。なぜかというと結局描画領域が1なので、追加するとそれで囲まれた部分が2になるんですよね。だからabs_geq_two, 2だけ切り取られるってわけです。

描画

 で、contoursが取得できたので描画します。beginContour...を使ってもいいんですけど、めんどくさいので、ctxでやります。

  const drawContours = (contours) => {
    ctx.beginPath();
    for(const contour of contours){
      for(let k=0; k<contour.length; k+=2){
        if(k===0){
          ctx.moveTo(contour[0], contour[1]);
        }else{
          ctx.lineTo(contour[k], contour[k+1]);
        }
      }
    }
    ctx.closePath();
    ctx.fill();
    ctx.stroke();
  }

スライスされてる感を出すためにtranslateでいじってます。p5とctxがごっちゃごちゃ。

  draw = () => {
    background(64);
    strokeWeight(4);

    const t = frameCount%60;
    const shift = Math.pow(t/60, 0.5)*60;
    translate(2+shift,2-shift);
    ctx.strokeStyle = "red";
    drawContours(lower);
    translate(-4-shift*2,-4+shift*2);
    ctx.strokeStyle = "blue";
    drawContours(upper);
  }

まあ万能なライブラリなんかあるわけないので、自由にあれこれ使えばいいんです。p5しか使えないのでは窮屈なので。
 最近遊んだプラットフォームが頑なにp5しか使わせてくれなかったので、ちょっと思うところがありました。自由が一番ですよね。

おわりに

 ここまでお読みいただいてありがとうございました。

追記(2025/09/23)

 この記事を書いてる間は全く気付かなかったんですが、この記事を見てもわかるように、「獣」の字が上の方にずれてますよね?実はtextToContoursはChrome系とFirefox系で挙動が異なるようです。ざっくりいうとFirefox系ではセンタリングに失敗します。原因は不明です。次の更新で直されるでしょう。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?