Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

154
Vistas
Uso de D3 para recuperar un condado de EE. UU. TopoJSON a partir de coordenadas

Tengo un conjunto de coordenadas recuperadas como:

 navigator.geolocation.getCurrentPosition(function(position) { let coordinates: [number, number] = [position.coords.longitude, position.coords.latitude] } // eg [-70.1234567, 40.987654]

Quiero usar D3 para recuperar el condado correspondiente de un archivo TopoJSON de EE. UU. de la siguiente manera:

 getGeoLocation(topology, coordinates) { topojson.feature(topology, topology["objects"]["counties"])["features"].filter(function(polygon) { polygon["geometry"]["coordinates"].forEach(coord => { console.log(d3.polygonContains(coord, coordinates)) }) }) }

Sin embargo, hacer esto devuelve false para cada objeto del condado. No estoy seguro de si el mejor enfoque es usar d3.geoContains() o d3.polygonContains() , aunque en línea parece que puede haber algún problema relacionado con las características de MultiPolygon en TopoJSON (enlace aquí: https://cdn. jsdelivr.net/npm/us-atlas@3/counties-albers-10m.json ).

¿Cómo puedo resolver esto?

EDITAR

¿Quizás el problema es la falta de proyección en geoPath() que se usa en TopoJSON...? Aunque incluso si no lo proyecto y solo lo comparo con el JSON básico, el problema sigue siendo...

Algún contexto en el mapa (construido en Angular con TypeScript), donde this.topology es la importación JSON desde la URL especificada:

 path: any = d3.geoPath() this.svg = d3.select("#map") .attr("preserveAspectRatio", "xMidYMid meet") .attr("viewBox", "0 0 975 610") .attr("height", "100%") .attr("width", "100%") this.g = this.svg.append("g") .attr("id", "g") this.counties = this.g.append("g") .selectAll("path") .data(topojson.feature(this.topology, this.topology["objects"]["counties"])["features"]) .join("path") .attr("d", this.path) .attr("class", "county") .attr("id", function(d) {return d["id"]})
about 4 years ago · Juan Pablo Isaza
1 Respuestas
Responde la pregunta

0

d3.geoContains solo funciona en coordenadas esféricas (WGS84) que se especifican por longitud y latitud en grados. El TopoJSON que está utilizando proviene de esta fuente y ya se ha proyectado en un rango de píxeles mediante la proyección de Albers. Así que estos no funcionarán juntos.

La solución sería un método pathContains (hay un problema abierto al respecto). El método geoContains llama a polygonContains en una matriz de coordenadas modificada, porque los cálculos se realizan en la esfera. Solo necesitamos cálculos planos ya que las geometrías ya están proyectadas. Por supuesto, también debe proyectar las coordenadas del punto de entrada.

La implementación a continuación debería funcionar, pero ciertamente no evita todos los escollos que pueden ocurrir en general.

 const projection = d3.geoAlbersUsa().scale(1300).translate([487.5, 305]); const geo_path = d3.geoPath(); function pathContains(feature, point) { const coordinates = feature.geometry.coordinates; const n = coordinates.length; if (!!point) { for (let i = 0; i < n; i++) { if (d3.polygonContains(coordinates[i][0], point)) return true; } } return false; } d3.json("https://cdn.jsdelivr.net/npm/us-atlas@3/counties-albers-10m.json") .then(json => { const geo_shapes = topojson.feature(json, json.objects.states); function render() { const point = [ d3.select("#longitude").property("value"), d3.select("#latitude").property("value"), ] const projected = projection(point); d3.select("#map") .selectAll("path") .data(geo_shapes.features, d => d.id) .join("path") .attr("d", geo_path) .attr("class", "map-feature") .attr("fill", d => pathContains(d, projected) ? "red" : "white") .attr("stroke", "gray"); d3.select("circle") .raise() .attr("cx", !projected ? 0 : projected[0]) .attr("cy", !projected ? 0 : projected[1]) .attr("r", !projected ? 0 : 3); } d3.selectAll("input").on("input", render); d3.select("#map") .append("circle"); render(); });
 <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/7.3.0/d3.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/topojson/3.0.2/topojson.min.js"></script> <input type="number" multiple="0.1" id="longitude" value="-96.6"> <input type="number" multiple="0.1" id="latitude" value="38.6"> <svg id="map" viewBox="0 0 975 610"></svg>

about 4 years ago · Juan Pablo Isaza Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda