Tengo un mapa básico aquí, con datos ficticios. Básicamente un mapa de burbujas.
El problema es que tengo varios puntos (por ejemplo, 20) con exactamente las mismas coordenadas de GPS. La siguiente imagen es mi csv con datos ficticios, el color azul resalta los puntos superpuestos en este ejemplo básico. Eso es porque muchas empresas tienen las mismas coordenadas gps de la ciudad.

Aquí hay un violín con el código en el que estoy trabajando:
https://jsfiddle.net/MathiasLauber/bckg8es4/45/ Muchas investigaciones posteriores, descubrí que d3.js agrega esta función de simulación de fuerza, que evita que los puntos colisionen.
// Avoiding bubbles overlapping var simulationforce = d3.forceSimulation(data) .force('x', d3.forceX().x(d => xScale(d.longitude))) .force('y', d3.forceY().y(d => yScale(d.latitude))) .force('collide', d3.forceCollide().radius(function(d) { return d.radius + 10 })) simulationforce .nodes(cities) .on("tick", function(d){ node .attr("cx", function(d) { return projection.latLngToLayerPoint([d.latitude, d.longitude]).x; }) .attr("cy", function(d) {return projection.latLngToLayerPoint([d.latitude, d.longitude]).y; }) });El problema es que no puedo hacer que el diseño de fuerza funcione y mis puntos todavía están uno encima del otro. (líneas: 188-200 en el violín) .
Si tiene algún consejo, sugerencia o si nota errores básicos en mi código, hágamelo saber =D
Montón de código cercano a lo que estoy tratando de lograr
https://d3-graph-gallery.com/graph/circularpacking_group.html
https://jsbin.com/taqewaw/edit?html,salida
Hay 3 problemas:
x e y deben especificarse en los datos pasados a la llamada de simulation.nodes() .node en la función de devolución de llamada on('tick') ).dx y dy anteriores calculados por la simulaciónFragmentos de código relevantes a continuación
// 1. Add x and y (cx, cy) to each row (circle) in data const citiesWithCenter = cities.map(c => ({ ...c, x: projection.latLngToLayerPoint([c.latitude, c.longitude]).x, y: projection.latLngToLayerPoint([c.latitude, c.longitude]).y, })) // citiesWithCenter will be passed to selectAll('circle').data() // 2. node selection you forgot const node = selection .selectAll('circle') .data(citiesWithcenter) .enter() .append('circle') ... // let used in simulation simulationforce.nodes(citiesWithcenter).on('tick', function (d) { node .attr('cx', function (d) { // 3. use previously computed x value // on the first tick run, the values in citiesWithCenter is used return dx }) .attr('cy', function (d) { // 3. use previously computed y value // on the first tick run, the values in citiesWithCenter is used return dy }) })Demostración completa de trabajo aquí: https://jsfiddle.net/b2Lhfuw5/