Diseño y distribución en plantaGestión de almacenesLocalización de instalaciones

Método de localización de instalaciones utilizando mapas de calor (Google Maps + Javascript)

Google Maps (Javascript)

Mucho se ha desarrollado en la literatura académica acerca de los métodos o algoritmos de localización de instalaciones. En el estudio de localización se pueden abordar dos grandes aspectos: macrolocalización y microlocalización. En ambos casos el procedimiento de análisis de localización abordará las fases de:

  • Análisis preliminar
  • Búsqueda de alternativas de localización
  • Evaluación de alternativas
  • Selección de localización
Macrolocalización: Es decir, la selección de la región o zona más adecuada, evaluando las regiones que preliminarmente presenten ciertos atractivos para la industria que se trate.

Microlocalización: Es decir, la selección específica del sitio o terreno que se encuentra en la región que ha sido evaluada como la más conveniente.

Algunos de los algoritmos que apoyan las fases del procedimiento de localización, presentan dificultades propias del contexto operacional real que se pretende abordar. Por ejemplo, el Método de Centro de Gravedad, requiere de la consideración de un conjunto de instalaciones existentes, y su objetivo es el de establecer la ubicación de un punto de servicio / atención / suministro para los puntos dados. Requiere para ello de la existencia de un sistema de coordenadas con un punto de origen.

Recuerdo que cuando utilicé este algoritmo en la Universidad utilizamos la copia de un mapa de la región, sobre ella trazamos un plano cartesiano, definimos las ubicaciones del caso, registramos las coordenadas y como resultado obtuvimos las coordenadas de la localización ideal. La dificultad subyace en la falta de practicidad.

Otro método, como el Heurístico de Ardalan, utiliza un conjunto de instalaciones existentes, y un conjunto de localizaciones tentativas. Toma como base una matriz de distancias y el objetivo consiste en optimizar la cobertura. Sin embargo, obtener la información requiere del levantamiento de mínimo una matriz n * m. En la medida en la que el número de ubicaciones aumenta el algoritmo se convierte en complejo.


Desde hace algunos años, la disponibilidad de servidores de aplicaciones de mapas, los sistemas de posicionamiento satelital, los sistemas de información geográfica, entre otros; han facilitado la adopción de soluciones basadas en entornos reales, como herramientas que apoyen algunas de las fases del procedimiento de localización de ubicaciones.

En este artículo utilizaremos mapas de calor y servidores de aplicaciones de mapas, como herramienta visual de soporte en los procesos de selección de localizaciones.

¿Qué es un mapa de calor?

mapa de calorEn este contexto, un mapa de calor es una capa de visualización que se utiliza para representar la intensidad de los datos en puntos geográficos (ubicaciones). Cuando la capa de mapa de calor se encuentra habilitada, aparecerá una superposición de color en la parte superior del mapa. De forma predeterminada (es un estándar), las áreas de mayor intensidad se colorearán en rojo y las áreas de menor intensidad aparecerán en verde.

La intensidad de los datos de una región en particular puede aumentar dada la concentración de ubicaciones en una zona específica. Del mismo modo, pueden utilizarse puntos de datos ponderados, es decir, que un punto geográfico en particular puede tener un peso que hará que el punto se represente con mayor intensidad.

Un ejemplo de aplicación práctica de los puntos de datos ponderados, puede ser la cantidad de individuos que vivan en un punto específico. En este caso, los puntos ponderados ayudarán a representar densidad poblacional.


Mapas de calor + Google Maps

El servidor de aplicaciones de mapas más popular del mundo: Google Maps, cuenta con una librería de visualización que nos permite el uso de mapas de calor con puntos normales o ponderados. Evaluaremos su uso por medio de un caso práctico.

El Departamento de Desarrollo Sostenible de la ciudad de Cali se encuentra implementando una estrategia piloto de recolección de aceite de cocina usado. Ha articulado este proyecto con una Universidad, la cual desarrolló 4 contenedores inteligentes (BIN’s) para la disposición del bioresiduo. En investigaciones asociadas, la Universidad ha determinado que el reciclaje del aceite es un problema de densidad; esto quiere decir que es vital la ubicación de los contenedores (cobertura), para así mismo optimizar el proceso de disposición y recolección. El proyecto piloto piensa articular a las instituciones de educación como puntos potenciales de recolección. Por medio de las instituciones piensan socializar el programa con la comunidad. El primer reto del proyecto consiste en determinar la ubicación de los contenedores inteligentes (4 unidades). La información relacionada con las instituciones de educación que hacen parte del programa (ubicación geográfica / población estudiantil), se detalla a continuación:

 

EstablecimientoLatitud / LongitudNúmero de estudiantes
 Comfandi San Nicolás3.4535911182,  -76.5225488581494
 Mayor de Santiago de Cali3.4515777580,  -76.510232156908
 Municipal Comfandi3.4481079145, -76.510747140697
 Internado San Carlos3.4469941349, -76.5152532501714
 León de Greiff3.4479794015, -76.4999324741731
 Nuestra Señora de la Anunciación3.4451521118, -76.4964134162297
 Fernando de Aragón3.4373556029, -76.5138370441265
 Casa Evangélica3.4379553366, -76.5229994701658
 San Alberto Magno3.4330289411, -76.527076427604
 Santa María Goretty3.4334144860, -76.507206624416
 San Alberto Magno3.4331574561,  -76.5267331041584
 San Ignacio de Loyola3.4317866287,  -76.5173346442350
 Nuestro Futuro3.4306299916, -76.503601735964
 Sabio Caldas3.4290878065, -76.516605083329
 CREAD3.4250609784, -76.514888470774
 Licomtec3.4166645586, -76.5167338291818
  Nuestra Señora De La Providencia3.4195347715,  -76.4959198891530
 Real Suizo3.4152080294, -76.4932376802106
 Nuevo Edén3.4157220988, -76.533835594330
 Católico3.4130660706, -76.539843742976
 Santa María Stella3.4270315559,  -76.5513450541975
 Santa Isabel3.4080535495,  -76.508172225936
 Compartir3.4319576632,  -76.4749557521563
 Lancaster3.4007708157,  -76.5517742131219
 Parroquial Divino Salvador3.3970865884, -76.5425903281954
 Reyes Católicos3.3933166668,  -76.537354656399
 Liceo Anglo del Valle3.3873187189,  -76.5197593741741
 Laurence3.3834202377, -76.5207893431111
 Los Almendros3.3812782083,  -76.5202314431826
 Bautista3.3772083395,  -76.5232784321772
 Lacordaire3.3781508370,  -76.5446073571965
 General José María Córdoba3.3935733137, -76.549328047841
 El Hogar3.3907458636,  -76.550315100770
 Americano3.3790932549, -76.546881873650
 Santa Filomena3.4019699352, -76.5134508211401
 Tomás Vasconi3.4030409276, -76.5173132021474
 República del Salvador3.4044546356, -76.5214330751926
 Los Andes3.4296010767,  -76.5376121601566
Villacolombia3.4454939428, -76.5016920202354
Las Américas3.4492208216, -76.5059406382043
Santa Fe3.4422382667, -76.5098888502333
Evaristo García3.4407817764, -76.517527780696
Alfredo Vásquez Cobo3.4355983661,  -76.5164548981073
Ciudad de Cali3.4311431813,  -76.5127212631275
INEM3.4827619907, -76.49976083031485
Olaya Herrera3.4781785185, -76.5128070931470
Guillermo Valencia3.4744945902,  -76.5136654001248
José Ignacio Rengifo3.4716245430, -76.5136654002160
Santo Tomás3.4583022697,  -76.5164548981776
La Merced3.4627144903, -76.502464496706
Pedro Antonio Molina3.4828048267, -76.4876157892369
Santa Librada3.4622861203, -76.5230209452498
República de Israel3.4636569037, -76.5105325801510
San Vicente Paul3.4662271172, -76.5095026122330
Manuel María Mallarino3.4567601292, -76.4885170101464
Sebastián de Belalcázar3.4602299411,  -76.485212529628
Liceo Departamental3.4238604624,  -76.538556302364
Libardo Madrid3.4220611537,  -76.5438348902439
Metropolitano Santa Anita3.4016910381, -76.5421826511815
San José3.3969358164,  -76.5503151082230

De acuerdo a la información disponible, es posible utilizar un mapa de calor como herramienta de análisis preliminar y búsqueda de alternativas de localización. Veamos.

Agregar una capa de mapa de calor

La API de Google Maps puede utilizarse de la misma manera en la que un sitio web incorpora un mapa tradicional a su plataforma (Javascript). También pueden utilizarse plataformas externas para su visualización como JSFiddle.

Lo primero que haremos es configurar el mapa sobre el cual se ubicarán los puntos:

let map, heatmap;

function initMap() {
  map = new google.maps.Map(document.getElementById("map"), {
    zoom: 13,
    center: { lat: 3.43, lng: -76.51 },
    mapTypeId: "satellite",
  });
  heatmap = new google.maps.visualization.HeatmapLayer({
    data: getPoints(),
    map: map,
  });
  document
    .getElementById("toggle-heatmap")
    .addEventListener("click", toggleHeatmap);
  document
    .getElementById("change-gradient")
    .addEventListener("click", changeGradient);
  document
    .getElementById("change-opacity")
    .addEventListener("click", changeOpacity);
  document
    .getElementById("change-radius")
    .addEventListener("click", changeRadius);
}

zoom: Indicará el nivel de cercanía inicial del mapa de acuerdo a su centro. De igual forma, como usuarios podemos utilizar los controles para acercar o alejar una vez tengamos la visualización.

center: Indicará las coordenadas centrales del mapa (latitud y longitud). En nuestro ejemplo hemos adicionado las coordenadas de la ciudad de Cali (lat: 3.43, lng: -76.51).

mapTypeId: Tipo de mapa a utilizar. Podemos elegir un mapa tipo relieve o un mapa satelital (satellite).

En este mapa utilizaremos algunas funciones que nos permitirán cambiar algunos atributos de visualización: degradado, opacidad, radio de calor. 

gradient: Corresponde al degradado de color del mapa de calor, de manera predeterminada degradará desde el rojo (máxima intensidad) hacia el verde. Sin embargo, usted puede configurar la matriz de colores del degradado. En nuestro ejemplo, permitiremos que el usuario haga un cambio en la configuración del degradado con un clic.

opacity: La opacidad corresponde a la transparencia de la capa del mapa de calor, expresada como un número entre 0 y 1. En nuestro ejemplo, permitiremos que el usuario haga un cambio en la configuración de la opacidad con un clic.

radius: Corresponde al radio de influencia de cada punto de datos, en píxeles. Este es uno de los atributos más importantes del mapa de calor, ya que a partir de su valor podremos visualizar mejor o no, la data correspondiente. En nuestro ejemplo, permitiremos que el usuario haga un cambio en la configuración del radio con un clic.

Cambio de atributos

Las siguientes líneas permitirán cambiar los atributos ya mencionados con un solo clic. A continuación se establecen los valores opcionales de cada atributo.

function toggleHeatmap() {
  heatmap.setMap(heatmap.getMap() ? null : map);
}

function changeGradient() {
  const gradient = [
    "rgba(0, 255, 255, 0)",
    "rgba(0, 255, 255, 1)",
    "rgba(0, 191, 255, 1)",
    "rgba(0, 127, 255, 1)",
    "rgba(0, 63, 255, 1)",
    "rgba(0, 0, 255, 1)",
    "rgba(0, 0, 223, 1)",
    "rgba(0, 0, 191, 1)",
    "rgba(0, 0, 159, 1)",
    "rgba(0, 0, 127, 1)",
    "rgba(63, 0, 91, 1)",
    "rgba(127, 0, 63, 1)",
    "rgba(191, 0, 31, 1)",
    "rgba(255, 0, 0, 1)",
  ];
  heatmap.set("gradient", heatmap.get("gradient") ? null : gradient);
}

function changeRadius() {
  heatmap.set("radius", heatmap.get("radius") ? null : 20);
}

function changeOpacity() {
  heatmap.set("opacity", heatmap.get("opacity") ? null : 5);
}

Data de entrada: Ubicaciones

A continuación se ingresarán las 50 ubicaciones de nuestro caso de ejemplo. Utilizaremos puntos ponderados, con coordenadas de latitud y longitud, y un peso determinado por la población estudiantil de cada punto.

function getPoints() {
  return [
    {location: new google.maps.LatLng(3.453591118286918, -76.52254885881977), weight: 1494},
    {location: new google.maps.LatLng(3.451577758085148, -76.51023215602375), weight: 908},
    {location: new google.maps.LatLng(3.4481079145332427, -76.51074714011278), weight: 697},
    {location: new google.maps.LatLng(3.4469941349057063, -76.51525325089182), weight: 1714},
    {location: new google.maps.LatLng(3.4479794015658674, -76.49993247424311), weight: 1731},
    {location: new google.maps.LatLng(3.4451521118907227, -76.49641341630138), weight: 2297},
    {location: new google.maps.LatLng(3.4373556029276764, -76.51383704461735), weight: 1265},
    {location: new google.maps.LatLng(3.4379553366684252, -76.52299947000571), weight: 1658},
    {location: new google.maps.LatLng(3.4330289411959662, -76.52707642704613), weight: 604},
    {location: new google.maps.LatLng(3.4334144860421287, -76.50720662416609), weight: 416},
    {location: new google.maps.LatLng(3.433157456127054, -76.52673310420856), weight: 1584},
    {location: new google.maps.LatLng(3.431786628745183, -76.51733464458373), weight: 2350},
    {location: new google.maps.LatLng(3.4306299916118603, -76.50360173554287), weight: 964},
    {location: new google.maps.LatLng(3.4290878065901618, -76.51660508379094), weight: 329},
    {location: new google.maps.LatLng(3.4250609784210844, -76.51488847016083), weight: 774},
    {location: new google.maps.LatLng(3.4166645586142086, -76.51673382932174), weight: 1818},
    {location: new google.maps.LatLng(3.419534771537968, -76.49591988905668), weight: 1530},
    {location: new google.maps.LatLng(3.41520802942298, -76.493237680305), weight: 2106},
    {location: new google.maps.LatLng(3.4157220988351096, -76.53383559476927), weight: 330},
    {location: new google.maps.LatLng(3.4130660706512925, -76.53984374247463), weight: 976},
    {location: new google.maps.LatLng(3.427031555952873, -76.55134505496746), weight: 1975},
    {location: new google.maps.LatLng(3.408053549563415, -76.50817222583817), weight: 936},
    {location: new google.maps.LatLng(3.431957663249241, -76.47495575209557), weight: 1563},
    {location: new google.maps.LatLng(3.400770815705138, -76.55177421321405), weight: 1219},
    {location: new google.maps.LatLng(3.3970865884759056, -76.54259032842468), weight: 1954},
    {location: new google.maps.LatLng(3.393316666803048, -76.53735465673438), weight: 399},
    {location: new google.maps.LatLng(3.387318718983735, -76.5197593748766), weight: 1741},
    {location: new google.maps.LatLng(3.3834202377137204, -76.52078934305466), weight: 1111},
    {location: new google.maps.LatLng(3.381278208361199, -76.52023144362487), weight: 1826},
    {location: new google.maps.LatLng(3.377208339558826, -76.52327843281832), weight: 1772},
    {location: new google.maps.LatLng(3.378150837005705, -76.54460735730136), weight: 1965},
    {location: new google.maps.LatLng(3.3935733137749238, -76.54932804783431), weight: 841},
    {location: new google.maps.LatLng(3.390745863684127, -76.55031510067163), weight: 770},
    {location: new google.maps.LatLng(3.3790932549330677, -76.54688187341141), weight: 650},
    {location: new google.maps.LatLng(3.4019699352880104, -76.51345082175563), weight: 1401},
    {location: new google.maps.LatLng(3.4030409276299833, -76.51731320242338), weight: 1474},
    {location: new google.maps.LatLng(3.4044546356985284, -76.52143307513562), weight: 1926},
    {location: new google.maps.LatLng(3.429601076750566, -76.53761216054455), weight: 1566},
    {location: new google.maps.LatLng(3.4454939428890783, -76.5016920200071), weight: 2354},
    {location: new google.maps.LatLng(3.4492208216317457, -76.50594063874162), weight: 2043},
    {location: new google.maps.LatLng(3.4422382667554077, -76.50988885009086), weight: 2333},
    {location: new google.maps.LatLng(3.4407817764607853, -76.51752778074483), weight: 696},
    {location: new google.maps.LatLng(3.435598366122187, -76.51645489840418), weight: 1073},
    {location: new google.maps.LatLng(3.431143181324255, -76.51272126375868), weight: 1275},
    {location: new google.maps.LatLng(3.48276199070547, -76.49976083030087), weight: 1485},
    {location: new google.maps.LatLng(3.4781785185724408, -76.51280709388969), weight: 1470},
    {location: new google.maps.LatLng(3.474494590235007, -76.51366540070475), weight: 1248},
    {location: new google.maps.LatLng(3.47162454307462, -76.51366540070475), weight: 2160},
    {location: new google.maps.LatLng(3.458302269741842, -76.51645489800703), weight: 1776},
    {location: new google.maps.LatLng(3.4627144903470133, -76.50246449692165), weight: 706},
    {location: new google.maps.LatLng(3.4828048267502214, -76.48761578902122), weight: 2369},
    {location: new google.maps.LatLng(3.4622861203152, -76.52302094514219), weight: 2498},
    {location: new google.maps.LatLng(3.4636569037348472, -76.51053258098315), weight: 1510},
    {location: new google.maps.LatLng(3.4662271172959103, -76.5095026128051), weight: 2330},
    {location: new google.maps.LatLng(3.4567601292443983, -76.4885170108912), weight: 1464},
    {location: new google.maps.LatLng(3.460229941169211, -76.48521252965324), weight: 628},
    {location: new google.maps.LatLng(3.423860462402868, -76.53855630259389), weight: 364},
    {location: new google.maps.LatLng(3.422061153775949, -76.54383489070575), weight: 2439},
    {location: new google.maps.LatLng(3.4016910381681438, -76.54218265181241), weight: 1815},
    {location: new google.maps.LatLng(3.396935816423716, -76.55031510890593), weight: 2230},
   
  ];
}

A partir de estas configuraciones y data de entrada, podemos obtener un mapa de calor soportado en Google Maps. Podemos ver este ejemplo en: Mapa de calor Google Maps Ejemplo.

El resultado será:

Podemos ocultar o visualizar la capa del mapa de calor; cambiar los colores del degradado; cambar el radio de intensidad de cada punto ponderado; y por último, cambiar la transparencia de la capa.

Así mismo, podemos considerar, por ejemplo, que la representación visual se encuentra muy dispersa y no nos permite tener una idea concluyente. Podemos intentar ampliando el radio (radius) de cada punto (en el código directamente), es decir, su influencia. De manera que nos permita una visualización con mayor densidad. Ampliando a 70 píxeles el radio del código anterior, tendríamos:

mapas de calor

A partir de esta imagen los tomadores de decisiones pueden tener una idea aproximada respecto a las zonas geográficas de mayor densidad poblacional. Al contrario de los algoritmos tradicionales, no obtendremos una coordenada específica (que probablemente conduzca a un lugar inhabitable o no disponible); tendremos zonas de densidad basadas en la ponderación deseada.

Podemos ampliar el zoom sobre una zona deseada y conocer los puntos específicos (con su intensidad respectiva):

mapas de calor

Aquí podemos ver con claridad la diferencia del peso ponderado de los puntos; aquellos puntos más intensos serán aquellas instituciones educativas con mayor población estudiantil (de acuerdo a nuestro caso). Podemos incluso, haciendo uso del registro de imágenes en campo de Google, revisar un sector en específico; revisar el estado de las vías, revisar si existen unidades habitables, entre otros:


Tal como lo hemos mencionado, los mapas de calor son no nos proporcionan como resultado una localización específica; nos proporcionan una visión de densidad basada en un factor de ponderación establecido. Además, es una herramienta dinámica, la cual puede integrarse con fuentes de datos diversas, que puede manipularse en un entorno geográfico real.

Es una herramienta que recomendamos para el análisis preliminar y la búsqueda de zonas de localización.

Sin embargo, al utilizar mapas de calor en entornos como por ejemplo Python, podemos integrar a esta herramienta, un método heurístico que nos proporcione una localización específica. Si quieres conocer un modelo que integra ambas herramientas, te invitamos a leer: Mapas de calor y Algoritmo de Centro de Gravedad utilizando Python.

Bryan Salazar López

Ingeniero Industrial y Magíster en Logística Integral especializado en productividad y modelamiento de procesos bajo dimensiones de sostenibilidad, industria 4.0, transformación digital y modelos de optimización. Docente universitario de pregrado y posgrado con experiencia en la enseñanza de estos temas. Fundador de Ingenieriaindustrialonline.com, un sitio en donde se recogen las aportaciones de investigaciones, artículos y referencias relevantes para la industria.

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.

Botón volver arriba
Nuestros partners recogerán datos y usarán cookies para ofrecerle anuncios personalizados y medir el rendimiento.    Ver Política de privacidad
Privacidad