点がパス上にあるか否かを表す真偽値オブジェクト
点が領域内にあるか否かを表す真偽値オブジェクトは、
IsInRegion[ <点>, <領域> ]
で作成できる。
これに対して、点がパス内にあるか否かを表す真偽値オブジェクトは、どうすれば作成できるだろうか。これを作成するためのコマンドは用意されていないので、他のコマンドの組み合せで作れるかを試みた。
ClosestPoint[ <パス>, <点> ]
は、指定した点に最も近いパス上の点を返すコマンドである。これを用いて、
<点P> ≟ ClosestPoint[ <パス>, <点P> ]
とすれば、目的の真偽値オブジェクトを作成できる。
応用例:凸包の頂点をリストで返す
任意の点を要素とするリストオブジェクトを作成し、名前を list1 とする。
list1の凸包は、
ConvexHull[ list1 ]
で作成できる。これは軌跡オブジェクトである。軌跡オブジェクトは、パスの一種である*1。
list1の要素である点のうち、list1の凸包の頂点のみを抽出して、リストとして得るには、以下のようにすればよい(これによって得られるリストの名前を、仮にconvexListとする)。
RemoveUndefined[Zip[If[t ≟ ClosestPoint[ConvexHull[list1], t], t, ?], t, list1]]
list1の各要素である点について、その点が凸包ConvexHull[ list1 ]上にあるならば、その点自身を返し、そうでなければ未定義オブジェクト「?」を返す、という作業を行い、結果をリストで得る。そして、RemoveUndefined コマンドで、未定義オブジェクト「?」を除去している。
凸包を多角形オブジェクトとして返す
上記で求めた convexList を用いて、
Polygon[ convexList ]
としても、必ずしも凸多角形を得られるとは限らない。これは、convexList 内の要素である点が、必ずしも凸多角形を与えるような順序で並んでいるとは限らないことが原因である。
convexListの要素を、凸多角形を与えるような順序に並び替えるには、パスパラメータ*2をキーとして、Sort コマンドを実行すればよい。
convexListの要素のパスパラメータを、リストとして得るには、以下のようにすればよい(これによって得られるリストの名前を、仮にpathListとする)*3。
RemoveUndefined[Zip[If[t ≟ ClosestPoint[ConvexHull[list1], t], PathParameter[ClosestPoint[ConvexHull[list1], t]], ?], t, list1]]
そして、
Polygon[Sort[convexList, pathList]]
によって、目的の凸多角形を得ることができる。
オリジナルツール「ConvexPolygon」
上記の結果を利用して、点のリストを引数として、その凸包を多角形オブジェクトで返すオリジナルツールを作成した。
*1:パスの定義は、
https://wiki.geogebra.org/en/Geometric_Objects#Paths
を参照。
*2:パスパラメータの定義は、
https://wiki.geogebra.org/en/PathParameter_Command
を参照。
*3:なお、convexListを用いて、
Zip[PathParameter[a],a,convexList]
とする方法でも良さそうだが、実際に試したところ、「?」からなるリストが返され、使えなかった。
多角形オブジェクトを用いて、頂点または辺のリストを返す
多角形の名前を poly1 とする。
poly1の頂点のリストは、
{Vertex[poly1]}
と表せる。
また、poly1の辺のリストは、
Sequence[Segment[Element[{Vertex[poly1]}, t], Element[{Vertex[poly1]}, If[t ≠ Length[{Vertex[poly1]}], t + 1, 1]]], t, 1, Length[{Vertex[poly1]}]]
と表せる。
なお、poly1の辺のリストは、以下のように表すこともできる。長いが、Ifを使わず、FirstコマンドやJoinコマンドを使っている点が特徴的である。
Sequence[Segment[Element[Join[{{Vertex[poly1]}, First[{Vertex[poly1]}]}], t], Element[Join[{{Vertex[poly1]}, First[{Vertex[poly1]}]}], t + 1]], t, 1, Length[{Vertex[poly1]}]]
さらに、poly1の辺を、1つの折れ線オブジェクトとして表すことも可能である。
PolyLine[Join[{{Vertex[poly1]}, First[{Vertex[poly1]}]}]]
辺のリストを返す数式は、上記のように長く煩雑であるため、実用性を考えて、オリジナルツールにした。
オリジナルツール「Sides」
任意の多角形における全頂点の集合の凸包を多角形オブジェクトで返す
GeoGebraでは、任意の多角形オブジェクト(名前をpoly1とする)における全頂点の集合
{Vertex[poly1]}
の凸包は、
ConvexHull[{Vertex[poly1]}]
で得ることができる。
しかし、この方法で得られる凸包は、軌跡オブジェクトであり、多角形オブジェクトではない。
これに対して、以下の数式を、入力バーに入力して実行すれば、{Vertex[poly1]}の凸包を、多角形オブジェクトとして得ることができる。
Polygon[CopyFreeObject[Sequence[Point[ConvexHull[{Vertex[poly1]}], t / (Length[RemoveUndefined[Sequence[Intersect[ConvexHull[{Vertex[poly1]}], Element[{Vertex[poly1]}, t]], t, 1, Length[{Vertex[poly1]}]]]] + 1)], t, 0, Length[RemoveUndefined[Sequence[Intersect[ConvexHull[{Vertex[poly1]}], Element[{Vertex[poly1]}, t]], t, 1, Length[{Vertex[poly1]}]]]]]]]
利用例
追記
本記事執筆後に、よりよい方法を思いついた。下記記事を参照されたい。