7
votes

D3: Trouver la zone d'un géo polygone dans D3

J'ai une carte qui utilise un fichier Geojson pour dessiner les pays. Je veux ensuite dessiner un cercle centré sur chaque pays. Mais pour les pays avec plusieurs régions de bordure (les États-Unis, le continent, Hawaii, l'Alaska), je veux le cercle sur la plus grande région de sélection. J'essaie de le faire en comparant les zones des différentes régions de sélection, mais cela ne marche pas pour des raisons pour des raisons que je ne comprends pas.

Voici un exemple de la Geojson, montrant comment l'Australie a plusieurs régions de sélection: xxx pré>

et voici le code où j'essaie de comparer les zones de différentes régions de sélection. Dans ce si code> instruction, j'essaie de comprendre si le pays a plus d'une région de liaison (qui semble fonctionner), puis dans le bloc pour code> bloc, choisissez Le plus grand. p>

Le problème: les valeurs "zone" que je reçoivent sont toutes 0 et coords code> est toujours choisi dans la première région de liaison, plutôt que le plus grand.

      var path = d3.geo.path().projection(projection)


12 commentaires

Qu'entendez-vous par «ne pas fonctionner»? Obtenez-vous des messages d'erreur?


Désolé, bonne question, je vais éditer mon message original. Ce qui ne fonctionne pas, c'est que la valeur que je reçois pour ces calculs de la région semble être nulle. Et les cercles sont tirés sur la première région de liaison, peu importe quoi.


Pouvez-vous nous montrer la définition de chemin aussi s'il vous plaît?


Oui, mettra à jour maintenant.


Le fichier complet est ici: Github.com/acprice/flights/blob/ Master / Vols / Vols.html


Selon la documentation, vous devez transmettre une fonctionnalité complète sur chemin.area , c'est-à-dire une liste de coordonnées. Est-ce que ça marche si vous passez un pays entier?


Je vais essayer ça. Mais je pensais que Path.Area pourrait aussi prendre juste un polygone ou un multiolygone.


Vous pouvez essayer de construire un polygone à l'aide d'un sous-ensemble des coordonnées.


Ok, à droite. Donc, c'est que je dois analyser chaque tableau dans les coordonnées au format Point? Ou êtes-vous connu de manière plus facile? (Merci pour l'aide, en passant)


Il peut être plus facile d'extraire le sous-ensemble de coordonnées que vous souhaitez et de les mettre dans un objet qui ressemble à l'original (c'est-à-dire un nombre droit de coordonnées imbriquées, attribut "Type").


Hey @larskotthoff c'est exactement juste. Il m'a fallu un moment pour obtenir un objet qui "regarde" comme l'original, mais j'ai fait à la fin. Merci de votre aide.


Ok, je vais ajouter cela comme une réponse pour la référence future.


3 Réponses :


1
votes

La fonction .area s'attend à une fonctionnalité et ne fonctionne pas avec une liste de coordonnées. Le moyen le plus simple de faire fonctionner est probablement de copier l'objet d'origine, supprimez toutes les coordonnées que vous n'êtes pas intéressé et transmettez-la sur PATH.AREA . Le code ressemblerait à quelque chose comme xxx


1 commentaires

Hey, merci. J'ai mis en œuvre une solution légèrement plus explicite la nuit dernière. Je viens de l'ajouter comme une autre réponse. Votre approche peut être un peu plus rationalisée.



4
votes

Juste parce que personne n'a ajouté une réponse pleinement mise en œuvre, j'ai décidé de répondre à ma propre question. Voici le code qui prend Geojson, comme spécifié dans la question initiale et renvoie les coordonnées de la plus grande région de sélection pour les pays avec plus d'une région de sélection. Pour les pays dotés d'une seule région de sélection, il renvoie les coordonnées de la seule région de sélection. (Je devais modifier le code un peu pour en faire une méthode autonome ici, mais je suis sûr que c'est sans erreur.)

function getLargestBoundingRegion(country) {

var largestRegionCoords;
var path = d3.geo.path()

//Check if the country has more than one bounding region.
if (country.geometry.coordinates.length > 1) {

    var regionToReturn = {        
        "type": "Feature",
        "geometry": {
            "type": "Polygon", 
            "coordinates": country.geometry.coordinates[0]},            
        };

    for (var i=1; i<country.geometry.coordinates.length; i++) {

        var testRegion = {        
                    "type": "Feature",
                "geometry": {
                    "type": "Polygon", 
                    "coordinates": country.geometry.coordinates[i]},            
            };

        if (path.area(testRegion) > path.area(regionToReturn)) {
            regionToReturn = testRegion;    
            largestRegionCoords = country.geometry.coordinates[i][0];    
            }
        }

    } else {    
        largestRegionCoords = country.geometry.coordinates[0];
    }

return largestRegionCoords;


0 commentaires

9
votes

Vous pouvez calculer la zone d'un polygone arbitraire à l'aide du algorithme de shoelace .

function polygonArea(points) {
  var sum = 0.0;
  var length = points.length;
  if (length < 3) {
    return sum;
  }
  points.forEach(function(d1, i1) {
    i2 = (i1 + 1) % length;
    d2 = points[i2];
    sum += (d2[1] * d1[0]) - (d1[1] * d2[0]);
  });
  return sum / 2;
}

polygonArea([[0,0], [4,0], [4,3]]);  // 6


1 commentaires

@Paulvidal, les mêmes unités que les coordonnées du point utilisé comme entrée.