Compare commits

...

8 Commits

7 changed files with 349 additions and 154 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -61,7 +61,7 @@
<span class="icon mr-2"> <span class="icon mr-2">
<i class="fa fa-map"></i> <i class="fa fa-map"></i>
</span> </span>
Cartografia Catasto storico
</button> </button>
<button class="button is-outlined is-rounded is-link mr-4 mt-1" id="howto" title="Istruzioni"> <button class="button is-outlined is-rounded is-link mr-4 mt-1" id="howto" title="Istruzioni">
<span class="icon is-large has-text-link"> <span class="icon is-large has-text-link">
@@ -284,20 +284,6 @@
</template> </template>
<aside class="menu ml-4 mt-3" data-id="cartography-aside"> <aside class="menu ml-4 mt-3" data-id="cartography-aside">
<button title="Chiudi menu" class="delete is-pulled-right" data-action="menu#closeCartography"></button> <button title="Chiudi menu" class="delete is-pulled-right" data-action="menu#closeCartography"></button>
<ul class="menu-list">
<li>
<input type="checkbox" data-controller="layer" data-action="layer#toggleCadastral" />
Catasto Agenzia delle Entrate (particelle e fabbricati)
</li>
</ul>
<p class="menu-label is-size-5 mt-4 is-clickable" data-id="historic">
<span role="button" data-action="click->menu#toggle" data-id="historic">
Catasto storico
<span class="icon pl-2">
<i class="fa fa-chevron-right" data-menu-target="icon" data-id="historic"></i>
</span>
</span>
</p>
</aside> </aside>
</div> </div>
</div> </div>

View File

@@ -43,4 +43,21 @@ export class SiteMedia {
</div> </div>
`; `;
} }
renderReconstructions() {
return `
<div class="content has-text-centered mb-5 pb-5">
<p class="is-size-5 mt-3">Ricostruzioni 3D</p>
<div style="max-width: 70%; margin: 0 auto">
<p class="is-size-6 has-text-centered">Gallery ricostruzioni 3D</p>
<figure class="is-relative is-clickable has-text-centered" id="gallery-3d">
<img src="img/${this._siteData.filename}" width="300"/>
<div class="icon overlay is-flex is-justify-content-center is-align-items-center">
<i class="is-flex fa fa-2x fa-play-circle"></i>
</div>
</figure>
</div>
</div>
`;
}
} }

View File

@@ -5,6 +5,7 @@ import API_CONFIG from "./config.js";
import Icons from "./icons.js"; import Icons from "./icons.js";
import { SphericalPhoto } from "./components/SphericalPhoto.js"; import { SphericalPhoto } from "./components/SphericalPhoto.js";
import { GisState } from "./state.js"; import { GisState } from "./state.js";
import Options from "./layer_options.js";
const MAPBOX_TOKEN = 'pk.eyJ1Ijoibmljb3BhIiwiYSI6ImNseWNwZjJjbjFidzcya3BoYTU0bHg4NnkifQ.3036JnCXZTEMt6jVgMzVRw'; const MAPBOX_TOKEN = 'pk.eyJ1Ijoibmljb3BhIiwiYSI6ImNseWNwZjJjbjFidzcya3BoYTU0bHg4NnkifQ.3036JnCXZTEMt6jVgMzVRw';
const BASE_URL = location.href; const BASE_URL = location.href;
@@ -28,47 +29,6 @@ GIS.INIT_ZOOM = 14;
GIS.MIN_ZOOM = 11; GIS.MIN_ZOOM = 11;
GIS.MAX_ZOOM = 24; GIS.MAX_ZOOM = 24;
const optionsVincoli = {
color: '#222',
opacity: 0.8,
weight: 1,
fillColor: '#fa7861',
fillOpacity: 0.8
};
const optionsSiti = {
color: '#800040',
opacity: 1,
weight: 1.5,
fillColor: '#800040',
fillOpacity: 0.8
};
const optionsGrotta = {
color: '#205dac',
opacity: 1,
weight: 1.5,
fillColor: '#205dac',
fillOpacity: 0.8
}
const optionsPaesistici = {
color: '#222',
opacity: 1,
weight: 1.5,
fillColor: '#88d28d',
fillOpacity: 0.8
};
const optionsFabbricati = {
color: '#222',
opacity: 1,
weight: 1.5,
fillColor: '#5b5d5f',
fillOpacity: 0.8
};
const clusterOptions = {
spiderfyOnMaxZoom: false,
showCoverageOnHover: false,
disableClusteringAtZoom: 19,
};
/** /**
* Capitalize a text string * Capitalize a text string
* @todo Move to utils * @todo Move to utils
@@ -108,37 +68,36 @@ GIS.initMap = async function (mapId, zoomLevel = this.INIT_ZOOM) {
L.control.scale({imperial: false}).addTo(map); L.control.scale({imperial: false}).addTo(map);
L.control.graphicScale({fill: 'hollow', position: 'bottomright'}).addTo(map); L.control.graphicScale({fill: 'hollow', position: 'bottomright'}).addTo(map);
let layerVincoli = await this.loadGeoJSON('vincoli.geojson', optionsVincoli); let layerVincoli = await this.loadGeoJSON('vincoli.geojson', Options.constraintsArch);
let layerPaesistici = await this.loadGeoJSON('paesistici.geojson', optionsPaesistici); let layerPaesistici = await this.loadGeoJSON('paesistici.geojson', Options.constraintsLand);
let buildings = await this.loadGeoJSON('fabbricati.geojson', Options.buildings, false);
await this.addLayerGroups(map); await this.addLayerGroups(map);
await this.fetchCartographyLayers(); await this.fetchCartographyLayers();
const archeo = {
'Vincoli archeologici' : layerVincoli,
'Vincoli paesistici' : layerPaesistici,
//'Catasto storico' : historicCadastre,
};
L.control.layers(baseMap, archeo).addTo(map);
GisState.map = map;
const reprojectedWMSLayer = GIS.reprojectWMS(); const reprojectedWMSLayer = GIS.reprojectWMS();
const wmsLayer = new reprojectedWMSLayer( const wmsLayer = new reprojectedWMSLayer(
'https://wms.cartografia.agenziaentrate.gov.it/inspire/wms/ows01.php?', 'https://wms.cartografia.agenziaentrate.gov.it/inspire/wms/ows01.php?',
{ {
layers: 'CP.CadastralParcel,fabbricati', layers: 'CP.CadastralParcel,codice_plla,fabbricati',
transparent: true, transparent: true,
format: 'image/png', format: 'image/png',
version: '1.1.1', version: '1.1.1',
minZoom: 15, minZoom: this.INIT_ZOOM,
maxZoom: this.MAX_ZOOM, maxZoom: this.MAX_ZOOM,
tileSize: 1024, tileSize: 1024,
opacity: 0.6, opacity: 0.6,
} }
); );
const cartography = {
'Catasto Agenzia delle Entrate (zoom per visualizzare)' : wmsLayer,
'Fabbricati' : buildings,
'Vincoli archeologici' : layerVincoli,
'Vincoli archeologici indiretti' : layerPaesistici,
};
L.control.layers(baseMap, cartography).addTo(map);
GisState.cartography.cadastral = wmsLayer; GisState.map = map;
return map; return map;
} }
@@ -211,15 +170,20 @@ GIS.sites = async function () {
let sitesData = await fetch(`${API_URL}/sites`) let sitesData = await fetch(`${API_URL}/sites`)
.then(data => data.json()); .then(data => data.json());
let sites = L.markerClusterGroup(clusterOptions); let sites = L.markerClusterGroup(Options.cluster);
let geom = []; let geom = [];
for (let record of sitesData) { for (let record of sitesData) {
if (record.geojson) { if (record.geojson) {
const options = record.gisId === 'grotta_azzurra' ? const options = record.gisId === 'grotta_azzurra' ?
optionsGrotta : optionsSiti; Options.grotta : Options.site;
geom.push(await this.loadSiteLayer(record, options)); geom.push(await this.loadSiteLayer(record, options));
} }
if (record.area) {
const options = record.gisId === 'villa_bismarck' ?
Options.bismarck : Options.site;
geom.push(await this.loadSiteLayer(record, options, false, true));
}
const marker = L.marker( const marker = L.marker(
record.coordinates, record.coordinates,
@@ -251,7 +215,7 @@ GIS.notConserved = async function () {
let notConserData = await fetch(`${API_URL}/not_conserved`) let notConserData = await fetch(`${API_URL}/not_conserved`)
.then(data => data.json()); .then(data => data.json());
let notConserved = L.markerClusterGroup(clusterOptions); let notConserved = L.markerClusterGroup(Options.cluster);
for (let record of notConserData.records) { for (let record of notConserData.records) {
const marker = L.marker( const marker = L.marker(
@@ -281,7 +245,7 @@ GIS.findings = async function () {
.then(data => data.json()); .then(data => data.json());
let findings = L.markerClusterGroup( let findings = L.markerClusterGroup(
clusterOptions Options.cluster
); );
for (let record of findingsData) { for (let record of findingsData) {
@@ -313,7 +277,7 @@ GIS.prehistoric = async function () {
.then(data => data.json()); .then(data => data.json());
let prehistoric = L.markerClusterGroup( let prehistoric = L.markerClusterGroup(
clusterOptions Options.cluster
); );
for (let record of data.records) { for (let record of data.records) {
@@ -345,7 +309,7 @@ GIS.underwater = async function () {
let underwaterData = await fetch(`${API_URL}/underwater`) let underwaterData = await fetch(`${API_URL}/underwater`)
.then(data => data.json()); .then(data => data.json());
let underwater = L.markerClusterGroup(clusterOptions); let underwater = L.markerClusterGroup(Options.cluster);
for (let record of underwaterData.records) { for (let record of underwaterData.records) {
const marker = L.marker( const marker = L.marker(
@@ -370,7 +334,6 @@ GIS.underwater = async function () {
/** /**
* Adds layers to map and returns an object * Adds layers to map and returns an object
* with {baseMap, archeoLayers, sitesLayerGroup} * with {baseMap, archeoLayers, sitesLayerGroup}
* @todo Load areas for sites that have them!!
* @param {L.Map} map * @param {L.Map} map
* @returns {{baseMap: {"OpenStreetMap": L.TileLayer}}} * @returns {{baseMap: {"OpenStreetMap": L.TileLayer}}}
*/ */
@@ -389,16 +352,15 @@ GIS.initLayers = async function(map) {
maxZoom: GIS.MAX_ZOOM, maxZoom: GIS.MAX_ZOOM,
attribution: '&copy; Mapbox' attribution: '&copy; Mapbox'
}); });
let boundaries = await this.loadGeoJSON('confini.geojson', {}, false); let boundaries = await this.loadGeoJSON('confini.geojson', {}, false);
let buildings = await this.loadGeoJSON('fabbricati.geojson', optionsFabbricati, false);
let baseCatasto = new L.LayerGroup([buildings, boundaries]);
const baseGroup = new L.LayerGroup([osmap]); const baseGroup = new L.LayerGroup([osmap]);
baseGroup.addTo(map); baseGroup.addTo(map);
const baseMap = { const baseMap = {
"OpenStreetMap" : osmap, "OpenStreetMap" : osmap,
"Satellite" : mapbox, "Satellite" : mapbox,
"Cartografia catastale" : baseCatasto, 'Limiti amministrativi' : boundaries,
}; };
return baseMap; return baseMap;
@@ -479,9 +441,10 @@ GIS.loadGeoJSON = async function (geoJSON, options, popup = true) {
* @param {boolean} popup Should the features have a popup? * @param {boolean} popup Should the features have a popup?
* @returns {L.Layer} * @returns {L.Layer}
*/ */
GIS.loadSiteLayer = async function (site, options, popup = true) { GIS.loadSiteLayer = async function (site, options, popup = true, area = false) {
const geoJSON = `${site.gisId}.geojson`; let geoJSON = site.gisId;
const geo = await fetch(`${BASE_URL}/geojson/${geoJSON}`) geoJSON += area ? '_area.geojson' : '.geojson';
const geo = await fetch(`${BASE_URL}geojson/${geoJSON}`)
.then(res => res.json()) .then(res => res.json())
.catch(error => console.error(`Can't load layer ${geoJSON}. Reason: ${error}`)); .catch(error => console.error(`Can't load layer ${geoJSON}. Reason: ${error}`));
@@ -560,11 +523,13 @@ GIS.cacheDBData = async function (layerId, dbId) {
GIS.featurePopup = function (layerName, feature) { GIS.featurePopup = function (layerName, feature) {
const html = ` const html = `
<table class="table is-striped is-size-6 m-2"> <table class="table is-striped is-size-6 m-2">
<tr><th>Oggetto</th><td>${feature.properties.OGGETTO}</td></tr> <tr><th>Oggetto</th><td>${feature.properties.OGGETTO ?? 'n.d.'}</td></tr>
<tr><th>Anno</th><td>${feature.properties.ANNO}</td></tr> <tr><th>Anno</th><td>${feature.properties.ANNO}</td></tr>
<tr><th>Comune</th><td>${capitalize(feature.properties.COMUNE)}</td></tr> <tr><th>Comune</th><td>${capitalize(feature.properties.COMUNE)}</td></tr>
<tr><th>Località</th><td>${capitalize(feature.properties.LOCALITA)}</td></tr> <tr><th>Località</th><td>${capitalize(feature.properties.LOCALITA) ?? 'n.d.'}</td></tr>
<tr><th>Proprietà</th><td>${capitalize(feature.properties.PROPRIETA)}</td></tr> <tr><th>Proprietà</th><td>${capitalize(feature.properties.PROPRIETA)}</td></tr>
<tr><th>Foglio</th><td>${feature.properties.FOGLIO}</td></tr>
<tr><th>Particella</th><td>${feature.properties.PART_BIS}</td></tr>
</table> </table>
`; `;
const content = { const content = {
@@ -586,10 +551,8 @@ GIS.reprojectWMS = function (crs = 'EPSG:4258') {
const reprojectedWMSLayer = L.TileLayer.WMS.extend({ const reprojectedWMSLayer = L.TileLayer.WMS.extend({
getTileUrl(tilePoint) { getTileUrl(tilePoint) {
const map = GisState.map; const map = GisState.map;
//const crs = map.options.crs;
const tileSize = this.getTileSize(); const tileSize = this.getTileSize();
//const geoPoint = L.point(tilePoint.x, tilePoint.y);
const nwPoint = L.point( const nwPoint = L.point(
tilePoint.x * tileSize.x, tilePoint.x * tileSize.x,
tilePoint.y * tileSize.y, tilePoint.y * tileSize.y,

View File

@@ -0,0 +1,54 @@
/**
* @namespace Options
*/
let Options = {};
Options.constraintsArch = {
color: '#222',
opacity: 0.8,
weight: 1,
fillColor: '#fa7861',
fillOpacity: 0.8
};
Options.site = {
color: '#800040',
opacity: 1,
weight: 1.5,
fillColor: '#800040',
fillOpacity: 0.8
};
Options.grotta = {
color: '#205dac',
opacity: 1,
weight: 1.5,
fillColor: '#205dac',
fillOpacity: 0.8
}
Options.bismarck = {
color: '#a4a79a',
opacity: 1,
weight: 1.5,
fillColor: '#a4a79a',
fillOpacity: 0.8
}
Options.constraintsLand = {
color: '#222',
opacity: 1,
weight: 1.5,
fillColor: '#88d28d',
fillOpacity: 0.8
};
Options.buildings = {
color: '#222',
opacity: 1,
weight: 1.5,
fillColor: '#5b5d5f',
fillOpacity: 0.8
};
Options.cluster = {
spiderfyOnMaxZoom: false,
showCoverageOnHover: false,
disableClusteringAtZoom: 19,
};
export default Options;

View File

@@ -100,8 +100,14 @@ UI.openSiteModal = function (data, selector) {
let surveys = data.images.filter(i => i.type === 'Survey'); let surveys = data.images.filter(i => i.type === 'Survey');
let photos = data.images.filter(i => i.type === 'Photo'); let photos = data.images.filter(i => i.type === 'Photo');
let videos = data.images.filter(i => i.type === 'Video'); let videos = data.images.filter(i => i.type === 'Video');
let reconstructions = data.images.filter(i => i.type === 'Reconstruction');
if (surveys.length === 0 && photos.length === 0 && videos.length === 0) { const noMedia = surveys.length === 0
&& photos.length === 0
&& reconstructions.length === 0
&& videos.length === 0;
if (noMedia) {
images.innerHTML = '<p class="has-text-centered">Nessuna risorsa visuale disponibile</p>'; images.innerHTML = '<p class="has-text-centered">Nessuna risorsa visuale disponibile</p>';
} }
@@ -114,6 +120,9 @@ UI.openSiteModal = function (data, selector) {
siteMedia.siteData = photos[0] ?? undefined; siteMedia.siteData = photos[0] ?? undefined;
images.innerHTML += photos[0] ? siteMedia.renderPhotos() : ''; images.innerHTML += photos[0] ? siteMedia.renderPhotos() : '';
siteMedia.siteData = reconstructions[0] ?? undefined;
images.innerHTML += reconstructions[0] ? siteMedia.renderReconstructions() : '';
siteMedia.siteData = videos[0] ?? undefined; siteMedia.siteData = videos[0] ?? undefined;
images.innerHTML += videos[0] ? siteMedia.renderVideos() : ''; images.innerHTML += videos[0] ? siteMedia.renderVideos() : '';
} }
@@ -122,6 +131,7 @@ UI.openSiteModal = function (data, selector) {
this.imageGallery('gallery-1', surveys); this.imageGallery('gallery-1', surveys);
this.imageGallery('gallery-2', photos); this.imageGallery('gallery-2', photos);
this.imageGallery('gallery-3d', reconstructions);
this.imageGallery('gallery-video', videos, true); this.imageGallery('gallery-video', videos, true);
} }
/** /**