重心をポリゴンに割り当てて移動する


9

QGIS 1.8 Lisboaを使用しています。ポリゴンシェープファイルから重心を計算した後、それらの一部がポリゴンアウトラインの外側にある場合、それらを元のポリゴン上に移動したいと思います。基準は、ポリゴン自体の識別コードとして使用する座標を抽出するために使用する必要があるため、一義的でなければなりません。したがって、プロシージャは、同じポリゴンに対して実行されるたびに同じポイントの位置を出力する必要があります(「ランダムポイント」関数で指定されるようなランダムな位置ではなく、実行されるたびに新しい結果が得られます)。


1
2つの質問のように聞こえます。私が正しく理解している場合、(a)ポリゴン内にランダムなポイントを追加し、(b)それらまたはポリゴンに、これに基づいて一意のIDを与える必要があります。(a)で頭に浮かぶ最も簡単なことは、QGISの既存のランダムポイント機能を使用して、そのポイントクラウドとポリゴンを交差させることです。
lynxlynxlynx 2013

「ランダムポイント」関数を同じポリゴンで異なる時間に使用すると、結果が異なります(つまり、各ポリゴンから派生したポイントの位置は、関数を新しく使用するたびに異なります)。ポリゴン自体の識別コードとして使用したい座標を抽出できる、ポリゴンごとの常に同じポイント。
umbe1987 2013

ジオメトリツールの下fTools「真重心」ツールを使用する- docs.qgis.org/html/en/docs/user_manual/plugins/...
Mapperz

それは私に重心を与えるだけですが、これは私が避ける必要があるポリゴンの外側にある可能性もあります。最小距離のような関数を使用して、派生元のポリゴン上でそれらを移動する必要があります(ただし、距離に興味はありません。移動させたいです)。別のブログで、誰かがPostGISのST_PointOnSurfaceを使うように言われました(しかし、私はQGISを使っています)。
umbe1987 2013

回答:


7

Shapely pythonライブラリを使用できます。これはrepresentative_point()、ポリゴン内にあることが保証されている関数を提供します。

以下は、QGIS Pythonコンソールで実行できるPythonスクリプトです。属性を作成するポリゴンレイヤーを選択する必要があります。この関数は、更新する属性の名前を取ります。属性はレイヤーにすでに存在している必要があり、文字列タイプである必要があり、十分な長さ(30文字)である必要があります。

アルゴリズムが見つけたポイントの例を次に示します。

import shapely.wkb

def setIDPoint(attributename):
 layer = qgis.utils.iface.activeLayer()
 provider = layer.dataProvider()
 fields = provider.fields()
 provider.select(provider.attributeIndexes() )
 attributeID = provider.fieldNameIndex(attributename)
 feature = QgsFeature()
 layer.startEditing()
 while provider.nextFeature(feature):
  wkb = feature.geometry().asWkb()
  polygon = shapely.wkb.loads(wkb)
  reprPoint = ','.join([str(polygon.representative_point().x), str(polygon.representative_point().y)] )
  feature.changeAttribute(attributeID, reprPoint)
  layer.updateFeature(feature)
 layer.commitChanges()

私はそれをテストしようとしています、まさに私が探していたもののようです。実行したらすぐにお知らせします!
umbe1987 2013

私がそれについて理解しなかったことの1つは、「文字列型である必要があり、十分な長さ(30文字)である必要がある」とはどういう意味ですか。このライブラリは、ポリゴンshpfileで直接動作していますか?もしそうなら、私は少なくとも30文字でAttタブに新しい文字列型フィールドを作成することになっています、そしてこれは更新されるものでしょうか?
umbe1987 2013

@ user9518:はい、現時点で関数を作成する方法です。自分でテーブルに属性を作成し、フィールドの名前のみを関数に渡す必要があります。スクリプトが必要な場合は、必要なフィールド自体を作成するようにスクリプトを簡単に変更することもできます。
ジェイク

ひとつだけ欠けています。「def」と入力して関数(またはクラス)を定義しているようですが、スクリプトの作成を終了しても何も起こりません。どうすれば最終的に結果をテーブルに入れることができますか?
umbe1987 2013

1
それは完全に機能しました!!! レイヤーの座標系に基づいて座標が記述されていると思いますが、ポイントが必要な場合は、それらの座標でshpを作成する必要があります。あなたがここにいたら、少なくとも3つのビールを提供します。あなたの努力を本当にありがとう!!!
umbe1987

5

ftools centroidツールは、凹型の場合、図心をポリゴンの外側に配置できます。

ST_PointOnSurface間違いなくあなたがしたいことをします。SPITを使用してシェイプファイルをPostGISにインストールし、PgQueryプラグインを使用してクエリを実行している場合は、QGIS内からコマンドを使用できます。

あるいは、PostGISのインストールが1回限りの使用に少しかかる場合は、QGIS内からSpatialiteを使用できます。次に、QSpatiaLiteプラグインを使用してデータをSpatiaLiteにインポートし、クエリを実行できます(SpatialLiteの栄誉ST_PointOnSurface)。


2

私があなたを正しく理解している場合は、Vector-> Research Tools_> Random Pointsを使用します。次に、「層別サンプリングデザイン(個々のポリゴン)」の下で選択し、入力フィールドの値を使用し、適切なフィールドを使用して、異なるポリゴンごとに生成されるポイントの数値を提供します。


「適切なフィールド」とはどういう意味ですか?重心を使用して、それが参照するポリゴンの最も近い部分にリンクすることを考えていました。たとえば、それがアウトラインの外側にある場合は、そのポイントから最も近いポリゴンまでの最小距離を計算することによって。目的は、そのポイント座標を抽出して、ポリゴンの一意の固有識別コードとして使用することです。
umbe1987 2013

基本的に私がやろうとしていることは、各重心をその相対ポリゴンに割り当て、それをそのポリゴンの内側に配置する(または少なくとも境界線に触れる)ことです。
umbe1987

@ user9518:すみません、あなたの質問を誤解しました。各ポリゴン内に特定の数のランダムポイントが必要だと思いました。たとえば、ポリ1に2ポイント、ポリ2に10ポイントなど、「適切なフィールド」という用語を使用します。もちろん、「この数のポイントを使用」に1を選択して、ポリゴンごとに1つのポイントのみを生成することもできます。このポイントはポリゴンの内側にあるか、少なくとも境界線に接触しています。しかし、このポイントはランダムごとに見つかります。そのため、手順をやり直すと、他のポイントが得られます:-(
カート

1

Realcentroidsプラグインは、プラグインからインストールできます>プラグインの管理とインストールはQGIS 2.2で私のために機能して、重心のようなポイントを生成しました。カートから提案されたランダムポイントツールを試しましたが、ポリゴンごとに1ポイントを指定しましたが、代わりに2ポイントが生成されました。さらに不利な点は、ほとんどの場合、ポイントはランダムであるため、重心を表していないことです。

http://www.agt.bme.hu/gis/qgis/realcentroid/

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.