きゃんブロ

きゃんなブログ

自作npm、square-dxf-checker完成までの道のり#3 四角形になる条件設定と面積の算出

こんにちは。
aya-kyanです。

「自作npm、square-dxf-checker完成までの道のり」というタイトルでDXFの図形を判断し、面積を計算するというnpmを作成した過程について書いています。
今回が3番目の記事で、最終回です。
前回の記事は下記からどうぞ。

aya-kyan.hatenablog.com

 

「次回は、長方形になる条件設定について書きます。」と書いてから、かなり時間が経ってしまいました。
次に書きたいネタが出てきたので、この話を早く終わらせなくてはいけないと思い再び書いています。(早く書きなさい。)

本題に入ります。

 

長方形になる条件

長方形になる条件はなんでしょうか。
これは小学校で習いましたね。
正解は、「4つの角が全て等しい」です。
この条件に、「4つの辺の長さが全て等しい」も加わると、正方形になります。
したがって、正方形は長方形の仲間です。

今回は、DXFの中から情報を取り出し、それが長方形であることを確認します。
そのためには、下記のことが分かれば良いでしょう。

  • 図形を構成する辺が4本ある
  • 4つの角が全て等しい(=4隅の角が90度である)

まず、辺が4本なければ、長方形は作れませんね。
辺は少なすぎても多すぎてもダメで、4本でなければ他の図形が描画されていると判断してよさそうです。
それに加えて、長方形の条件である4隅の角が90度であることを証明できればよさそうです。
4隅の角が90度であることが証明できれば、平行四辺形、台形である可能性はなくなります。

 

長方形であることを証明する手順

長方形になる条件がわかりました。
それでは、どのようにすればそれを証明できるでしょうか。
熟考した結果、下記のような手順で証明すればいいのではないかと考えました。

  1. 4本の線を、下記の2ペアに分ける
    1. 水平な線2本
    2. 垂直な線2本
  2. それぞれのペアの線同士が同じ長さであることを確認する
    1. 水平な線同士が同じ長さである
    2. 垂直な線同士が同じ長さである
  3.  それぞれのペアの線が平行であることを確認する
    1. 水平である2本の線が平行である
    2. 垂直である2本の線が平行である
  4. 始点、もしくは終点が同じ座標であることを確認する
    1. 水平な線の座標同士
    2. 垂直な線の座標同士
    3. 水平な線の座標と、垂直な線の座標同士

これだけ書いてもわからないと思うので、詳細に説明をしていきます。

線の長さ、水平/垂直、平行であるかは確認済み

前回の記事で説明した情報をもとに、すでに下記のことができています。

  • 水平/垂直な線ごとにペアで分ける
  • 線の長さの取得

これにより、先述した1~3の条件は確認済みです。
再度、ターミナル上で出力したものを下記に記載します。

【Side View】
Vertical line in side view:
 [
  {
    StartPoint: [ '324.126701', '199.219757' ],
    EndPoint: [ '324.126701', '99.219757' ]
  },
  {
    StartPoint: [ '334.126701', '199.219757' ],
    EndPoint: [ '334.126701', '99.219757' ]
  }
]
Length of first line: 100
Length of second line: 100
These lines are same length.

Horizontal line in side view:
 [
  {
    StartPoint: [ '324.126701', '99.219757' ],
    EndPoint: [ '334.126701', '99.219757' ]
  },
  {
    StartPoint: [ '324.126701', '199.219757' ],
    EndPoint: [ '334.126701', '199.219757' ]
  }
]
Length of first line: 10
Length of second line: 10
These lines are same length.

Thickness: 10 

【Front View】
Vertical line in front view:
 [
  {
    StartPoint: [ '293.924544', '199.219757' ],
    EndPoint: [ '293.924544', '99.219757' ]
  },
  {
    StartPoint: [ '93.924544', '99.219757' ],
    EndPoint: [ '93.924544', '199.219757' ]
  }
]
Length of first line: 100
Length of second line: 100
These lines are same length.

Horizontal line in front view:
 [
  {
    StartPoint: [ '93.924544', '199.219757' ],
    EndPoint: [ '293.924544', '199.219757' ]
  },
  {
    StartPoint: [ '293.924544', '99.219757' ],
    EndPoint: [ '93.924544', '99.219757' ]
  }
]
Length of first line: 200
Length of second line: 200
These lines are same length.

水平/垂直の判断基準について少し復習をすると下記のようになります。

辺Aの始点から終点の、x座標の差分が0、かつy座標には差分がある

→ 辺Aは垂直方向

辺Aの始点から終点の、y座標の差分が0、かつx座標には差分がある

→ 辺Aは水平方向

前回、上記のように判断し、それぞれのグループでペアを作っていました。
したがって、それぞれのペアに属している線同士は、平行であると言えます。
なぜなら、水平な線のペアであれば、どちらの線も水平なので平行であると言えます。

*斜めに描画されている四角形はどうするんだ!というツッコミが入りそうですが、今回は考えないことにします。

さらに、始点から終点の差分から線の長さも取得していました。
以上より、線の長さ、水平/垂直であること、平行であることは確認済みです。

始点、もしくは終点が同じ座標であることを確認

1~3の条件は確認済みとなりました。
あとは4の条件を確認するのみです。
まずは、なぜこれを確認する必要があるのかを見ていきましょう。

水平/垂直である線の座標同士を確認する理由

もし確認しなかった場合、下記の画像のように線の位置がずれる可能性が生まれます。

これでは四角形を形作ることはできません。

水平な線と、垂直な線のそれぞれの座標同士を確認する理由

もし確認しなかった場合、下記のように4本の線同士が重ならない可能性が生まれます。

水平、垂直であることは確認できても重ならないのであれば四角形にはなりません。

座標が一致するか確認

下記のようなロジックで実装してみました。

  1. 垂直線の全ての座標を取得し配列に入れる(仮にarray1とする)
  2. 水平線の全ての座標を取得し配列に入れる(仮にarray2とする)
  3. array1の重複を削除
  4. array2の重複も削除
  5. 四角形であれば点が4点残るはずなので、array1とarray2が等しいか確認し、trueであれば検証OK

ちなみに、JavaScriptでは == で配列同士を判定することができないようです。

array1 = [ '199.219757', '324.126701', '334.126701', '99.219757' ]
array2 = [ '199.219757', '324.126701', '334.126701', '99.219757' ]
array1 == array2 //false