Handle path and rects in map

There are many installations on the map that are drawn with rect
instead of path.  I could transform them with Inkscape, but i finally
found out about DOMMatrix, that helps me a lot to convert points, as
it can parse the values of the `transform` attribute.

I also saw that SVGGraphicElements has getCTM() and getScreenCTM(), but
neither of them worked for me: the resulting transformation was “shrunk”
on the map (i.e., like it was scaled down).
This commit is contained in:
jordi fita mas 2024-01-29 16:00:36 +01:00
parent d5b61e7283
commit 1de4042d91
2 changed files with 159 additions and 45 deletions

View File

@ -1503,19 +1503,85 @@ values (52, 72, 'Juli Verd', current_date + interval '23 days', current_date + i
alter table amenity alter column amenity_id restart with 132;
select add_amenity(52, 'edifici-camping', 'Edifici Càmping', '<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec scelerisque lorem vestibulum enim sollicitudin ornare. Aliquam egestas pretium porttitor. Donec iaculis tempus est, id lobortis risus semper vel. Maecenas ut imperdiet neque. Donec mattis purus felis, vitae interdum risus egestas pharetra. Vestibulum dui neque, condimentum ultrices erat sed, fringilla pharetra ante. Maecenas hendrerit neque mattis risus consectetur euismod. Cras urna metus, bibendum a neque sed, pharetra commodo magna.</p>', '<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec scelerisque lorem vestibulum enim sollicitudin ornare. Aliquam egestas pretium porttitor. Donec iaculis tempus est, id lobortis risus semper vel. Maecenas ut imperdiet neque. Donec mattis purus felis, vitae interdum risus egestas pharetra. Vestibulum dui neque, condimentum ultrices erat sed, fringilla pharetra ante. Maecenas hendrerit neque mattis risus consectetur euismod. Cras urna metus, bibendum a neque sed, pharetra commodo magna.</p>');
select add_amenity(52, 'camp-esport', 'Camp Esport', '<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec scelerisque lorem vestibulum enim sollicitudin ornare. Aliquam egestas pretium porttitor. Donec iaculis tempus est, id lobortis risus semper vel. Maecenas ut imperdiet neque. Donec mattis purus felis, vitae interdum risus egestas pharetra. Vestibulum dui neque, condimentum ultrices erat sed, fringilla pharetra ante. Maecenas hendrerit neque mattis risus consectetur euismod. Cras urna metus, bibendum a neque sed, pharetra commodo magna.</p>', '<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec scelerisque lorem vestibulum enim sollicitudin ornare. Aliquam egestas pretium porttitor. Donec iaculis tempus est, id lobortis risus semper vel. Maecenas ut imperdiet neque. Donec mattis purus felis, vitae interdum risus egestas pharetra. Vestibulum dui neque, condimentum ultrices erat sed, fringilla pharetra ante. Maecenas hendrerit neque mattis risus consectetur euismod. Cras urna metus, bibendum a neque sed, pharetra commodo magna.</p>');
select add_amenity(52, 'botiga', 'Botiga', '<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec scelerisque lorem vestibulum enim sollicitudin ornare. Aliquam egestas pretium porttitor. Donec iaculis tempus est, id lobortis risus semper vel. Maecenas ut imperdiet neque. Donec mattis purus felis, vitae interdum risus egestas pharetra. Vestibulum dui neque, condimentum ultrices erat sed, fringilla pharetra ante. Maecenas hendrerit neque mattis risus consectetur euismod. Cras urna metus, bibendum a neque sed, pharetra commodo magna.</p>', '<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec scelerisque lorem vestibulum enim sollicitudin ornare. Aliquam egestas pretium porttitor. Donec iaculis tempus est, id lobortis risus semper vel. Maecenas ut imperdiet neque. Donec mattis purus felis, vitae interdum risus egestas pharetra. Vestibulum dui neque, condimentum ultrices erat sed, fringilla pharetra ante. Maecenas hendrerit neque mattis risus consectetur euismod. Cras urna metus, bibendum a neque sed, pharetra commodo magna.</p>');
select add_amenity(52, 'recepcio', 'Recepció', '<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec scelerisque lorem vestibulum enim sollicitudin ornare. Aliquam egestas pretium porttitor. Donec iaculis tempus est, id lobortis risus semper vel. Maecenas ut imperdiet neque. Donec mattis purus felis, vitae interdum risus egestas pharetra. Vestibulum dui neque, condimentum ultrices erat sed, fringilla pharetra ante. Maecenas hendrerit neque mattis risus consectetur euismod. Cras urna metus, bibendum a neque sed, pharetra commodo magna.</p>', '<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec scelerisque lorem vestibulum enim sollicitudin ornare. Aliquam egestas pretium porttitor. Donec iaculis tempus est, id lobortis risus semper vel. Maecenas ut imperdiet neque. Donec mattis purus felis, vitae interdum risus egestas pharetra. Vestibulum dui neque, condimentum ultrices erat sed, fringilla pharetra ante. Maecenas hendrerit neque mattis risus consectetur euismod. Cras urna metus, bibendum a neque sed, pharetra commodo magna.</p>');
select add_amenity(52, 'bar', 'Bar', '<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec scelerisque lorem vestibulum enim sollicitudin ornare. Aliquam egestas pretium porttitor. Donec iaculis tempus est, id lobortis risus semper vel. Maecenas ut imperdiet neque. Donec mattis purus felis, vitae interdum risus egestas pharetra. Vestibulum dui neque, condimentum ultrices erat sed, fringilla pharetra ante. Maecenas hendrerit neque mattis risus consectetur euismod. Cras urna metus, bibendum a neque sed, pharetra commodo magna.</p>', '<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec scelerisque lorem vestibulum enim sollicitudin ornare. Aliquam egestas pretium porttitor. Donec iaculis tempus est, id lobortis risus semper vel. Maecenas ut imperdiet neque. Donec mattis purus felis, vitae interdum risus egestas pharetra. Vestibulum dui neque, condimentum ultrices erat sed, fringilla pharetra ante. Maecenas hendrerit neque mattis risus consectetur euismod. Cras urna metus, bibendum a neque sed, pharetra commodo magna.</p>');
select add_amenity(52, 'edifici_serveis', 'Edifici Serveis', '<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec scelerisque lorem vestibulum enim sollicitudin ornare. Aliquam egestas pretium porttitor. Donec iaculis tempus est, id lobortis risus semper vel. Maecenas ut imperdiet neque. Donec mattis purus felis, vitae interdum risus egestas pharetra. Vestibulum dui neque, condimentum ultrices erat sed, fringilla pharetra ante. Maecenas hendrerit neque mattis risus consectetur euismod. Cras urna metus, bibendum a neque sed, pharetra commodo magna.</p>', '<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec scelerisque lorem vestibulum enim sollicitudin ornare. Aliquam egestas pretium porttitor. Donec iaculis tempus est, id lobortis risus semper vel. Maecenas ut imperdiet neque. Donec mattis purus felis, vitae interdum risus egestas pharetra. Vestibulum dui neque, condimentum ultrices erat sed, fringilla pharetra ante. Maecenas hendrerit neque mattis risus consectetur euismod. Cras urna metus, bibendum a neque sed, pharetra commodo magna.</p>');
select add_amenity(52, 'piscina', 'Piscina', '<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec scelerisque lorem vestibulum enim sollicitudin ornare. Aliquam egestas pretium porttitor. Donec iaculis tempus est, id lobortis risus semper vel. Maecenas ut imperdiet neque. Donec mattis purus felis, vitae interdum risus egestas pharetra. Vestibulum dui neque, condimentum ultrices erat sed, fringilla pharetra ante. Maecenas hendrerit neque mattis risus consectetur euismod. Cras urna metus, bibendum a neque sed, pharetra commodo magna.</p>', '<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec scelerisque lorem vestibulum enim sollicitudin ornare. Aliquam egestas pretium porttitor. Donec iaculis tempus est, id lobortis risus semper vel. Maecenas ut imperdiet neque. Donec mattis purus felis, vitae interdum risus egestas pharetra. Vestibulum dui neque, condimentum ultrices erat sed, fringilla pharetra ante. Maecenas hendrerit neque mattis risus consectetur euismod. Cras urna metus, bibendum a neque sed, pharetra commodo magna.</p>');
select add_amenity(52, 'parc', 'Parc', '<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec scelerisque lorem vestibulum enim sollicitudin ornare. Aliquam egestas pretium porttitor. Donec iaculis tempus est, id lobortis risus semper vel. Maecenas ut imperdiet neque. Donec mattis purus felis, vitae interdum risus egestas pharetra. Vestibulum dui neque, condimentum ultrices erat sed, fringilla pharetra ante. Maecenas hendrerit neque mattis risus consectetur euismod. Cras urna metus, bibendum a neque sed, pharetra commodo magna.</p>', '<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec scelerisque lorem vestibulum enim sollicitudin ornare. Aliquam egestas pretium porttitor. Donec iaculis tempus est, id lobortis risus semper vel. Maecenas ut imperdiet neque. Donec mattis purus felis, vitae interdum risus egestas pharetra. Vestibulum dui neque, condimentum ultrices erat sed, fringilla pharetra ante. Maecenas hendrerit neque mattis risus consectetur euismod. Cras urna metus, bibendum a neque sed, pharetra commodo magna.</p>');
select add_amenity_carousel_slide(52, 'edifici-camping', 80, 'Llegenda');
select add_amenity_carousel_slide(52, 'edifici-camping', 81, 'Llegenda');
select add_amenity_carousel_slide(52, 'edifici-camping', 82, 'Llegenda');
select add_amenity_carousel_slide(52, 'edifici-camping', 83, 'Llegenda');
select add_amenity_carousel_slide(52, 'edifici-camping', 84, 'Llegenda');
select add_amenity_carousel_slide(52, 'edifici-camping', 85, 'Llegenda');
select add_amenity_carousel_slide(52, 'camp-esport', 80, 'Llegenda');
select add_amenity_carousel_slide(52, 'camp-esport', 81, 'Llegenda');
select add_amenity_carousel_slide(52, 'camp-esport', 82, 'Llegenda');
select add_amenity_carousel_slide(52, 'camp-esport', 83, 'Llegenda');
select add_amenity_carousel_slide(52, 'camp-esport', 84, 'Llegenda');
select add_amenity_carousel_slide(52, 'camp-esport', 85, 'Llegenda');
select add_amenity_carousel_slide(52, 'botiga', 80, 'Llegenda');
select add_amenity_carousel_slide(52, 'botiga', 81, 'Llegenda');
select add_amenity_carousel_slide(52, 'botiga', 82, 'Llegenda');
select add_amenity_carousel_slide(52, 'botiga', 83, 'Llegenda');
select add_amenity_carousel_slide(52, 'botiga', 84, 'Llegenda');
select add_amenity_carousel_slide(52, 'botiga', 85, 'Llegenda');
select add_amenity_carousel_slide(52, 'recepcio', 80, 'Llegenda');
select add_amenity_carousel_slide(52, 'recepcio', 81, 'Llegenda');
select add_amenity_carousel_slide(52, 'recepcio', 82, 'Llegenda');
select add_amenity_carousel_slide(52, 'recepcio', 83, 'Llegenda');
select add_amenity_carousel_slide(52, 'recepcio', 84, 'Llegenda');
select add_amenity_carousel_slide(52, 'recepcio', 85, 'Llegenda');
select add_amenity_carousel_slide(52, 'bar', 80, 'Llegenda');
select add_amenity_carousel_slide(52, 'bar', 81, 'Llegenda');
select add_amenity_carousel_slide(52, 'bar', 82, 'Llegenda');
select add_amenity_carousel_slide(52, 'bar', 83, 'Llegenda');
select add_amenity_carousel_slide(52, 'bar', 84, 'Llegenda');
select add_amenity_carousel_slide(52, 'bar', 85, 'Llegenda');
select add_amenity_carousel_slide(52, 'edifici_serveis', 80, 'Llegenda');
select add_amenity_carousel_slide(52, 'edifici_serveis', 81, 'Llegenda');
select add_amenity_carousel_slide(52, 'edifici_serveis', 82, 'Llegenda');
select add_amenity_carousel_slide(52, 'edifici_serveis', 83, 'Llegenda');
select add_amenity_carousel_slide(52, 'edifici_serveis', 84, 'Llegenda');
select add_amenity_carousel_slide(52, 'edifici_serveis', 85, 'Llegenda');
select add_amenity_carousel_slide(52, 'piscina', 80, 'Llegenda');
select add_amenity_carousel_slide(52, 'piscina', 81, 'Llegenda');
select add_amenity_carousel_slide(52, 'piscina', 82, 'Llegenda');
select add_amenity_carousel_slide(52, 'piscina', 83, 'Llegenda');
select add_amenity_carousel_slide(52, 'piscina', 84, 'Llegenda');
select add_amenity_carousel_slide(52, 'piscina', 85, 'Llegenda');
select add_amenity_carousel_slide(52, 'parc', 80, 'Llegenda');
select add_amenity_carousel_slide(52, 'parc', 81, 'Llegenda');
select add_amenity_carousel_slide(52, 'parc', 82, 'Llegenda');
select add_amenity_carousel_slide(52, 'parc', 83, 'Llegenda');
select add_amenity_carousel_slide(52, 'parc', 84, 'Llegenda');
select add_amenity_carousel_slide(52, 'parc', 85, 'Llegenda');
select add_amenity_feature(52, 'edifici-camping', 'person', 'Máx. 6 pers.');
select add_amenity_feature(52, 'edifici-camping', 'area', 'de 55 a 65 ');
select add_amenity_feature(52, 'edifici-camping', 'electricity', 'Electricitat');
select add_amenity_feature(52, 'edifici-camping', 'shower', 'Accés als serveis');
select add_amenity_feature(52, 'camp-esport', 'person', 'Máx. 6 pers.');
select add_amenity_feature(52, 'camp-esport', 'area', 'de 55 a 65 ');
select add_amenity_feature(52, 'camp-esport', 'electricity', 'Electricitat');
select add_amenity_feature(52, 'camp-esport', 'shower', 'Accés als serveis');
select add_amenity_feature(52, 'botiga', 'person', 'Máx. 6 pers.');
select add_amenity_feature(52, 'botiga', 'area', 'de 55 a 65 ');
select add_amenity_feature(52, 'botiga', 'electricity', 'Electricitat');
select add_amenity_feature(52, 'botiga', 'shower', 'Accés als serveis');
select add_amenity_feature(52, 'recepcio', 'person', 'Máx. 6 pers.');
select add_amenity_feature(52, 'recepcio', 'area', 'de 55 a 65 ');
select add_amenity_feature(52, 'recepcio', 'electricity', 'Electricitat');
select add_amenity_feature(52, 'recepcio', 'shower', 'Accés als serveis');
select add_amenity_feature(52, 'bar', 'person', 'Máx. 6 pers.');
select add_amenity_feature(52, 'bar', 'area', 'de 55 a 65 ');
select add_amenity_feature(52, 'bar', 'electricity', 'Electricitat');
select add_amenity_feature(52, 'bar', 'shower', 'Accés als serveis');
select add_amenity_feature(52, 'edifici_serveis', 'person', 'Máx. 6 pers.');
select add_amenity_feature(52, 'edifici_serveis', 'area', 'de 55 a 65 ');
select add_amenity_feature(52, 'edifici_serveis', 'electricity', 'Electricitat');
select add_amenity_feature(52, 'edifici_serveis', 'shower', 'Accés als serveis');
select add_amenity_feature(52, 'piscina', 'person', 'Máx. 6 pers.');
select add_amenity_feature(52, 'piscina', 'area', 'de 55 a 65 ');
select add_amenity_feature(52, 'piscina', 'electricity', 'Electricitat');
select add_amenity_feature(52, 'piscina', 'shower', 'Accés als serveis');
select add_amenity_feature(52, 'parc', 'person', 'Máx. 6 pers.');
select add_amenity_feature(52, 'parc', 'area', 'de 55 a 65 ');
select add_amenity_feature(52, 'parc', 'electricity', 'Electricitat');
select add_amenity_feature(52, 'parc', 'shower', 'Accés als serveis');
insert into legal_text (company_id, slug, name, content)
values (52, 'reservation', 'Normes i condicions de cancel·lació', '<h3>Termes de canceŀlació</h3><p><ul><li>Anul·lació 30 dies abans de la vostra arribada: es retornarà el 95 % del vostre dipòsit.</li><li>Anul·lació entre 30 i 7 dies abans de la vostra arribada: es retornarà el 50 % de la vostra fiança.</li><li>Anul·lació amb menys de 7 dies abans de la vostra arribada: <strong>no</strong> es retornarà el vostre dipòsit.</li><li>Si el client decideix deixar lallotjament o la parcel·la abans de la data prevista, no es farà cap reemborsament.</li><li>Si el client no es presenta el dia darribada i no li ha informat per escrit, el càmping anul·larà automàticament la seva reserva.</li></ul><small>(La sol·licitud es farà sempre per escrit pel client.)</small></p>')

View File

@ -76,11 +76,32 @@
});
}
// XXX: this is from the “parceles” layer.
const ctm = [1, 0, 0, 1, 83.2784, 66.1766];
function getPath(el) {
if (!el) {
return el;
}
switch (el.localName) {
case 'path':
case 'rect':
return el;
case 'g':
return getPath(el.firstElementChild);
default:
console.warn('unhandled element type', el.localName);
return null
}
}
function transform(x, y) {
return [ctm[0] * x + ctm[2] * y + ctm[4], ctm[1] * x + ctm[3] * y + ctm[5]];
function getCTM(ctm, el) {
if (el.localName === 'svg') {
return ctm;
}
const transform = el.getAttribute('transform');
if (!transform) {
return getCTM(ctm, el.parentElement);
}
const matrix = new DOMMatrix(transform);
return getCTM(matrix.multiply(ctm), el.parentElement);
}
function setupFeatures(prefix, baseURI) {
@ -89,37 +110,64 @@
if (!label) {
continue;
}
const path = campsite.firstElementChild;
const commands = parse(path.getAttribute('d'));
const points = [];
const p0 = [0, 0];
for (const cmd of commands) {
switch (cmd[0]) {
case 'M':
case 'L':
const cmdM = transform(cmd[1], cmd[2]);
p0[0] = cmdM[0];
p0[1] = latLngBounds.getNorth() - cmdM[1];
break;
case 'm':
case 'l':
p0[0] += cmd[1];
p0[1] -= cmd[2];
break;
case 'C':
const cmdC = transform(cmd[5], cmd[6]);
p0[0] = cmdC[0];
p0[1] = latLngBounds.getNorth() - cmdC[1];
break;
case 'Z':
case 'z':
continue;
default:
console.error(cmd);
}
points.push([p0[1], p0[0]]);
const path = getPath(campsite);
if (!path) {
console.warn(campsite, 'has no path');
continue;
}
const ctm = getCTM(new DOMMatrix([1, 0, 0, 1, 0, 0]), path);
const points = [];
const p0 = new DOMPoint();
function setP0(x, y) {
p0.x = x;
p0.y = y;
const p1 = p0.matrixTransform(ctm);
p0.x = p1.x;
p0.y = latLngBounds.getNorth() - p1.y;
}
switch (path.localName) {
case 'rect':
const x = parseFloat(path.getAttribute('x'));
const y = parseFloat(path.getAttribute('y'));
const w = parseFloat(path.getAttribute('width'));
const h = parseFloat(path.getAttribute('height'));
setP0(x, y);
points.push([p0.y, p0.x]);
setP0(x + w, y);
points.push([p0.y, p0.x]);
setP0(x + w, y + h);
points.push([p0.y, p0.x]);
setP0(x, y + h);
points.push([p0.y, p0.x]);
break;
case 'path':
const commands = parse(path.getAttribute('d'));
for (const cmd of commands) {
switch (cmd[0]) {
case 'M':
case 'L':
setP0(cmd[1], cmd[2]);
break;
case 'm':
case 'l':
p0.x += cmd[1];
p0.y -= cmd[2];
break;
case 'C':
setP0(cmd[5], cmd[6]);
break;
case 'Z':
case 'z':
continue;
default:
console.error(cmd);
}
points.push([p0.y, p0.x]);
}
break;
}
console.log(points);
const feature = L.polygon(points, {color: 'transparent'}).addTo(map);
feature.on({
mouseover: highlightAccommodation,