CEREMA MRN CPL
  • Accueil
  • Questionnaire trouver votre catégorie
  • Fiches
    • 01-Immeuble ou maison en pan de bois
    • 02-Immeuble ou maison en brique enduite
    • 03-Immeuble de rapport ou maison en pierre
    • 04-Immeuble ou maison en brique manufacturée d’avant-guerre
    • 05-Villa Néo-normande et régionalisme
    • 06-Constructions des années 1920-1930 et Art Déco
    • 07-Reconstruction
    • 08-Tours, barres et plots
    • 09-Pavillon moderniste des années 1960-1974
    • 10-Immeubles et tours post-modernes (1974-2000)
    • 11-Pavillon des premières réglementations thermiques (1974-2000)
    • 12-Immeubles contemporains (après 2000)
    • 13-Pavillon contemporain (après 2000)
  • Conseils et accompagnement
  • Carte
  • Annexes
    • Glossaire
    • Méthodologie

Contact : pour un accompagnement personnalisé pour rénover votre bien, prenez rdv avec Énergies Métropole : 📞 02 76 30 32 32 🔗 https://energies.metropole-rouen-normandie.fr/nous-contacter/

Carte interactive
  • Carte
  • Précaution de lecture
  • Mode d’emploi
mutable myId='';
mutable myTup={};
// A FAIRE
// idée garder juste les colonnes du pop up puis fabriquer une colonne avec un json
// ce json mutable sera ensuite exploité dans la partie texte !

myMap = {
  const entete = document.getElementById('quarto-header');
  const headerHeight = entete ? entete.getBoundingClientRect().height : 0;
  const availableHeight = window.innerHeight - headerHeight - 120; // forfait de 40px pour prendre de la marge

  const container = html`<div style="width: 100%; height: ${availableHeight}px; margin: 0; padding: 0;">`;
  // on définit le container de la carte et on l'attend  , on mettant fill: false la card prend la taille de la map et en réglant le height en vh en tatonnant on trouve la bonne proportion
  //const container = html`<div style="width:100%; height:55vh; margin:0; padding:0;">`;
  
  yield container; // comme un return mais ça continue le code qui suit

    // add the PMTiles plugin to the maplibregl global.
    const protocol = new pmtiles.Protocol();
    maplibregl.addProtocol('pmtiles', (request) => {
        return new Promise((resolve, reject) => {
            const callback = (err, data) => {
                if (err) {
                    reject(err);
                } else {
                    resolve({data});
                }
            };
            protocol.tile(request, callback);
        });
    });
    //const PMTILES_URL_B1 = 'https://guillaumechretiencerema.github.io/mydatas/recoquartiers/bat_48_58.pmtiles?raw=true';
    //const PMTILES_URL_B1 = 'http://162.19.124.68/recoquartiers/0-pmtiles/bat_48_58.pmtiles';
    const PMTILES_URL_B1 = `${LAYERS_PATH}/batiments_groupes_cpl_detail.pmtiles`;
    const b1 = new pmtiles.PMTiles(PMTILES_URL_B1);
    protocol.add(b1);

    const PMTILES_URL_C =`${LAYERS_PATH}/communes.pmtiles`;
    const c = new pmtiles.PMTiles(PMTILES_URL_C);
    protocol.add(c);

    const PMTILES_URL_TUPS =`${LAYERS_PATH}/tache_tups_cat_regroupee_descohre.pmtiles`;
    const tups = new pmtiles.PMTiles(PMTILES_URL_TUPS);
    protocol.add(tups);

    const PMTILES_URL_ENSBH =`${LAYERS_PATH}/ens_bati_meme_categorie.pmtiles`;
    const ensbh = new pmtiles.PMTiles(PMTILES_URL_ENSBH);
    protocol.add(ensbh);

    const sourceOrtho = {style:'normal', format:'image/jpeg',layer:'HR.ORTHOIMAGERY.ORTHOPHOTOS'};
    const sourcePlanIGN = {style:'normal', format:'image/png',layer:'GEOGRAPHICALGRIDSYSTEMS.PLANIGNV2'};
    const sourceHillShade = {style:'estompage_grayscale',format:'image/png',layer:'ELEVATION.ELEVATIONGRIDCOVERAGE.SHADOW'};

  const map = new maplibregl.Map({
    container,
    center: [1.0920, 49.4381],
            zoom: 9,
            pitch: 0,
            maxPitch: 75,
            style: {
                version: 8,
                // glyph nécessaires pour les text dans les symbol...
                glyphs: "https://demotiles.maplibre.org/font/{fontstack}/{range}.pbf",
                sources: {
                    'raster-planign': {
                        type: 'raster',
                        //'tiles': ['https://tile.openstreetmap.org/{z}/{x}/{y}.png'],
                        tiles: [
                           `https://data.geopf.fr/wmts?SERVICE=WMTS&style=${sourcePlanIGN.style}&VERSION=1.0.0&REQUEST=GetTile&format=${sourcePlanIGN.format}&layer=${sourcePlanIGN.layer}&tilematrixset=PM&TileMatrix={z}&TileCol={x}&TileRow={y}`
                        ],
                        tileSize: 256,
                        attribution: '© <a href="https://www.ign.fr/">IGN</a>',
                        minzoom: 0,
                        maxzoom: 22
                    },
                    'raster-ortho': {
                        type: 'raster',
                        //'tiles': ['https://tile.openstreetmap.org/{z}/{x}/{y}.png'],
                        tiles: [
                            `https://data.geopf.fr/wmts?SERVICE=WMTS&style=${sourceOrtho.style}&VERSION=1.0.0&REQUEST=GetTile&format=${sourceOrtho.format}&layer=${sourceOrtho.layer}&tilematrixset=PM&TileMatrix={z}&TileCol={x}&TileRow={y}`
                        ],
                        tileSize: 256,
                        attribution: '© <a href="https://www.ign.fr/">IGN</a>',
                        minzoom: 0,
                        maxzoom: 22
                    },
                    'hillshadeSource': {
                        type: 'raster',
                        //'tiles': ['https://tile.openstreetmap.org/{z}/{x}/{y}.png'],
                        tiles: [
                            `https://data.geopf.fr/wmts?SERVICE=WMTS&style=${sourceHillShade.style}&VERSION=1.0.0&REQUEST=GetTile&format=${sourceHillShade.format}&layer=${sourceHillShade.layer}&tilematrixset=PM&TileMatrix={z}&TileCol={x}&TileRow={y}`
                        ],
                        tileSize: 256,
                        attribution: '© <a href="https://www.ign.fr/">IGN</a>',
                        minzoom: 0,
                        maxzoom: 22
                    },
                    'source_c': {
                        type: 'vector',
                        url: `pmtiles://${PMTILES_URL_C}`
                    },
                    'source_b1': {
                        type: 'vector',
                        url: `pmtiles://${PMTILES_URL_B1}`
                    },
                    'source_tups': {
                        type: 'vector',
                        url: `pmtiles://${PMTILES_URL_TUPS}`
                    },
                    'source_ensbh': {
                        type: 'vector',
                        url: `pmtiles://${PMTILES_URL_ENSBH}`
                    }
                },
                layers: [ 
                    // PLAN IGN
                    {
                        id: 'raster-planign',
                        type: 'raster',
                        source: 'raster-planign',
                        layout: {
                            // Make the layer visible by default.
                            visibility: 'visible' //ou none
                        },
                    },
                    // ORTHOPHOTO
                    {
                        id: 'raster-ortho',
                        type: 'raster',
                        source: 'raster-ortho',
                        layout: {
                            // Make the layer visible by default.
                            visibility: 'none' //ou none
                        },
                    },
                    // OMBRES
                    {
                        id: 'hillshadeSource',
                        type: 'raster',
                        source: 'hillshadeSource',
                        layout: {
                            // Make the layer visible by default.
                            visibility: 'visible' //ou none
                        },
                    },
                    // COMMUNES
                    {
                        id: "communes",
                        source: "source_c",
                        'source-layer': "communes",
                        type: "line", 
                        paint: {
                            'line-color': 'white',
                            'line-width': 2
                        }
                    },
                    // ASTUCE POUR LE BATIMENT SELECTIONNE
                    { 
                        id: "selectedB",
                        source: "source_b1",
                        'source-layer': 'batiments_groupes_cpl_detail',
                        /*type: "line",
                        layout: {
                            "line-join": "round",
                            "line-cap": "round"
                        },
                        paint: {
                            "line-color": "yellow",
                            "line-width": 8
                        },*/
                        type: "fill-extrusion", // Changer le type de couche en "fill-extrusion"
                        paint: {                            
                            "fill-extrusion-color": "yellow", // Couleur de remplissage extrudée
                            "fill-extrusion-height": ["get", "bdtopo_bat_hauteur_mean"], // Propriété de hauteur à utiliser pour extruder les polygones
                            "fill-extrusion-base": 0, // Hauteur de base de l'extrusion
                            "fill-extrusion-opacity": 0.7
                        },
                        filter: ["==", "batiment_groupe_id", 'bdnb-bg-1112-ULAV-CYVN'] // Filtre initial vide
                    },
                    // TUPS AGREGEES PROPRIO
                    {
                        id: 'tups_agreges',
                        source: 'source_tups',
                        'source-layer': 'tache_tups_cat_regroupee_descohre',
                        type: "fill", // Changer le type de couche en "fill-extrusion"
                        paint: {
                            "fill-color": [
                                'match',
                                /*['get', 'methode'], 
                                // Définissez une couleur par défaut si nécessaire :
                                '#808080' // Couleur grise par défaut pour les valeurs non spécifiées*/
                                ['get', 'id_group_cat'], 
                                "01-02-03","#B34D42",
                                "04","#D99058",
                                "05-06","#4682B4",
                                "07","#D2AE53",
                                "08","#A9A9A9",
                                "09","#D19896",
                                "10","#89666B",
                                "11","#996699",
                                "12","#3C6971",
                                "13","#9BB4D5",
                                "14","#96A87E",
                                "white" // couleur si ça match pas
                            ],      
                            "fill-opacity": 0.7
                        }
                    },
                    // BATIMENTS GROUPE DETAIL AVEC COULEUR SELON PROPRIO
                    {
                        id: 'batiments_groupes_cpl_detail',
                        source: 'source_b1',
                        'source-layer': 'batiments_groupes_cpl_detail',
                        type: "fill-extrusion", // Changer le type de couche en "fill-extrusion"
                        paint: {                            
                            //"fill-extrusion-color": "purple", // Couleur de remplissage extrudée
                            
                            "fill-extrusion-color": [
                                'match',
                                ['get', 'id_cat_pat'], 
                                "01","#795548",
                                "02","#B34D42",
                                "03","#DEB887",
                                "04","#D99058",
                                "05","#6b8e23",
                                "06","#4682B4",
                                "07","#D2AE53",
                                "08","#A9A9A9",
                                "09","#D19896",
                                "10","#89666B",
                                "11","#996699",
                                "12","#3C6971",
                                "13","#9BB4D5",
                                "14","#96A87E",
                                "white" // couleur si ça match pas
                            ],
                            
                            
                            
                            "fill-extrusion-height": ["get", "bdtopo_bat_hauteur_mean"], // Propriété de hauteur à utiliser pour extruder les polygones
                            "fill-extrusion-base": 0, // Hauteur de base de l'extrusion
                            "fill-extrusion-opacity": 1
                        }
                    },
                    // ENS BATI MEME CAT
                    {
                        id: "ens_bati_homo",
                        source: "source_ensbh",
                        'source-layer': "ens_bati_meme_categorie",
                        type: "line", 
                        paint: {
                            'line-color': 'yellow',
                            'line-width': 1
                        }
                    },
                ]
            }
  });

  //------------------------------------------------------------------------------------------------      
  map.addControl(new maplibregl.NavigationControl(
    {
      visualizePitch: true,
      //showZoom: true,
      //showCompass: true
    }), 
    'top-left'
  );
  
  map.addControl(new maplibregl.FullscreenControl()), 'top-right';

  const scale = new maplibregl.ScaleControl({
    maxWidth: 80,
    unit: 'metric'
  });
  map.addControl(scale);


  //------------------------------------------------------------------------------------------------      
  map.on('click', 'batiments_groupes_cpl_detail', (e) => {
    // Center the map on the coordinates of any clicked symbol from the 'symbols' layer.
    const centroid = turf.centroid(e.features[0].geometry);
    map.flyTo({
        center: centroid.geometry.coordinates,
        zoom: 17,
        pitch: 45
    });
    
    // POP UP on click
    new maplibregl.Popup()
        .setLngLat(e.lngLat)
        .setHTML(`Batiment(s groupés) n°${e.features[0].properties.batiment_groupe_id} <br>
                  Catégorie la plus probable : ${e.features[0].properties.categorie_calculee}
                `)
        .addTo(map);
    mutable myId = e.features[0].properties.idtup;
    mutable myTup = e.features[0].properties;
    
    // test highlight NEW !
    // Mettre à jour le filtre de la couche de surbrillance pour montrer uniquement l'élément cliqué
    map.setFilter('selectedB', ['==', 'batiment_groupe_id', e.features[0].properties.batiment_groupe_id]);
    // et l'inverse pour les bâtiments non sélectionné
    map.setFilter('batiments_groupes_cpl_detail', ['!=', 'batiment_groupe_id', e.features[0].properties.batiment_groupe_id]);

  });
  
  //------------------------------------------------------------------------------------------------      
  // Change the cursor to a pointer when the it enters a feature in the 'symbols' layer.
  map.on('mouseenter', 'batiments_groupes_cpl_detail', () => {
      map.getCanvas().style.cursor = 'pointer';
  });

  // Change it back to a pointer when it leaves.
  map.on('mouseleave', 'batiments_groupes_cpl_detail', () => {
      map.getCanvas().style.cursor = '';
  });

  //------------------------------------------------------------------------------------------------      
  const mySelectCommune = document.getElementById('mySelectCommune');
  mySelectCommune.addEventListener('change', () => {
      map.fitBounds( JSON.parse(mySelectCommune.value) );
  });
  
  //------------------------------------------------------------------------------------------------      
  // pris sur un exemple, permet de refaire un coup de propre
  invalidation.then(() => map.remove());
  
  
  //------------------------------------------------------------------------------------------------
  // TEST API ADRESSE GOUV FR cf header pour les lib css et js et exemple pris sur
  // https://github.com/webgeodatavore/photon-geocoder-autocomplete/blob/master/demo/photon-demo-maplibre.js
  function AddDomControl(dom) {
    this._dom = dom;
  }
  
  AddDomControl.prototype.onAdd = function (map) {
    this._map = map;
    this._container = document.createElement("div");
    this._container.className = "maplibregl-ctrl photon-geocoder-autocomplete";
    this._container.appendChild(this._dom);
    return this._container;
  };
  
  AddDomControl.prototype.onRemove = function () {
    this._container.parentNode.removeChild(this._container);
    this._map = undefined;
  };
  
  // Format result in the search input autocomplete
  var formatResult = function (feature, el) {
    var title = document.createElement("strong");
    el.appendChild(title);
    var detailsContainer = document.createElement("small");
    el.appendChild(detailsContainer);
    var details = [];
    title.innerHTML = feature.properties.label || feature.properties.name;
    var types = {
      housenumber: "numéro",
      street: "rue",
      locality: "lieu-dit",
      municipality: "commune",
    };
    if (types[feature.properties.type]) {
      var spanType = document.createElement("span");
      spanType.className = "type";
      title.appendChild(spanType);
      spanType.innerHTML = types[feature.properties.type];
    }
    if (
      feature.properties.city &&
      feature.properties.city !== feature.properties.name
    ) {
      details.push(feature.properties.city);
    }
    if (feature.properties.context) {
      details.push(feature.properties.context);
    }
    detailsContainer.innerHTML = details.join(", ");
  };
  
  // Function to show you can do something with the returned elements
  function myHandler(featureCollection) {
    console.log(featureCollection);
  }
  
  // We reused the default function to center and zoom on selected feature.
  // You can make your own. For instance, you could center, zoom
  // and add a point on the map
  function onSelected(feature) {
    console.log(feature);
    map.setCenter(feature.geometry.coordinates);
    map.setZoom(16);
  }
  
  // URL for API
  var API_URL = "//api-adresse.data.gouv.fr";
  
  // Create search by adresses component
  var searchCcontainer = new Photon.Search({
    resultsHandler: myHandler,
    onSelected: onSelected,
    placeholder: "Tapez une adresse",
    formatResult: formatResult,
    url: API_URL + "/search/?",
    feedbackEmail: null,
  });
  
  map.addControl(new AddDomControl(searchCcontainer), "bottom-left");
  //------------------------------------------------------------------------------------------------
  // Ebauche de menu sur mesure

  const mapMenuDiv = document.createElement('div');
  mapMenuDiv.classList.add('mapFondDePlan');
  //mapMenuDiv.innerHTML = '<strong>Fond de plan :</strong>';
  map.getContainer().appendChild(mapMenuDiv);
  // Ajouter un style pour le z-index

  mapMenuDiv.style.position = 'absolute'; // new
  mapMenuDiv.style.zIndex = '1000'; // new


  /*const customDivHTML = `
    <div>
        <label for="orthoCheckbox">Orthophoto</label>
        <input type="checkbox" id="orthoCheckbox" unchecked>
    </div>
  `;*/
  const customDivHTML = `
          <strong>Fond de plan :</strong>
          <div class="form-check form-switch">
              <input class="form-check-input" type="checkbox" role="switch" id="orthoCheckbox">
              <label class="form-check-label" for="orthoCheckbox">Photos aériennes</label>
          </div>                    
      `;
  mapMenuDiv.innerHTML += customDivHTML;

  // doc à creuser
  // https://docs.mapbox.com/mapbox-gl-js/example/toggle-layers/
  document.getElementById('orthoCheckbox').addEventListener('change', function (e) {
      e.preventDefault();
      e.stopPropagation();

      const valeurCheckbox = document.getElementById('orthoCheckbox').checked;
      if (valeurCheckbox) {
          map.setLayoutProperty('raster-ortho', 'visibility', 'visible');
          map.setLayoutProperty('raster-planign', 'visibility', 'none');
      } else {
          map.setLayoutProperty('raster-ortho', 'visibility', 'none');
          map.setLayoutProperty('raster-planign', 'visibility', 'visible');
      }
  });

  // Brouillon pour ajouter mon menu layer !
  const mapLayersDiv = document.createElement('div');
  mapLayersDiv.classList.add('mapLayers');
  //mapMenuDiv.innerHTML = '<strong>Fond de plan :</strong>';
  map.getContainer().appendChild(mapLayersDiv);
  // Ajouter un style pour le z-index

  mapLayersDiv.style.position = 'absolute'; // new
  mapLayersDiv.style.zIndex = '1000'; // new
  const customDivHTML_2 = `
          <button id="toggleMapMenuButton" class="btn btn-light">
              <img src="images/icons/layers-half.svg" alt="Icône SVG" width="25" height="25">
          </button>                    
          <div id="layersList" ></div>
          `
  mapLayersDiv.innerHTML += customDivHTML_2;

  const toggleableLayerIds= [
      "communes",
      "batiments_groupes_cpl_detail",
      "tups_agreges",
      "ens_bati_homo"
      ];

  const aliasLayerIds = {
      "communes":"Communes",
      "batiments_groupes_cpl_detail":"Bâtiments",
      "tups_agreges":"Parcelles",
      "ens_bati_homo":"Ensembles bâtis homogènes"
  };

  // https://docs.mapbox.com/mapbox-gl-js/example/toggle-layers/
  // Set up the corresponding toggle button for each layer.                
  for (const id of toggleableLayerIds) {
      // Skip layers that already have a button set up.
      if (document.getElementById(id)) {
          continue;
      }

      // Create a link.
      const link = document.createElement('a');
      link.id = id;
      link.href = '#';
      //link.textContent = id;
      link.textContent = aliasLayerIds[id] || id;
      link.className = 'active';

      // Show or hide layer when the toggle is clicked.
      link.onclick = function (e) {
          const clickedLayer = this.id;
          e.preventDefault();
          e.stopPropagation();

          const visibility = map.getLayoutProperty(
              clickedLayer,
              'visibility'
          ) || 'visible';
          // NB : je rajoute ou visible car la première c'est undefined ? ? ?
          // Toggle layer visibility by changing the layout object's visibility property.
          if (visibility === 'visible') {
              map.setLayoutProperty(clickedLayer, 'visibility', 'none');
              this.className = '';
          } else {
              this.className = 'active';
              map.setLayoutProperty(
                  clickedLayer,
                  'visibility',
                  'visible'
              );
          }
      };

      const layers = document.getElementById('layersList');
      layers.appendChild(link);
  }

}

Limite : logement dans lieu de culte : bâtiment forme complexe qui renvoie facilement vers villa néonormande alors que non. Pareil pour les logements de fonction dans les usines ou les gros bâtiments tertiaires (écoles, etc.)

Incliner et faire tourner la carte
Maintenez enfoncé le bouton droit de la souris et déplacez la pour incliner le point de vue ou faire tourner la carte.

Sélectionner un bâtiment (ou un ensemble groupés)
Cliquez sur un bâtiment (bouton gauche de la souris) pour en visualiser les informations. Lorsque les informations ne sont pas disponible pour un seul bâtiment, c’est un ensemble de bâtiments qui sera sélectionné.

locale = d3.formatLocale({
  decimal: ",",    // Virgule pour les décimales
  thousands: " ",  // Espace pour le séparateur de milliers
  grouping: [3],   // Groupement par 3 chiffres nombre)
});
formatter = locale.format(",.0f")
bbox_communes = FileAttachment("data/bbox_communes.json").json()
html`
<div>
    <label for="mySelectCommune">Communes :</label>
    <select id="mySelectCommune">
      <option value="" disabled selected hidden>Choisir une commune</option>
    </select>
</div>
`
html`<div style="font-size:14px">
        <div style="margin-bottom:3px;"><strong>Catégorie de patrimoine la plus probable</strong></div>

        <div style="border: 2px solid #B34D42; border-radius:10px; padding:10px;">
  
            <span class="badge" style="background:#795548;opacity:1">    </span> 01-Immeuble ou maison en pan de bois<br>
            <span class="badge" style="background:#B34D42;opacity:1">    </span> 02-Immeuble ou maison en brique classique enduite<br>
            <span class="badge" style="background:#DEB887;opacity:1">    </span> 03-Immeuble de rapport ou maison en pierre<br>
        </div>
        <span class="badge" style="background:#D99058;opacity:1">    </span> 04-Immeuble ou maison en brique manufacturée d’avant-guerre<br>
        
        <div style="border: 2px solid #4682B4; border-radius:10px; padding:10px;">
            <span class="badge" style="background:#6b8e23;opacity:1">    </span> 05-Villa Néo-normande ou Art Nouveau<br>
            <span class="badge" style="background:#4682B4;opacity:1">    </span> 06-Immeuble ou maison des années 1920-1930 ou Art déco<br>
          
        </div>
        <span class="badge" style="background:#D2AE53;opacity:1">    </span> 07-Reconstruction<br>
        <span class="badge" style="background:#A9A9A9;opacity:1">    </span> 08-Tour, barre ou plot<br>
        <span class="badge" style="background:#D19896;opacity:1">    </span> 09-Pavillon moderniste des années 1960-1970<br>
        <span class="badge" style="background:#89666B;opacity:1">    </span> 10-Immeuble ou tour post-moderne (1974-2000)<br>
        <span class="badge" style="background:#996699;opacity:1">    </span> 11-Pavillon des premières réglementations thermiques (1974-2000)<br>
        <span class="badge" style="background:#3C6971;opacity:1">    </span> 12-Immeuble contemporain (après 2000)<br>
        <span class="badge" style="background:"9BB4D5";opacity:1">    </span> 13-Pavillon contemporain (après 2000)<br>
        <span class="badge" style="background:#96A87E;opacity:1">    </span> 14-Construction provisoire / autre<br>
        <span class="badge" style="background:lightgrey;opacity:0.25">    </span> Non classé<br>

        <span class="badge" style="background:yellow;opacity:1">    </span> Ensemble de bâtis de même catégorie<br>

        <br>

     </div>
`
// un peu de js pur !
{
  const selectElement = document.getElementById("mySelectCommune");
  bbox_communes.forEach(item => {
    const option = document.createElement("option");
    option.value = item.value;
    option.text = item.text;
    selectElement.appendChild(option);
  });
}

©Cerema ©Métropole Rouen Normandie