La triangulation de la géométrie était autrefois une "chose".
Cela peut être fait si vous avez l'extension 3D Analyst, mais si vous ne l'avez pas et que vous devez connaître les principes et pouvez utiliser NumPy et python... c'est parti.
1 créer un tableau à partir de la géométrie (FeatureClassToNumPyArray est un bon début. J'ai déjà publié du code sur comment faire cela
2 la trianguler (j'utilise scipy)
3 obtenir le centroïde de chaque triangle. (encore une fois, j'ai publié du code pour cela.)
4 vérifier si les centroïdes sont à l'intérieur de la forme originale.
Pour compliquer cela, les polygones sont soit convexes soit concaves, avec ou sans trous et peuvent être composés de plusieurs parties. Parfois, il faut donc décomposer votre géométrie à sa forme la plus simple et parcourir chaque partie. Les formes convexes sont ennuyeuses, donc je vais les ignorer.
Voici 3 formes, C, D, A. C est une forme concave sans trous. D est convexe mais a un trou. A est concave et a un trou.
Leurs versions triangulées.
Et la triangulation contrainte. C’est-à-dire la triangulation avec les triangles qui ne sont pas dans l’enveloppe extérieure originale ou dans un trou.
On dirait que tout va bien.
Pour effectuer la triangulation, vous pouvez utiliser
from scipy.spatial import Delaunay
def triangulate_pnts(pnts):
"""Triangule les points et retourne les triangles.
Paramètres
----------
pnts : array
Points pour une forme ou un groupe de points au format tableau.
Soit geo.shapes soit np.ndarray.
out : array
Un tableau des points des triangles.
.. note::
Les simplesxes sont ordonnés dans le sens antihoraire, ce qui est inversé dans cette
implémentation.
"""
pnts = np.unique(pnts, axis=0) # ne garder que les points uniques
avg = np.mean(pnts, axis=0)
p = pnts - avg
tri = Delaunay(p)
simps = tri.simplices
# -- conteneur d'indices, remplir avec indices, répéter le premier et décaler vers la gauche
# traduire les points en arrière
z = np.zeros((len(simps), 4), dtype='int32')
z[:, :3] = simps
z[:, 3] = simps[:, 0]
tmp_ = p[z] + avg
new_pnts= []
for i in tmp_: # réordonner dans le sens horaire
if _bit_area_(i) < 0.0: # -- 2025_10_27
i = i[::-1]
new_pnts.append(i)
return new_pnts
def _bit_area_(a):
"""Mini e_area, utilisé par `areas` et `centroids`.
Les aires négatives sont des trous. Ceci est intentionnellement inversé par rapport à
la formule du `shoelace`.
"""
a = _base_(a)
x0, y1 = (a.T)[:, 1:] # configuration du produit croisé comme suit
x1, y0 = (a.T)[:, :-1]
e0 = np.einsum('...i,...i->...i', x0, y0) # modifié le 2024-03-28
e1 = np.einsum('...i,...i->...i', x1, y1)
return np.sum((e0 - e1) * 0.5)
def _area_centroid_(a):
r"""Calcule l'aire et le centroïde pour un polygone monopartite, `a`.
Ceci est aussi utilisé pour calculer l'aire et le centroïde des parties d'un tableau Geo.
Notes
-----
Pour les formes multipartites, utilisez simplement cette syntaxe :
>>> # rectangle avec trou
>>> a0 = np.array([[[0., 0.], [0., 10.], [10., 10.], [10., 0.], [0., 0.]],
[[2., 2.], [8., 2.], [8., 8.], [2., 8.], [2., 2.]]])
>>> [_area_centroid_(i) for i in a0]
>>> [(100.0, array([ 5.00, 5.00])), (-36.0, array([ 5.00, 5.00]))]
"""
a = _base_(a)
x0, y1 = (a.T)[:, 1:]
x1, y0 = (a.T)[:, :-1]
e0 = np.einsum('...i,...i->...i', x0, y0)
e1 = np.einsum('...i,...i->...i', x1, y1)
t = e1 - e0
area = np.sum((e0 - e1) * 0.5)
x_c = np.sum((x1 + x0) * t, axis=0) / (area * 6.0)
y_c = np.sum((y1 + y0) * t, axis=0) / (area * 6.0)
return area, np.asarray([-x_c, -y_c])
Voici C
C
array([[ 0.00, 0.00],
[ 0.00, 10.00],
[ 10.00, 10.00],
[ 10.00, 8.00],
[ 2.00, 8.00],
[ 2.00, 2.00],
[ 10.00, 2.00],
[ 10.00, 0.00],
[ 0.00, 0.00]])
Les centroïdes ainsi que les aires et triangulations peuvent être déterminés en utilisant ce qui précède.
'Tester quels triangles font partie de la géométrie originale implique d'utiliser une recherche points-dans-polygone.' J'ai fait cela il y a longtemps dans ma précédente incarnation.
'Point in Polygon ... Geometry Mysteries - Esri Community' (Point dans Polygone ... Mystères de Géométrie - Communauté Esri)
'Il utilise l'approche du nombre d'enroulement.' (winding number approach).
'Donc si vous avez besoin d'une triangulation de Delaunay contrainte pour vos objets géométriques... essayez-la.'
'Note :'
'Si vous voulez voir plus de choses en python, NumPy et ArcPy consultez mon site github.'
'Dan Patterson sur github'