Pemière version des tuiles pbf de cabanes à faible zoom

This commit is contained in:
leosw committed 2026-10-18 15:19:59 +02:00
1 parent 5c77ff2c1d
commit 9c68959083
5 files changed
+140 -17

No files matched your search

+72 -9
View File
@@ -1,6 +1,7 @@
// Carte principale
var mymap;
var poiLayer;
var vectorLayer;
var icons = {};
$(document).ready(function() {
@@ -46,6 +47,38 @@ $(document).ready(function() {
poiLayer = L.layerGroup().addTo(mymap);
// Couche vectorielle utilisée pour les faibles zooms
vectorLayer = L.vectorGrid.protobuf(
root + "poi/tile/{z}/{x}/{y}.pbf",
{
interactive: true,
maxZoom: 9,
vectorTileLayerStyles: {
pois: {}
}
}
);
// Clic sur un POI vectoriel
vectorLayer.on("click", function(e) {
if (
e.layer &&
e.layer.properties &&
e.layer.properties.permalink
) {
window.location =
root +
"poi/" +
e.layer.properties.permalink;
}
});
// ---------------------------------------------------------
// Contrôles
// ---------------------------------------------------------
@@ -138,12 +171,9 @@ $(document).ready(function() {
// ---------------------------------------------------------
function loadVisiblePois() {
if (mymap.getZoom() < 10) {
poiLayer.clearLayers();
if (mymap.getZoom() < 10)
return;
}
var b = mymap.getBounds();
@@ -178,35 +208,68 @@ $(document).ready(function() {
direction: "top",
offset: [0, -10],
opacity: 0.9,
className:
"poi-tooltip"
className: "poi-tooltip"
}
);
marker.on(
"click",
function() {
window.location =
root +
"poi/" +
poi.permalink;
}
);
poiLayer.addLayer(marker);
});
}
);
}
// ---------------------------------------------------------
// Bascule entre le calque tle et geojson
// ---------------------------------------------------------
function switchLayers() {
var z = mymap.getZoom();
if (z < 10) {
poiLayer.clearLayers();
if (!mymap.hasLayer(vectorLayer)) {
mymap.addLayer(vectorLayer);
}
} else {
if (mymap.hasLayer(vectorLayer)) {
mymap.removeLayer(vectorLayer);
}
loadVisiblePois();
}
}
// ---------------------------------------------------------
// Rechargement automatique
// ---------------------------------------------------------
mymap.on("moveend", loadVisiblePois);
mymap.on("zoomend", loadVisiblePois);
mymap.on("zoomend", switchLayers);
mymap.on("moveend", function() {
// Premier chargement
if (mymap.getZoom() >= 10) {
loadVisiblePois();
}
});
switchLayers();
});
@@ -0,0 +1,2 @@
"use strict";function __$strToBlobUri(t,e,r){try{return window.URL.createObjectURL(new Blob([Uint8Array.from(t.split("").map(function(t){return t.charCodeAt(0)}))],{type:e}))}catch(i){return"data:"+e+(r?";base64,":",")+t}}function Pbf(t){this.buf=ArrayBuffer.isView&&ArrayBuffer.isView(t)?t:new Uint8Array(t||0),this.pos=0,this.type=0,this.length=this.buf.length}function readVarintRemainder(t,e,r){var i,n,o=r.buf;if(n=o[r.pos++],i=(112&n)>>4,n<128)return toNum(t,i,e);if(n=o[r.pos++],i|=(127&n)<<3,n<128)return toNum(t,i,e);if(n=o[r.pos++],i|=(127&n)<<10,n<128)return toNum(t,i,e);if(n=o[r.pos++],i|=(127&n)<<17,n<128)return toNum(t,i,e);if(n=o[r.pos++],i|=(127&n)<<24,n<128)return toNum(t,i,e);if(n=o[r.pos++],i|=(1&n)<<31,n<128)return toNum(t,i,e);throw new Error("Expected varint not more than 10 bytes")}function readPackedEnd(t){return t.type===Pbf.Bytes?t.readVarint()+t.pos:t.pos+1}function toNum(t,e,r){return r?4294967296*e+(t>>>0):4294967296*(e>>>0)+(t>>>0)}function writeBigVarint(t,e){var r,i;if(t>=0?(r=t%4294967296|0,i=t/4294967296|0):(r=~(-t%4294967296),i=~(-t/4294967296),4294967295^r?r=r+1|0:(r=0,i=i+1|0)),t>=0x10000000000000000||t<-0x10000000000000000)throw new Error("Given varint doesn't fit into 10 bytes");e.realloc(10),writeBigVarintLow(r,i,e),writeBigVarintHigh(i,e)}function writeBigVarintLow(t,e,r){r.buf[r.pos++]=127&t|128,t>>>=7,r.buf[r.pos++]=127&t|128,t>>>=7,r.buf[r.pos++]=127&t|128,t>>>=7,r.buf[r.pos++]=127&t|128,t>>>=7,r.buf[r.pos]=127&t}function writeBigVarintHigh(t,e){var r=(7&t)<<4;e.buf[e.pos++]|=r|((t>>>=3)?128:0),t&&(e.buf[e.pos++]=127&t|((t>>>=7)?128:0),t&&(e.buf[e.pos++]=127&t|((t>>>=7)?128:0),t&&(e.buf[e.pos++]=127&t|((t>>>=7)?128:0),t&&(e.buf[e.pos++]=127&t|((t>>>=7)?128:0),t&&(e.buf[e.pos++]=127&t)))))}function makeRoomForExtraLength(t,e,r){var i=e<=16383?1:e<=2097151?2:e<=268435455?3:Math.ceil(Math.log(e)/(7*Math.LN2));r.realloc(i);for(var n=r.pos-1;n>=t;n--)r.buf[n+i]=r.buf[n]}function writePackedVarint(t,e){for(var r=0;r<t.length;r++)e.writeVarint(t[r])}function writePackedSVarint(t,e){for(var r=0;r<t.length;r++)e.writeSVarint(t[r])}function writePackedFloat(t,e){for(var r=0;r<t.length;r++)e.writeFloat(t[r])}function writePackedDouble(t,e){for(var r=0;r<t.length;r++)e.writeDouble(t[r])}function writePackedBoolean(t,e){for(var r=0;r<t.length;r++)e.writeBoolean(t[r])}function writePackedFixed32(t,e){for(var r=0;r<t.length;r++)e.writeFixed32(t[r])}function writePackedSFixed32(t,e){for(var r=0;r<t.length;r++)e.writeSFixed32(t[r])}function writePackedFixed64(t,e){for(var r=0;r<t.length;r++)e.writeFixed64(t[r])}function writePackedSFixed64(t,e){for(var r=0;r<t.length;r++)e.writeSFixed64(t[r])}function readUInt32(t,e){return(t[e]|t[e+1]<<8|t[e+2]<<16)+16777216*t[e+3]}function writeInt32(t,e,r){t[r]=e,t[r+1]=e>>>8,t[r+2]=e>>>16,t[r+3]=e>>>24}function readInt32(t,e){return(t[e]|t[e+1]<<8|t[e+2]<<16)+(t[e+3]<<24)}function readUtf8(t,e,r){for(var i="",n=e;n<r;){var o=t[n],s=null,a=o>239?4:o>223?3:o>191?2:1;if(n+a>r)break;var u,h,l;1===a?o<128&&(s=o):2===a?128==(192&(u=t[n+1]))&&(s=(31&o)<<6|63&u)<=127&&(s=null):3===a?(u=t[n+1],h=t[n+2],128==(192&u)&&128==(192&h)&&((s=(15&o)<<12|(63&u)<<6|63&h)<=2047||s>=55296&&s<=57343)&&(s=null)):4===a&&(u=t[n+1],h=t[n+2],l=t[n+3],128==(192&u)&&128==(192&h)&&128==(192&l)&&((s=(15&o)<<18|(63&u)<<12|(63&h)<<6|63&l)<=65535||s>=1114112)&&(s=null)),null===s?(s=65533,a=1):s>65535&&(s-=65536,i+=String.fromCharCode(s>>>10&1023|55296),s=56320|1023&s),i+=String.fromCharCode(s),n+=a}return i}function writeUtf8(t,e,r){for(var i,n,o=0;o<e.length;o++){if((i=e.charCodeAt(o))>55295&&i<57344){if(!n){i>56319||o+1===e.length?(t[r++]=239,t[r++]=191,t[r++]=189):n=i;continue}if(i<56320){t[r++]=239,t[r++]=191,t[r++]=189,n=i;continue}i=n-55296<<10|i-56320|65536,n=null}else n&&(t[r++]=239,t[r++]=191,t[r++]=189,n=null);i<128?t[r++]=i:(i<2048?t[r++]=i>>6|192:(i<65536?t[r++]=i>>12|224:(t[r++]=i>>18|240,t[r++]=i>>12&63|128),t[r++]=i>>6&63|128),t[r++]=63&i|128)}return r}function Point$1(t,e){this.x=t,this.y=e}function VectorTileFeature$2(t,e,r,i,n){this.properties={},this.extent=r,this.type=0,this._pbf=t,this._geometry=-1,this._keys=i,this._values=n,t.readFields(readFeature,this,e)}function readFeature(t,e,r){1==t?e.id=r.readVarint():2==t?readTag(r,e):3==t?e.type=r.readVarint():4==t&&(e._geometry=r.pos)}function readTag(t,e){for(var r=t.readVarint()+t.pos;t.pos<r;){var i=e._keys[t.readVarint()],n=e._values[t.readVarint()];e.properties[i]=n}}function classifyRings(t){var e=t.length;if(e<=1)return[t];for(var r,i,n=[],o=0;o<e;o++){var s=signedArea(t[o]);0!==s&&(void 0===i&&(i=s<0),i===s<0?(r&&n.push(r),r=[t[o]]):r.push(t[o]))}return r&&n.push(r),n}function signedArea(t){for(var e,r,i=0,n=0,o=t.length,s=o-1;n<o;s=n++)e=t[n],r=t[s],i+=(r.x-e.x)*(e.y+r.y);return i}function VectorTileLayer$2(t,e){this.version=1,this.name=null,this.extent=4096,this.length=0,this._pbf=t,this._keys=[],this._values=[],this._features=[],t.readFields(readLayer,this,e),this.length=this._features.length}function readLine truncated
;var workerCode=__$strToBlobUri('"use strict";function simplify$1(e,t){var r,n,o,i,a=t*t,s=e.length,l=0,u=s-1,c=[];for(e[l][2]=1,e[u][2]=1;u;){for(n=0,r=l+1;r<u;r++)(o=getSqSegDist(e[r],e[l],e[u]))>n&&(i=r,n=o);n>a?(e[i][2]=n,c.push(l),c.push(i),l=i):(u=c.pop(),l=c.pop())}}function getSqSegDist(e,t,r){var n=t[0],o=t[1],i=r[0],a=r[1],s=e[0],l=e[1],u=i-n,c=a-o;if(0!==u||0!==c){var f=((s-n)*u+(l-o)*c)/(u*u+c*c);f>1?(n=i,o=a):f>0&&(n+=u*f,o+=c*f)}return u=s-n,c=l-o,u*u+c*c}function convert$1(e,t){var r=[];if("FeatureCollection"===e.type)for(var n=0;n<e.features.length;n++)convertFeature(r,e.features[n],t);else"Feature"===e.type?convertFeature(r,e,t):convertFeature(r,{geometry:e},t);return r}function convertFeature(e,t,r){if(null!==t.geometry){var n,o,i,a,s=t.geometry,l=s.type,u=s.coordinates,c=t.properties;if("Point"===l)e.push(create(c,1,[projectPoint(u)]));else if("MultiPoint"===l)e.push(create(c,1,project(u)));else if("LineString"===l)e.push(create(c,2,[project(u,r)]));else if("MultiLineString"===l||"Polygon"===l){for(i=[],n=0;n<u.length;n++)a=project(u[n],r),"Polygon"===l&&(a.outer=0===n),i.push(a);e.push(create(c,"Polygon"===l?3:2,i))}else if("MultiPolygon"===l){for(i=[],n=0;n<u.length;n++)for(o=0;o<u[n].length;o++)a=project(u[n][o],r),a.outer=0===o,i.push(a);e.push(create(c,3,i))}else{if("GeometryCollection"!==l)throw new Error("Input data is not a valid GeoJSON object.");for(n=0;n<s.geometries.length;n++)convertFeature(e,{geometry:s.geometries[n],properties:c},r)}}}function create(e,t,r){var n={geometry:r,type:t,tags:e||null,min:[2,1],max:[-1,0]};return calcBBox(n),n}function project(e,t){for(var r=[],n=0;n<e.length;n++)r.push(projectPoint(e[n]));return t&&(simplify(r,t),calcSize(r)),r}function projectPoint(e){var t=Math.sin(e[1]*Math.PI/180),r=e[0]/360+.5,n=.5-.25*Math.log((1+t)/(1-t))/Math.PI;return n=n<0?0:n>1?1:n,[r,n,0]}function calcSize(e){for(var t,r,n=0,o=0,i=0;i<e.length-1;i++)t=r||e[i],r=e[i+1],n+=t[0]*r[1]-r[0]*t[1],o+=Math.abs(r[0]-t[0])+Math.abs(r[1]-t[1]);e.area=Math.abs(n/2),e.dist=o}function calcBBox(e){var t=e.geometry,r=e.min,n=e.max;if(1===e.type)calcRingBBox(r,n,t);else for(var o=0;o<t.length;o++)calcRingBBox(r,n,t[o]);return e}function calcRingBBox(e,t,r){for(var n,o=0;o<r.length;o++)n=r[o],e[0]=Math.min(n[0],e[0]),t[0]=Math.max(n[0],t[0]),e[1]=Math.min(n[1],e[1]),t[1]=Math.max(n[1],t[1])}function transformTile(e,t){if(e.transformed)return e;var r,n,o,i=e.z2,a=e.x,s=e.y;for(r=0;r<e.features.length;r++){var l=e.features[r],u=l.geometry;if(1===l.type)for(n=0;n<u.length;n++)u[n]=transformPoint(u[n],t,i,a,s);else for(n=0;n<u.length;n++){var c=u[n];for(o=0;o<c.length;o++)c[o]=transformPoint(c[o],t,i,a,s)}}return e.transformed=!0,e}function transformPoint(e,t,r,n,o){return[Math.round(t*(e[0]*r-n)),Math.round(t*(e[1]*r-o))]}function clip$1(e,t,r,n,o,i,a,s){if(r/=t,n/=t,a>=r&&s<=n)return e;if(a>n||s<r)return null;for(var l=[],u=0;u<e.length;u++){var c,f,p=e[u],h=p.geometry,m=p.type;if(c=p.min[o],f=p.max[o],c>=r&&f<=n)l.push(p);else if(!(c>n||f<r)){var g=1===m?clipPoints(h,r,n,o):clipGeometry(h,r,n,o,i,3===m);g.length&&l.push({geometry:g,type:m,tags:e[u].tags||null,min:p.min,max:p.max})}}return l.length?l:null}function clipPoints(e,t,r,n){for(var o=[],i=0;i<e.length;i++){var a=e[i],s=a[n];s>=t&&s<=r&&o.push(a)}return o}function clipGeometry(e,t,r,n,o,i){for(var a=[],s=0;s<e.length;s++){var l,u,c,f=0,p=0,h=null,m=e[s],g=m.area,d=m.dist,v=m.outer,y=m.length,x=[];for(u=0;u<y-1;u++)l=h||m[u],h=m[u+1],f=p||l[n],p=h[n],f<t?p>r?(x.push(o(l,h,t),o(l,h,r)),i||(x=newSlice(a,x,g,d,v))):p>=t&&x.push(o(l,h,t)):f>r?p<t?(x.push(o(l,h,r),o(l,h,t)),i||(x=newSlice(a,x,g,d,v))):p<=r&&x.push(o(l,h,r)):(x.push(l),p<t?(x.push(o(l,h,t)),i||(x=newSlice(a,x,g,d,v))):p>r&&(x.push(o(l,h,r)),i||(x=newSlice(a,x,g,d,v))));l=m[y-1],f=l[n],f>=t&&f<=r&&x.push(l),c=x[x.length-1],i&&c&&(x[0][0]!==c[0]||x[0][1]!==c[1])&&x.push(x[0]),newSlice(a,x,g,d,v)}return a}function newSlice(e,t,r,n,o){return t.length&&(t.area=r,t.dist=n,void 0!==o&&(t.outer=o),e.push(t)),[]}function wrap$1(e,t,r){var n=e,o=clip$2(e,1,-1-t,t,0,r,-1,2),i=clip$2(e,1,1-t,2+t,0,r,-1,2);return(o||i)&&(n=clip$2(e,1,-t,1+t,0,r,-1,2),o&&(n=shiftFeatureCoords(o,1).concat(n)),i&&(n=n.concat(shiftFeatureCoords(i,-1)))),n}function shiftFeatureCoords(e,t){for(var r=[],n=0;n<e.length;n++){var o,i=e[n],a=i.type;if(1===a)o=shiftCoords(i.geometry,t);else{o=[];for(var s=0;s<i.geometry.length;s++)o.push(shiftCoords(i.geometry[s],t))}r.push({geometry:o,type:a,tags:i.tags,min:[i.min[0]+t,i.min[1]],max:[i.max[0]+t,i.max[1]]})}return r}function shiftCoords(e,t){var r=[];r.area=e.area,r.dist=e.dist;for(var n=0;n<e.length;n++)r.push([e[n][0]+t,e[n][1],e[n][2]]);return r}function createTile$1(e,t,r,n,o,i){for(var a={features:[],numPoints:0,numSimplified:0,numFeatures:0,source:null,x:r,y:n,z2:t,transformed:!1,min:[2,1],max:[-1,0]},s=0;s<e.length;s++){a.numFeatures++,addFeature(a,e[s],o,i);var l=e[s].min,u=e[s].max;l[0]<a.min[0]&&(a.min[0]=l[0]),l[1]<a.min[1]&&(a.min[1]=l[1]),u[0]>a.Line truncated
+1 -1
View File
@@ -17,7 +17,7 @@ if(isset($controller->splitted_url[1]) && $controller->splitted_url[1] != '') {
else {
// Chargement de la carte et des dépendances Leaflet.
$head['title'] = "Carte";
$head['third'] = "leaflet/leaflet.js;leaflet-fullscreen/Leaflet.fullscreen.min.js;leaflet-easybutton/easy-button.js";
$head['third'] = "leaflet/leaflet.js;leaflet-fullscreen/Leaflet.fullscreen.min.js;leaflet-easybutton/easy-button.js;leaflet-vectorgrid/Leaflet.VectorGrid.bundled.min.js";
$head['css'] .= ";d.map.css;../third/leaflet/leaflet.css;../third/leaflet-fullscreen/leaflet.fullscreen.css;../third/leaflet-easybutton/easy-button.css";
$head['js'] = "d.map.js";
+12
View File
@@ -146,6 +146,18 @@ switch ($controller->splitted_url[1]) {
echo json_encode($out, JSON_UNESCAPED_UNICODE);
break;
case "tile":
$z = intval($controller->splitted_url[2]);
$x = intval($controller->splitted_url[3]);
$y = intval(str_replace(".pbf","",$controller->splitted_url[4]));
$pois = new Kabano\Pois();
header("Content-Type: application/x-protobuf");
echo $pois->getVectorTile($z,$x,$y);
break;
default:
// Affichage / édition / suppression d’un POI
if ($poi->checkPermalink($controller->splitted_url[1], $user->rankIsHigher("premium"))) {
+53 -7
View File
@@ -60,7 +60,6 @@ class Poi
** Checks if a page at this URL exists and return the ID
*****/
public function checkPermalink($permalink, $withArchive=0, $elementNb=0) {
global $config;
// Récupère la dernière version du POI.
$con = sql_connect();
@@ -215,7 +214,6 @@ class Poi
** Create a new poi
*****/
public function insert() {
global $config;
global $user;
// Création d'un nouveau POI.
@@ -284,7 +282,6 @@ class Poi
** Edit a POI by archiving the current version and inserting a new one
*****/
public function update() {
global $config;
global $user;
// Vérifie que les identifiants sont chargés.
@@ -345,7 +342,6 @@ class Poi
** Archive a POI
*****/
public function delete() {
global $config;
global $user;
// Archivage logique du POI.
@@ -369,7 +365,6 @@ class Poi
** Restore a POI
*****/
public function restore() {
global $config;
global $user;
// Restauration d'un POI archivé.
@@ -398,7 +393,6 @@ class Pois
// Liste des POIs publiés (ou archivés si demandé).
public function listPoisBBOX($n,$s,$e,$w,$archive=0) {
global $config;
// Chargement des POIs avec leurs versions actives.
$con = sql_connect();
@@ -469,8 +463,60 @@ class Pois
}
}
public function getVectorTile($z, $x, $y)
{
$con = sql_connect();
pg_query($con, "SET jit=off");
$sql = "WITH tile AS ( SELECT
ST_TileEnvelope($1, $2, $3) AS tile_geom
),
mvtgeom AS ( SELECT CAST(contents.id AS integer) AS id,
contents.poi_type::text AS poi_type,
contents.permalink::text AS permalink,
ST_AsMVTGeom( ST_Transform(
specs.geom,
3857
),
tile.tile_geom, 4096, 64, true ) AS geom
FROM content_version_poi_specifications specs
INNER JOIN content_versions
ON specs.content_version_id = content_versions.id
INNER JOIN content_locales
ON content_versions.locale_id = content_locales.id
INNER JOIN contents
ON content_locales.content_id = contents.id
CROSS JOIN tile
WHERE contents.type = 'poi'
AND specs.geom IS NOT NULL
AND ST_Transform(specs.geom, 3857) && tile.tile_geom
)
SELECT ST_AsMVT( mvtgeom, 'pois', 4096, 'geom' )
FROM mvtgeom
WHERE geom IS NOT NULL";
$result = pg_query_params(
$con,
$sql,
[$z, $x, $y]
);
if (!$result) {
throw new \Exception(
pg_last_error($con)
);
}
$row = pg_fetch_row($result);
pg_close($con);
return pg_unescape_bytea($row[0]);
}
public function getHistory($permalink) {
global $config;
// Historique des versions d'un POI.
$con = sql_connect();