メインコンテンツまでスキップ

チュートリアル点、線、矩形クラス

📚 Source Page

を使用する。Point,LineそしてRectangleクラスを使用すると、ジオメトリの計算が簡単になります。

レベル初心者

プラットフォーム:Windows, macOS, Linux, iOS, Android

クラス: Point,Line,Rectangle,Path,Random,Range

スタート

このチュートリアルのデモ・プロジェクトのダウンロードはこちらから:PIP|ZIP.プロジェクトを解凍し、最初のヘッダーファイルをProjucerで開く。

このステップでヘルプが必要な場合は、以下を参照してください。Tutorial: Projucer Part 1: Getting started with the Projucer.

デモ・プロジェクト

このデモ・プロジェクトは、いくつかの簡単な描画操作を行います。デフォルトの状態では、左上に小さなオレンジ色の四角がある灰色の背景を描画します:

正方形のシンプルな図面
正方形のシンプルな図面

線と長方形のさまざまな描画方法と、線と長方形がどのように描画されるかを見ていきます。Point,LineそしてRectangleクラスは、JUCEでの描画操作(およびコンポーネントの位置)に関する考え方を単純化します。

長方形の基本

グラフィックス描画やコンポーネント・レイアウトのコードの多くは、矩形を扱う必要があります。このチュートリアルでは、塗りつぶされた正方形の単純な描画から始めます。これからPoint,LineそしてRectangleクラスは描画操作に役立ちます。これらのテクニックは、子コンポーネントの配置にも応用できます(Component::resized()関数の中で)。私たちのpaint()関数はこうだ:

    void paint (juce::Graphics& g) override
{
g.fillAll (juce::Colours::darkgrey);
g.setColour (juce::Colours::orange);

g.fillRect (10, 10, 40, 40);
}

ここでは、矩形の境界を直接Graphics::fillRect()関数を別々の整数として扱う:

g.fillRect (10,  // x
10, // y
40, // width
40); // height

これは簡単だが、もし境界をRectangleオブジェクトを使えば、矩形の操作がずっと簡単になる。

RectangleクラスとPointクラスの使用

これらの別々の座標、幅、高さの値をRectangleオブジェクトを作成します。[1]:

void paint (juce::Graphics& g) override
{
g.fillAll (juce::Colours::darkgrey);

juce::Rectangle area (10, 10, 40, 40); // [1]

g.setColour (juce::Colours::orange);
g.fillRect (area);
}

これは正方形を描画する方法としては非常によく似ているが、元のサイズを保ったまま、正方形をコンポーネント境界の周囲に移動させることが非常に簡単にできるようになった。これはRectangleクラスはテンプレート・クラスです。この例ではintテンプレート・パラメータを使用します。JUCEの描画コードでは、一般的に次のどちらかを使用します。Rectangle<int>またはRectangle<float>オブジェクトそのPointそしてLineクラスもテンプレート・クラスです。intまたはfloatテンプレート・パラメータ。

長方形を作る方法は他にもある。例えば、幅と高さを指定するのではなく、矩形の角として使いたい点が2つあるとする。この場合PointクラスとRectangleビルダー

void paint (juce::Graphics& g) override
{
g.fillAll (juce::Colours::darkgrey);
g.setColour (juce::Colours::orange);
juce::Rectangle area (juce::Point (10, 10),
juce::Point (50, 50));

g.fillRect (area);
}

このテクニックの素晴らしい点のひとつは、任意の2点を指定できることだ。これらの点は矩形の左上と右下の角を表す必要はない。従って、これに相当するものは次のようになる:

juce::Rectangle area (juce::Point (10, 50),
juce::Point (50, 10));

Point クラスと Path クラスの使用

実際、このようなPathオブジェクトの各コーナーを定義する4点を持つ矩形を指定することができる:

void paint (juce::Graphics& g) override
{
g.fillAll (juce::Colours::darkgrey);
g.setColour (juce::Colours::orange);

juce::Path path;
path.startNewSubPath (juce::Point (10, 10));
path.lineTo (juce::Point (50, 10));
path.lineTo (juce::Point (50, 50));
path.lineTo (juce::Point (10, 50));
path.closeSubPath();

g.fillPath (path);
}
注記

この場合Point<float>クラスはPathクラスを使う必要がある。しかし、Point<int>::toFloat()関数とPoint<float>::toInt()関数を使えば、2種類のポイントを変換することができる。

エクササイズ

パスのポイントを変えて、他の四角形形状を作ってみてください。

パスに直接矩形を追加することもできる:

void paint (juce::Graphics& g) override
{
g.fillAll (juce::Colours::darkgrey);
g.setColour (juce::Colours::orange);

juce::Path path;
juce::Rectangle area (10, 10, 40, 40);
path.addRectangle (area);

g.fillPath (path);
}
注記

を使うこともできた。Rectangle<int>この場合Pathクラスが代わりに浮動小数点数に変換してくれる。

矩形内の点のテスト

のもう1つの便利な機能である。Rectangleオブジェクトは、指定された点を含むかどうかをテストできる。これをテストするために、マウスをクリックするたびにコンポーネントが再描画されるようにする。これを行うには、次の関数を追加します:

    void mouseDown (const juce::MouseEvent&) override
{
repaint();
}

それではpaint()関数はランダムに矩形と点を生成する。そして、その矩形を描画し、さらにその点を囲むように小さな矩形を描画する。この小さな矩形は、ランダムに生成された点が大きな矩形内にあるかどうかによって、異なる色で描かれる。私たちのpaint()関数は前と同じように始めるべきだが、ランダムな値を生成するつもりなので、システムの参照をキャッシュしておこう。Randomのオブジェクトもある。

    void paint (juce::Graphics& g) override
{
g.fillAll (juce::Colours::darkgrey);
g.setColour (juce::Colours::orange);

auto& random = juce::Random::getSystemRandom();

次に、ランダムな長方形を作成します。以下のコードを追加する:

        juce::Range rectRange (20, getWidth() / 2);
juce::Rectangle rectArea (random.nextInt (rectRange),
random.nextInt (rectRange),
random.nextInt (rectRange),
random.nextInt (rectRange));

g.drawRect (rectArea, 2);

を使用して、各矩形要素のランダム値の範囲を制限する。Rangeオブジェクトを描画します。また、長方形を(塗りつぶしではなく)2ポイントの太さで描画する。小さい矩形を描くには、もう1つのRectangleオブジェクトを使用する。もしRectangleコンストラクタはRectangleオブジェクトを、指定された幅と高さ(この順)でゼロ(0, 0)の位置に置く。次の行を追加する:

        juce::Rectangle pointArea (10, 10);

では、ランダムに点を生成し、その中心をpointAreaその点に矩形を描く。次のコードを追加する:

        juce::Point point (random.nextInt (juce::Range (0, getWidth())),
random.nextInt (juce::Range (0, getHeight())));
pointArea.setCentre (point);

これはRectangleクラスの中心を位置づけることができるからだ。これは、矩形の位置を左上隅と考えるよりも好ましい場合がある。これでRectangle::contains()関数を使用してpointオブジェクトがrectAreaオブジェクトを追加します。次のコードを追加する:

        g.setColour (rectArea.contains (point) ? juce::Colours::limegreen
: juce::Colours::cornflowerblue);

g.fillRect (pointArea);

アプリケーションを実行すると、次のスクリーンショットのようになるはずです。コンポーネントを再描画するには、コンポーネントをクリックすることを忘れないでください:

矩形�内の点のテスト
矩形内の点のテスト
注記

この例のコードはPointLineRectangleTutorial_02.hファイルにある。

ラインの処理

線の描画と処理も同様に簡単だ。次のコードは対角線を描画する:

void paint (juce::Graphics& g) override
{
g.fillAll (juce::Colours::darkgrey);
g.setColour (juce::Colours::orange);

juce::Line line (juce::Point (10, 10),
juce::Point (50, 50));

g.drawLine (line, 2.0f);
}

ライン交差点

についてLineクラスは線の交差テストも行うことができる。これをテストするために、ランダムにいくつかの線を生成し、これらの線のいずれかが他の線と交差する点に円を描くことにする。まずpaint()関数の背景を指定して、乱数生成の準備をする:

    void paint (juce::Graphics& g) override
{
g.fillAll (juce::Colours::darkgrey);
g.setColour (juce::Colours::orange);

auto& random = juce::Random::getSystemRandom();

では、ランダムな線を生成し、描画するだけでなく、配列に格納してみよう。次のコードを追加する:

        juce::Range lineRange (0, getWidth());
juce::Array> lines;
auto numLines = 10;

for (auto i = 0; i < numLines; ++i)
{
juce::Line line ((float) random.nextInt (lineRange),
(float) random.nextInt (lineRange),
(float) random.nextInt (lineRange),
(float) random.nextInt (lineRange));

lines.add (line);
g.drawLine (line, 2.0f);
}

次に色を変え、円を描く境界となる正方形を用意する。これを加える:

        g.setColour (juce::Colours::palegreen);
juce::Rectangle pointArea (8, 8);

最後に、線の配列を繰り返し、他の線との交差をチェックする。Line::intersects()関数を使用する。次にpointAreaこの点に矩形を置き、円を描く。これを行うには、以下のコードを追加する:

        for (auto lineI : lines)
{
for (auto lineJ : lines)
{
if (lines.indexOf (lineI) != lines.indexOf (lineJ))
{
juce::Point intersection;

if (lineI.intersects (lineJ, intersection)) // [2]
{
pointArea.setCentre (intersection);
g.fillEllipse (pointArea);
}
}
}
}
}

交差点をチェックするコード[2]を呼び出す。Line::intersects()関数を使用します。これはtrueが実際に交差している場合は、交差している点を返す。intersectionという議論になる。

今すぐアプリケーションを実行してください。マウスのクリックに反応して再描画するコードを残しておけば、コンポーネントをクリックすることで新しい線のセットを生成することができます。

ライン交差点
ライン交差点
注記

この例のコードはPointLineRectangleTutorial_03.hファイルにある。

もしboolによって返される。Line::intersects()関数を使うか、あるいはLine::getIntersection()の代わりに、点が描かれることになる。だろうが交差する場合、それぞれの方向に無限の長さまで延長する必要がある。例えば、次のコードを見てほしい:

//..
if (lines.indexOf (lineI) != lines.indexOf (lineJ))
{
juce::Point intersection;
pointArea.setCentre (lineI.getIntersection (lineJ));
g.fillEllipse (pointArea);
}
//..

そうすると、以下のスクリーンショットのようなものが生成される:

終点から先の線の交点
終点から先の線の交点
エクササイズ

最後のfor()この例のコードのループは単純だが、理想的なものではない。問題は、各行を他のすべての行と照合していることだ。.このコードを、各行のペアを一度だけチェックするように書き直してください。を削除できるはずだ。if (lines.indexOf (lineI) != lines.indexOf (lineJ))ステートメントを書き直した。

長方形の操作

では、矩形の操作についてもう少し見てみよう。始める前に、ランダムな色を生成する簡単な関数を追加してみよう (Tutorial: The Random class以下の例ではこれを何度も行うことになる):

    static juce::Colour getRandomColour()
{
auto& random = juce::Random::getSystemRandom();

return juce::Colour ((juce::uint8) random.nextInt (256),
(juce::uint8) random.nextInt (256),
(juce::uint8) random.nextInt (256));
}

では、矩形を描画するコードをRectangleクラスでは、10個の正方形を対角線上に描き、ランダムに生成された色を使う:

void paint (juce::Graphics& g) override
{
g.fillAll (juce::Colours::darkgrey);

juce::Rectangle area (10, 10, 40, 40);

auto numSquares = 10;

for (auto i = 0; i < numSquares; ++i)
{
g.setColour (getRandomColour());
g.fillRect (area);

area.translate (30, 30); // [3]
}
}

についてRectangle::translate()機能[3]は、与えられた矩形を指定された水平方向と垂直方向のオフセットだけ移動させる。結果は次のスクリーンショットのようになるはずです:

正方形の対角線パターン
正方形の対角線パターン

ここではそのコードを拡張して、次の描画操作の前に矩形のサイズを変更する。これに加えて、平行移動は矩形の幅と高さに等しくなるように行われる。

void paint (juce::Graphics& g) override
{
g.fillAll (juce::Colours::darkgrey);

juce::Rectangle area (10, 10, 40, 40);

auto& random = juce::Random::getSystemRandom();
auto numSquares = 10;

for (auto i = 0; i < numSquares; ++i)
{
g.setColour (getRandomColour());
g.fillRect (area);

area.translate (area.getWidth(), area.getHeight()); // [4]
area.setSize (random.nextInt (juce::Range (20, 40)), // width
random.nextInt (juce::Range (20, 40))); // height
}
}

これにより、以下のスクリーンショットに示すように、矩形はその角で「結合」される:

角で結ばれた長方形
角で結ばれた長方形

の代わりにRectangle::translate()関数を使う代わりに、足し算を使って矩形に点を「追加」して平行移動させることができる。つまり[4]上記の行に次の行を加える:

area += juce::Point (area.getWidth(), area.getHeight());

長方形の交差点

重なり合う長方形がある場合、交差する面積はRectangle::getIntersection()関数を使用する。次の例では、直列の現在の矩形と次の矩形の間の交差矩形を計算する。これを明確にするために、直列の各矩形の輪郭を描き、交差する領域を塗りつぶされた矩形として描くことで強調する。

    void paint (juce::Graphics& g) override
{
g.fillAll (juce::Colours::darkgrey);

juce::Rectangle area (10, 10, 40, 40);

auto& random = juce::Random::getSystemRandom();
juce::Range rectRandomRange (20, 40);
auto numSquares = 10;

for (auto i = 0; i < numSquares; ++i)
{
auto nextArea = area + juce::Point (random.nextInt (rectRandomRange), // [5]
random.nextInt (rectRandomRange));

g.setColour (getRandomColour());
g.fillRect (area.getIntersection (nextArea)); // [6]

g.setColour (getRandomColour());
g.drawRect (area, 2); // [7]

area = nextArea;
}
}

を使用していることに注意してください。+演算子で矩形をオフセット[5].また、交差する領域を最初に埋めます。[6]矩形の輪郭を描く前に[7].これにより、最後に交差する領域は、最終的に対応する矩形なしで描画される。

長方形の交差点
長方形の交差点
注記

この最後の例のコードはPointLineRectangleTutorial_04.hファイルにある。

概要

このチュートリアルでは、テンプレート・クラスPoint,LineそしてRectangle.特に以下のテクニックを取り上げた:

  • 創造と操作Rectangleオブジェクトを作成し、それを描画コードで使用する。
  • 創造するRectangle角の点から、または2つの長方形の交点からオブジェクトを見つける。
  • 創造するPathオブジェクトは矩形を含む。
  • 創造するLineオブジェクトに線を引き、線が交差する点を見つける。

参照