| Current Path : /home/atelierpru/www/airvalue/_astro/ |
| Current File : /home/atelierpru/www/airvalue/_astro/mvp-run.Dpx6IwID.js |
var e=110540,t=111320;function n(e){let t=0;for(let n=0;n<e.length-1;n++)t+=e[n][0]*e[n+1][1]-e[n+1][0]*e[n][1];return Math.abs(t/2)}function r(e){return e?e.type===`Polygon`?e.coordinates[0]||null:e.type===`MultiPolygon`&&e.coordinates.map(e=>e[0]||[]).sort((e,t)=>n(t)-n(e))[0]||null:null}function i(n){let i=n&&n.type===`MultiPolygon`?n.coordinates.map(e=>({type:`Polygon`,coordinates:e})):[n],a=0;for(let n of i){let i=r(n);if(!i||i.length<4)continue;let o=i[0][1],s=t*Math.cos(o*Math.PI/180),c=0;for(let t=0;t<i.length-1;t++){let[n,r]=i[t],[a,o]=i[t+1];c+=n*s*(o*e)-a*s*(r*e)}a+=Math.abs(c/2)}return Math.round(a*10)/10}function a(e,t){if(!t)return!1;let n=t=>{let n=!1;for(let r=0,i=t.length-1;r<t.length;i=r++){let[a,o]=t[r],[s,c]=t[i];o>e[1]!=c>e[1]&&e[0]<(s-a)*(e[1]-o)/(c-o)+a&&(n=!n)}return n};return t.type===`Polygon`?n(t.coordinates[0]||[]):t.type===`MultiPolygon`?t.coordinates.some(e=>n(e[0]||[])):!1}function o(e){let t=r(e);if(!t||!t.length)return null;let n=0,i=0,a=0;for(let e=0;e<t.length-1;e++){let[r,o]=t[e],[s,c]=t[e+1],l=r*c-s*o;n+=l,i+=(r+s)*l,a+=(o+c)*l}if(Math.abs(n)>1e-14)return[i/(3*n),a/(3*n)];let o=t.length>1&&t[0][0]===t[t.length-1][0]&&t[0][1]===t[t.length-1][1]?t.slice(0,-1):t,s=0,c=0;for(let[e,t]of o)s+=e,c+=t;return[s/o.length,c/o.length]}function s(e,t,n){if(!e||!e.features||!e.features.length)return e;let r=null,i=e=>{if(!(r||!Array.isArray(e))){if(typeof e[0]==`number`&&typeof e[1]==`number`){r=e;return}for(let t of e)i(t)}};for(let t of e.features)if(t.geometry&&i(t.geometry.coordinates),r)break;if(!r)return e;let a=Math.abs(r[0]-t)+Math.abs(r[1]-n);if(Math.abs(r[0]-n)+Math.abs(r[1]-t)<a){let t=e=>{if(Array.isArray(e)){if(typeof e[0]==`number`&&typeof e[1]==`number`){let t=e[0];e[0]=e[1],e[1]=t;return}for(let n of e)t(n)}};for(let n of e.features)n.geometry&&t(n.geometry.coordinates)}return e}function c(n,r){let i=t*Math.cos((n[1]+r[1])/2*(Math.PI/180)),a=(n[0]-r[0])*i,o=(n[1]-r[1])*e;return Math.sqrt(a*a+o*o)}function l(n,r,i){let a=t*Math.cos((n[1]+r[1]+i[1])/3*(Math.PI/180)),o=e,s=(r[0]-n[0])*a,c=(r[1]-n[1])*o,l=(i[0]-n[0])*a,u=(i[1]-n[1])*o,d=l-s,f=u-c,p=d*d+f*f;if(p===0)return Math.sqrt(s*s+c*c);let m=Math.max(0,Math.min(1,(-s*d+-c*f)/p)),h=s+m*d,g=c+m*f;return Math.sqrt(h*h+g*g)}function u(e,t){if(!t)return 1/0;let n=t.type===`LineString`?[t.coordinates]:t.type===`MultiLineString`?t.coordinates:[],r=1/0;for(let t of n){for(let n=0;n<t.length-1;n++){let i=l(e,t[n],t[n+1]);i<r&&(r=i)}for(let n of t){let t=c(e,n);t<r&&(r=t)}}return r}function d(e,t){if(!t)return 1/0;if(a(e,t))return 0;let n=t.type===`Polygon`?t.coordinates:t.type===`MultiPolygon`?t.coordinates.flat():[],r=1/0;for(let t of n)for(let n=0;n<t.length-1;n++){let i=l(e,t[n],t[n+1]);i<r&&(r=i)}return r}function f(e,t,n,r){let i=t[0]-e[0],a=t[1]-e[1],o=r[0]-n[0],s=r[1]-n[1],c=i*s-a*o;if(Math.abs(c)<1e-18)return null;let l=((n[0]-e[0])*s-(n[1]-e[1])*o)/c,u=((n[0]-e[0])*a-(n[1]-e[1])*i)/c;return l<0||l>1||u<0||u>1?null:[e[0]+l*i,e[1]+l*a]}function p(n,r){let i=t*Math.cos(n[1]*Math.PI/180),a=e,o=null;for(let e of r||[]){let t=e.geometry;if(!t)continue;let r=t.type===`LineString`?[t.coordinates]:t.type===`MultiLineString`?t.coordinates:[];for(let e of r)for(let t=0;t<e.length-1;t++){let r=e[t],s=e[t+1],c=(r[0]-n[0])*i,l=(r[1]-n[1])*a,u=(s[0]-n[0])*i,d=(s[1]-n[1])*a,f=u-c,p=d-l,m=f*f+p*p;if(!m)continue;let h=-(c*f+l*p)/m;h=Math.max(0,Math.min(1,h));let g=c+h*f,_=l+h*p,ee=Math.sqrt(g*g+_*_);if(!o||ee<o.distance_m){let e=Math.sqrt(m);o={distance_m:Math.round(ee*10)/10,dir_m:[f/e,p/e],anchor:[n[0]+g/i,n[1]+_/a]}}}}return o}function m(n,r,i,o){let s=t*Math.cos(n[1]*Math.PI/180),c=e,l=[-r[1],r[0]],u=[n[0]-l[0]*o/s,n[1]-l[1]*o/c],d=[n[0]+l[0]*o/s,n[1]+l[1]*o/c],p=[];for(let e of i||[])if(e){if(e.type===`Polygon`)p.push(...e.coordinates);else if(e.type===`MultiPolygon`)for(let t of e.coordinates)p.push(...t)}let m=[0,1];for(let e of p)for(let t=0;t<e.length-1;t++){let n=f(u,d,e[t],e[t+1]);if(!n)continue;let r=((n[0]-u[0])*s*l[0]+(n[1]-u[1])*c*l[1])/(2*o);r>0&&r<1&&m.push(r)}m.sort((e,t)=>e-t);let h=[];for(let e=0;e<m.length-1;e++){if(m[e+1]-m[e]<1e-9)continue;let t=(m[e]+m[e+1])/2,n=[u[0]+(d[0]-u[0])*t,u[1]+(d[1]-u[1])*t];(i||[]).some(e=>e&&a(n,e))&&h.push([m[e],m[e+1]])}let g=.5/(2*o),_=[];for(let e of h){let t=_[_.length-1];t&&e[0]-t[1]<g?t[1]=Math.max(t[1],e[1]):_.push([e[0],e[1]])}return{covered:_,spanM:2*o}}function h(e,t,n,r={}){let{covered:i,spanM:a}=m(e,t,n,r.maxM||40);if(!i.length)return{value_m:null,status:`NOT_FOUND`,detail:`aucun polygone traversé par la perpendiculaire à l'axe`};if((r.mode||`span`)===`sum`){let e=i.reduce((e,t)=>e+(t[1]-t[0])*a,0);return{value_m:Math.round(e*10)/10,status:`COMPUTED`,detail:i.length+` traversée(s) sommée(s)`}}let o=i.find(e=>e[0]<=.5&&.5<=e[1]),s=o||i.slice().sort((e,t)=>t[1]-t[0]-(e[1]-e[0]))[0];return{value_m:Math.round((s[1]-s[0])*a*10)/10,status:`COMPUTED`,detail:o?`corde au droit de l'axe`:`corde la plus longue (ancre hors polygone)`}}function g(e,t,n,r={}){let i=r.maxM||40,{covered:a,spanM:o}=m(e,t,n,i);if(!a.length)return{value_m:null,status:`NOT_FOUND`,detail:`aucune parcelle traversée par la perpendiculaire`};if(a.find(e=>e[0]<=.5&&.5<=e[1]))return{value_m:null,status:`ANCHOR_IN_PARCEL`,detail:`l'axe de voie tombe dans une parcelle — géométries à vérifier`};let s=null,c=null;for(let e of a)e[1]<=.5&&(s=e),e[0]>=.5&&!c&&(c=e);return!s||!c?{value_m:null,status:`UNBOUNDED`,detail:`parcelle absente d'un côté dans la fenêtre ±`+i+` m`}:{value_m:Math.round((c[0]-s[1])*o*10)/10,status:`COMPUTED`,detail:`vide entre parcelles opposées au droit de l'axe`}}function _(e){let t=[];for(let n of e&&e.results||[]){let e=n.geo_shape||n.geom||n.geo||null;e&&e.type===`Feature`&&(e=e.geometry),e&&(e.type===`Polygon`||e.type===`MultiPolygon`)&&t.push(e)}return t}function ee(e){let t=e&&e.results||[];if(!t.length)return{value_m:null,status:`NOT_FOUND`,detail:`aucun tronçon APUR à proximité`};for(let e of t){let t={};for(let[n,r]of Object.entries(e)){let e=typeof r==`string`?parseFloat(r):r;/largeur|larg_/i.test(n)&&typeof e==`number`&&isFinite(e)&&e>0&&(t[n]=e)}let n=Object.keys(t);if(!n.length)continue;let r=n.find(e=>/totale|voie|emprise/i.test(e)),i=r?t[r]:n.reduce((e,n)=>e+t[n],0);return{value_m:Math.round(i*10)/10,status:`COMPUTED`,detail:(r?`champ total `:`somme `)+n.map(e=>e+`=`+t[e]).join(` + `)}}return{value_m:null,status:`VALUE_MISSING`,detail:t.length+` tronçon(s) mais aucun champ largeur`}}function te(e,t){let n=(e&&e.elements||[]).filter(e=>e.tags&&e.tags.width),r=null;for(let e of n){let n=parseFloat(String(e.tags.width).replace(`,`,`.`));if(!isFinite(n)||n<=0)continue;let i=1/0;for(let n of e.geometry||[])i=Math.min(i,c(t,[n.lon,n.lat]));(!r||i<r.d)&&(r={d:i,v:n,tag:String(e.tags.width),name:e.tags.name||e.tags.highway||`way`})}return r?{value_m:Math.round(r.v*10)/10,status:`COMPUTED`,detail:r.name+` — width="`+r.tag+`" à `+Math.round(r.d)+` m (non vérifié)`}:{value_m:null,status:`NOT_FOUND`,detail:`aucun tag width à proximité (couverture OSM partielle)`}}function ne(e){return typeof e==`string`&&e.startsWith(`75`)}function re(e,t){if(!e||!t)return!1;let n=o(e);if(n&&a(n,t))return!0;let r=e.type===`Polygon`?[e.coordinates]:e.type===`MultiPolygon`?e.coordinates:[];for(let e of r)for(let n of e[0]||[])if(a(n,t))return!0;return!1}var v=e=>{let t=typeof e==`string`?parseFloat(e):e;return typeof t==`number`&&isFinite(t)?t:null};function ie(e,t){let n=e&&e.properties||{},r=e&&e.geometry||null,a=v(n.hauteur==null?n.height_m:n.hauteur),o=a,s=a==null?null:n.height_source||`BD_TOPO`;if(o==null){let e=v(n.altitude_maximale_toit),t=v(n.altitude_minimale_sol);e!=null&&t!=null&&e>t&&(o=Math.round((e-t)*10)/10,s=`BD_TOPO_ALTI`)}if(o==null){let e=v(n.epaisseur);e!=null&&e>0&&(o=e,s=`BD_TOPO_EPAISSEUR`)}let c=v(n.nombre_d_etages==null?n.floors_above_ground:n.nombre_d_etages),l=n.date_d_apparition?v(String(n.date_d_apparition).slice(0,4)):null,u=n.nature||null,d=n.usage_2||null,f=r?i(r):0,p=n.construction_legere===!0||n.construction_legere===`True`,m=p||f<20||/annexe|serre|transformateur|r[ée]servoir|garage|abri|hangar|b[âa]timent agricole/i.test(u||``);return{building_id:n.cleabs||n.building_id||n.id||`bat_`+(t+1),topographic_id:n.cleabs||null,geometry:r,footprint_m2:f,height_m:o,height_reference:o==null?null:`SOL`,height_source:s,floors_above_ground:c,housing_units_count:v(n.nombre_de_logements),usage:n.usage_1||n.usage||null,usage_2:d,nature:u,construction_year:l,has_light_construction:p,is_annex:m,is_main_building:!1}}function ae(e,t,n){let r=(e||[]).filter(e=>!e.is_annex),i=r.filter(e=>a(t,e.geometry));if(console.log(`[identifyMainBuilding] `+r.length+` mains, `+i.length+` contiennent le point, parcelle: `+(n?`oui`:`non`)),i.length)return{ok:!0,building_id:i.sort((e,t)=>t.footprint_m2-e.footprint_m2)[0].building_id,reason:`contains_address_point`,confidence:.95};let s=n?r.filter(e=>{let t=o(e.geometry);return t&&a(t,n)}):[];if(console.log(`[identifyMainBuilding] sur parcelle: `+s.length+` bâtiment(s)`),s.length===1)return{ok:!0,building_id:s[0].building_id,reason:`single_main_building_on_parcel`,confidence:.85};if(s.length>=2){let e=s.map(e=>{let n=o(e.geometry);return{building:e,dist:n?c(t,n):1/0,area:e.footprint_m2||0}});return e.sort((e,t)=>Math.abs(e.dist-t.dist)>5?e.dist-t.dist:t.area-e.area),console.log(`[identifyMainBuilding] auto-sélection parmi `+s.length+` : `+e[0].building.building_id+` (dist=`+Math.round(e[0].dist)+`m, area=`+Math.round(e[0].area)+`m²)`),{ok:!0,building_id:e[0].building.building_id,reason:`closest_to_address_point`,confidence:.7,candidates_count:s.length}}let l=r.map(e=>{let n=o(e.geometry);return{building:e,dist:n?c(t,n):1/0}}).filter(e=>e.dist<15).sort((e,t)=>e.dist-t.dist);return l.length?(console.log(`[identifyMainBuilding] fallback nearest: `+l[0].building.building_id+` (dist=`+Math.round(l[0].dist)+`m)`),{ok:!0,building_id:l[0].building.building_id,reason:`nearest_to_address_point`,confidence:.65}):{ok:!1,error:`BUILDING_NOT_IDENTIFIED`,detail:`Point BAN dans aucun des `+r.length+` bâtiments principaux du secteur ; `+s.length+` candidat(s) principal(aux) sur la parcelle`+(n?``:` (géométrie de parcelle absente)`)+`.`,candidates_on_parcel:s.length}}function oe(e){if(e.height_m==null||!e.floors_above_ground)return{height_per_floor_m:null,height_floor_consistency:`UNKNOWN`,warnings:[]};let t=Math.round(e.height_m/e.floors_above_ground*100)/100,n=`OK`,r=[];return t<2?(n=`INCONSISTENT`,r.push(`Moins de 2 m par niveau : incohérence probable`)):t>5&&(n=`TO_VERIFY`,r.push(`Plus de 5 m par niveau : contrôle nécessaire`)),{height_per_floor_m:t,height_floor_consistency:n,warnings:r}}function se(e,t,n){if(!e||!e.geometry||!t)return[];n??=.5;let i=r(e.geometry);if(!i||i.length<3)return[];let a=o(e.geometry),s=t.filter(t=>{if(t.building_id===e.building_id||!t.geometry)return!1;let a=r(t.geometry);if(!a||a.length<3)return!1;for(let e of i)for(let t=0;t<a.length-1;t++)if(l(e,a[t],a[t+1])<n)return!0;for(let e of a)for(let t=0;t<i.length-1;t++)if(l(e,i[t],i[t+1])<n)return!0;return!1});if(console.log(`[adjoiningBuildings] `+s.length+` touchant(s) (seuil `+n+`m), principal: `+e.building_id),s.length<=2||!a)return s;let u={};for(let e of s){let t=o(e.geometry);if(!t)continue;let n=Math.atan2(t[1]-a[1],t[0]-a[0]),r=Math.floor((n+Math.PI)/(2*Math.PI)*6)%6,i=c(a,t);(!u[r]||i<u[r].dist)&&(u[r]={building:e,dist:i})}return console.log(`[adjoiningBuildings] filtrage directionnel: `+Object.keys(u).length+` secteur(s) retenus sur `+s.length+` touchants`),Object.values(u).map(e=>e.building)}function ce(e,t){let n=r(e.geometry),i=r(t.geometry);if(!n||!i||n.length<3||i.length<3)return 1/0;let a=1/0;for(let e of n)for(let t=0;t<i.length-1;t++){let n=l(e,i[t],i[t+1]);n<a&&(a=n)}for(let e of i)for(let t=0;t<n.length-1;t++){let r=l(e,n[t],n[t+1]);r<a&&(a=r)}return a}function le(e){let t=e.height_m!=null&&e.height_m>0,n=e.floors_above_ground!=null&&e.floors_above_ground>0,r=n?e.floors_above_ground*3:null;if(t&&n){let t=Math.abs(e.height_m-r),n,i;return t>5?(n=Math.min(e.height_m,r),i=`MIN_ECART_SUPERIEUR_5M`):(n=Math.round((e.height_m+r)/2*10)/10,i=`MOYENNE_API_ET_NIVEAUX`),{value_m:n,method:i,source:(e.height_source||`BD_TOPO`)+`+NIVEAUX`,confidence:t>5?.6:.8,status:`HAUTEUR_CONSOLIDEE`,detail:{api_height_m:e.height_m,floors_estimate_m:r,gap_m:Math.round(t*10)/10,rule_applied:t>5?`GAP_GT_5M_TAKE_LOWER`:`AVERAGE`}}}return t?{value_m:e.height_m,method:`DONNEE_DIRECTE`,source:e.height_source||`BD_TOPO`,confidence:.85,status:`HAUTEUR_TROUVEE`}:n?{value_m:r,method:`NOMBRE_DE_NIVEAUX_X_3M`,source:`ESTIMATION`,confidence:.5,status:`HAUTEUR_ESTIMEE_PAR_NIVEAUX`}:{value_m:null,method:null,source:null,confidence:0,status:`HAUTEUR_NON_DISPONIBLE`}}function ue(e,t){if(!e||e<=0)return{parcel_area_m2:null,total_building_footprint_m2:null,existing_coverage_ratio:null,unbuilt_area_m2:null,status:`NOT_COMPUTABLE`};let n=Math.round((t||[]).reduce((e,t)=>e+(t.footprint_m2||0),0)*10)/10,r=Math.round(n/e*1e3)/1e3;return{parcel_area_m2:e,total_building_footprint_m2:n,existing_coverage_ratio:Math.min(1,r),unbuilt_area_m2:Math.max(0,Math.round((e-n)*10)/10),status:`COMPUTED`}}var y=[[/hauteur|filet|gabarit/i,`MAXIMUM_HEIGHT_REGULATION`,`HIGH`,`LOW`],[/alignement/i,`ALIGNMENT_REQUIREMENT`,`LOW`,`HIGH`],[/recul|retrait|marge/i,`SETBACK_REQUIREMENT`,`MEDIUM`,`HIGH`],[/inondation|ppri|submersion|risque/i,`FLOOD_RISK`,`MEDIUM`,`MEDIUM`],[/pleine terre|espace vert|v[ée]g[ée]talis|biotope|jardin/i,`FULL_SOIL_REQUIREMENT`,`LOW`,`HIGH`],[/monument|patrimoin|prot[ée]g[ée]|remarquable|psmv|abords|site (inscrit|class[ée])/i,`HERITAGE_PROTECTION`,`HIGH`,`MEDIUM`],[/logement social|mixit[ée] sociale/i,`SOCIAL_HOUSING_REQUIREMENT`,`LOW`,`MEDIUM`],[/stationnement|parking/i,`PARKING_REQUIREMENT`,`LOW`,`MEDIUM`],[/emplacement r[ée]serv[ée]/i,`RESERVED_LOCATION`,`LOW`,`HIGH`]];function de(e,t){let n=e&&e.properties||{},r=n.libelle||n.libelong||n.txt||``,i=`OTHER`,a=`LOW`,o=`LOW`;for(let[e,t,n,s]of y)if(e.test(r)){i=t,a=n,o=s;break}return{prescription_id:n.gpu_doc_id||n.idpsc||`presc_`+(t+1),type:i,official_label:r||null,geometry_type:n.gpu_layer===`LIN`?`line`:n.gpu_layer===`PCT`?`point`:`surface`,source:`GPU`,value:null,unit:null,status:`DETECTED`,relevance_vertical:a,relevance_horizontal:o}}function fe(e){let t=(e||[]).find(e=>e.type===`MAXIMUM_HEIGHT_REGULATION`);if(!t)return{detected:!1,value_m:null,status:`NOT_DETECTED`,confidence:0};let n=/(\d+(?:[.,]\d+)?)\s*m\b/i.exec(t.official_label||``),r=n?parseFloat(n[1].replace(`,`,`.`)):null;return{detected:!0,prescription_id:t.prescription_id,type:t.type,official_label:t.official_label,value_m:r,status:r==null?`VALUE_TO_EXTRACT`:`VALUE_EXTRACTED`,confidence:r==null?.4:.7}}function pe(e){if(!e||!e.length)return{found:!1,status:`NOT_FOUND`};let t=e[0].properties||{};return{found:!0,zone_id:t.idzone||t.gid||t.libelle||null,name:t.libelle||null,label:t.libelong||null,typezone:t.typezone||null,document_type:t.typedoc||null,partition:t.partition||null,approval_date:t.datappro||null,multiple_zones:e.length>1,zones_count:e.length,status:`VALIDATED`}}function me(e){if(!e||!e.length)return{found:!1,type:`RNU_OR_UNKNOWN`,status:`NOT_FOUND`};let t=e[0].properties||{};return{found:!0,document_id:t.partition||t.idurba||null,document_type:t.du_type||t.typedoc||null,territory_name:t.grid_title||t.nom||null,approval_date:t.datappro||t.date_appro||null,source:`GPU`,is_current:!0,status:`VALIDATED`}}function he(e,t,n){let r=e=>(e||``).normalize(`NFD`).replace(/[̀-ͯ]/g,``).toLowerCase().replace(/^(rue|avenue|boulevard|impasse|passage|place|allee|chemin|voie|cours|square|quai|route|sentier|rond-point)\s+/i,``).replace(/\s+/g,` `).trim(),i=(e||[]).map(e=>{let n=e.properties||{};return{name:n.cpx_toponyme_route_nommee||n.cpx_numero||null,nature:n.nature||null,width_m:v(n.largeur_de_chaussee),dist_m:Math.round(u(t,e.geometry))}}).filter(e=>e.dist_m<120).sort((e,t)=>e.dist_m-t.dist_m),a=r(n);if(a&&i.sort((e,t)=>(r(e.name)===a?0:1)-(r(t.name)===a?0:1)||e.dist_m-t.dist_m),!i.length)return{found:!1,status:`NOT_FOUND`,selected_value_m:null,roadway_width_m:null,access:{detected:!1,vehicle_access_possible:null}};let o=i.filter(e=>e.width_m!=null&&e.width_m>0),s=i[0],c=o.length?o[0]:s,l=!/sentier|escalier|chemin/i.test(s.nature||``);return{found:!0,street:{name:c.name,nature:c.nature,distance_m:c.dist_m},selected_value_m:c.width_m,roadway_width_m:c.width_m,measurement_type:c.width_m==null?null:`ROADWAY_WIDTH`,warning:c.width_m==null?`Largeur non renseignée dans la source`:`Largeur de chaussée BD TOPO — valeur prudente, non réglementaire (P2 : ne pas utiliser seule sans avertissement)`,status:c.width_m==null?`PARTIAL`:`ESTIMATED`,access:{detected:s.dist_m<40,vehicle_access_possible:s.dist_m<40?l:null},bordering_streets:i.slice(0,4)}}function ge(e){let t=[],n=new Set;return(function e(r){if(r!=null){if(typeof r==`string`){let e=/(\d+(?:[.,]\d+)?)\s*m(?:[eè]tres?)?\b/gi,i;for(;i=e.exec(r);){let e=parseFloat(i[1].replace(`,`,`.`));e>=3&&e<=60&&!n.has(e)&&(n.add(e),t.push(e))}return}if(Array.isArray(r)){r.forEach(e);return}typeof r==`object`&&Object.values(r).forEach(e)}})(e),t.sort((e,t)=>e-t),{values_m:t,max_value_m:t.length?t[t.length-1]:null,status:t.length?`VALUES_DETECTED`:`NOT_FOUND`,warning:t.length?`Hauteurs repérées dans le règlement structuré — plafond exact = dispositions cumulatives (calcul requis)`:null}}function _e({existingHeight:e,allowedHeightM:t,neighborHeights:n,roofAreaM2:r}){let i={status:`NOT_COMPUTABLE`,existing_height_m:e&&e.value_m!=null?e.value_m:null,permitted_height_m:t??null,additional_height_m:null,estimated_additional_floors:null,reference_roof_area_m2:r||null,gross_potential_floor_area_m2:null,limiting_rules:[],assumptions:[],missing_inputs:[],confidence:0};if(i.existing_height_m==null)return i.missing_inputs.push(`EXISTING_HEIGHT`),i;let a=null;if(t!=null)a=t,i.limiting_rules.push(`MAXIMUM_HEIGHT_REGULATION`),i.confidence=e.status===`HAUTEUR_TROUVEE`||e.status===`HAUTEUR_CONSOLIDEE`?.7:.5,i.status=`COMPUTED`;else{let e=(n||[]).filter(e=>typeof e==`number`&&e>0);if(e.length>=2)a=Math.round(e.reduce((e,t)=>e+t,0)/e.length*10)/10,i.limiting_rules.push(`HAUTEUR_SELON_MITOYENS`),i.assumptions.push(`Plafond estimé par harmonisation avec les bâtiments voisins (`+e.length+` hauteurs) — pas une règle opposable`),i.confidence=.35,i.status=`PARTIAL`;else return i.missing_inputs.push(`ALLOWED_HEIGHT`),i}let o=Math.round((a-i.existing_height_m)*10)/10;return i.permitted_height_m=a,i.additional_height_m=Math.max(0,o),i.estimated_additional_floors=o>=2.5?Math.floor(o/3)||+(o>=2.5):0,o>=2.5&&i.estimated_additional_floors===0&&(i.estimated_additional_floors=1),r&&i.estimated_additional_floors>0&&(i.gross_potential_floor_area_m2=Math.round(r*i.estimated_additional_floors)),o<2.5&&i.assumptions.push(`Réserve inférieure à un niveau : surélévation improbable sans dérogation`),i}function ve({unbuilt:e,footprintRuleRatio:t,accessDetected:n}){let r={status:`NOT_COMPUTABLE`,parcel_area_m2:e?e.parcel_area_m2:null,existing_building_footprint_m2:e?e.total_building_footprint_m2:null,existing_coverage_ratio:e?e.existing_coverage_ratio:null,unbuilt_area_m2:e?e.unbuilt_area_m2:null,regulatory_buildable_envelope_m2:null,potential_additional_footprint_m2:null,limiting_rules:[],assumptions:[],missing_inputs:[],warnings:[`La surface non bâtie n'est pas la surface constructible : retraits, pleine terre, accès et prescriptions restent à appliquer`],confidence:0};if(!e||e.status!==`COMPUTED`)return r.missing_inputs.push(`PARCEL_GEOMETRY`),r;if(t!=null){let n=Math.round(e.parcel_area_m2*t*10)/10;r.regulatory_buildable_envelope_m2=n,r.potential_additional_footprint_m2=Math.max(0,Math.round((n-e.total_building_footprint_m2)*10)/10),r.limiting_rules.push(`EMPRISE_MAXIMALE`),r.status=`COMPUTED`,r.confidence=.6}else r.missing_inputs.push(`MAX_FOOTPRINT_RULE`),r.status=`PARTIAL`,r.confidence=.3;return n===!1&&(r.warnings.push(`Aucun accès véhicule détecté à proximité — desserte à vérifier`),r.confidence=Math.min(r.confidence,.25)),r}function ye(e,t){let n={status:`NOT_COMPUTABLE`,vertical_net_floor_area_m2:e&&e.gross_potential_floor_area_m2!=null?e.gross_potential_floor_area_m2:null,horizontal_net_floor_area_m2:t&&t.potential_additional_footprint_m2!=null?t.potential_additional_footprint_m2:null,combined_net_floor_area_m2:null,compatible_scenarios:[],confidence:0},r=e&&(e.status===`COMPUTED`||e.status===`PARTIAL`)&&e.estimated_additional_floors>0,i=t&&t.status===`COMPUTED`&&t.potential_additional_footprint_m2>0;return r&&n.compatible_scenarios.push(`VERTICAL_ONLY`),i&&n.compatible_scenarios.push(`HORIZONTAL_ONLY`),r&&i&&n.compatible_scenarios.push(`COMBINED`),r&&i&&n.vertical_net_floor_area_m2!=null&&n.horizontal_net_floor_area_m2!=null?(n.combined_net_floor_area_m2=Math.round(n.vertical_net_floor_area_m2+n.horizontal_net_floor_area_m2),n.status=`COMPUTED`,n.confidence=Math.round(Math.min(e.confidence,t.confidence)*100)/100):(r||i)&&(n.status=`PARTIAL`,n.confidence=Math.round(((r?e.confidence:0)+(i?t.confidence:0))*50)/100),n}function be({address:e,zone:t,parcelId:n,mainBuilding:r,existingHeight:i,vertical:a,horizontal:o,prescriptions:s,servitudesCount:c}){let l=(s||[]).some(e=>e.type===`HERITAGE_PROTECTION`),u=a&&(a.status===`COMPUTED`||a.status===`PARTIAL`)&&a.estimated_additional_floors>0,d=o&&o.status===`COMPUTED`&&o.potential_additional_footprint_m2>0,f=`A_VERIFIER`;l?f=`CONTRAINT`:u&&a.status===`COMPUTED`||d?f=`GO`:(u||d)&&(f=`A_VERIFIER`);let p=[];return t&&t.name&&p.push([`Zone PLU`,t.name]),n&&p.push([`Parcelle cadastrale`,n]),i&&i.value_m!=null&&p.push([`Hauteur actuelle`,i.value_m+` m`+(i.status===`HAUTEUR_ESTIMEE_PAR_NIVEAUX`?` (est.)`:``)]),r&&r.floors_above_ground!=null&&p.push([`Niveaux`,r.floors_above_ground]),a&&a.estimated_additional_floors!=null&&p.push([`Potentiel vertical`,a.estimated_additional_floors>0?`+`+a.estimated_additional_floors+` niveau(x)`+(a.status===`PARTIAL`?` (à confirmer)`:``):`Limité`]),o&&o.unbuilt_area_m2!=null&&p.push([`Surface libre`,Math.round(o.unbuilt_area_m2)+` m²`]),(s||[]).length&&p.push([`Prescriptions`,s.length+` détectée(s)`]),c&&p.push([`Servitudes`,c]),{address:e||null,verdict:f,verdict_label:f===`GO`?`Potentiel détecté`:f===`CONTRAINT`?`Secteur contraint`:`Potentiel à confirmer`,rows:p}}var xe=[{id:`M1`,label:`Géocodage & normalisation`,ref:`S1.1`,desc:`BAN — position, score, code INSEE`,phase:`data`},{id:`M2`,label:`Parcelle cadastrale`,ref:`S1.2`,desc:`Géométrie officielle + numéro parcellaire`,phase:`data`},{id:`M3`,label:`Bâtiments individualisés`,ref:`Step 7`,desc:`Principal, annexes, dissociation`,phase:`data`},{id:`M4`,label:`Immeubles mitoyens`,ref:`Step 7 §10`,desc:`Adjacence réelle < 0,5 m`,phase:`data`},{id:`M5`,label:`Document d'urbanisme`,ref:`Step 11`,desc:`PLU/PLUi/RNU applicable (GPU)`,phase:`data`},{id:`M6`,label:`Zone PLU par intersection`,ref:`S1.7`,desc:`Zone(s) réellement applicables`,phase:`data`},{id:`M7`,label:`Prescriptions & servitudes`,ref:`S1.8`,desc:`Standardisées + hauteur isolée`,phase:`data`},{id:`M8`,label:`Règlement structuré`,ref:`Step 8`,desc:`Connecteur local (Airtable) si disponible`,phase:`data`},{id:`M9`,label:`Tronçons de voie`,ref:`P2`,desc:`BD TOPO — géométrie + largeur chaussée`,phase:`data`},{id:`M10`,label:`Hauteurs existantes`,ref:`P3`,desc:`Par bâtiment, jamais inventées`,phase:`calc`},{id:`M11`,label:`Largeur de voie & accès`,ref:`P2`,desc:`Chaussée + emprise estimée façade-à-façade`,phase:`calc`},{id:`M12`,label:`Espaces non bâtis`,ref:`Step 7 §18`,desc:`Emprise, ratio, surface libre, distances`,phase:`calc`},{id:`M13`,label:`Règles applicables`,ref:`Step 9`,desc:`Priorités, conflits tracés`,phase:`calc`},{id:`M14`,label:`Droits à construire`,ref:`Step 10`,desc:`Potentiels vertical / horizontal / combiné`,phase:`calc`}];async function b(e,t,n,r,i){let a=new URLSearchParams(Object.assign({action:n},r)).toString(),o=await e(t+`?`+a,i||{}),s=await o.json().catch(()=>null);if(!s||s.ok!==!0){let e=s&&s.error||`HTTP `+o.status;throw Error(n+` : `+e)}return s}async function x(e,t={}){let n=t.proxy||`/adm-api/proxy.php`,r=t.fetch||((...e)=>fetch(...e)),l=t.onStep||(()=>{}),u=t.chooseBuilding||null,f=t.chooseParcel||null,m=t.nocache?{nocache:`1`}:{},v={},y=(e,t,n)=>{v[e]=Object.assign({state:t},n||{}),l(e,t,n||{})};y(`M1`,`start`);let x;try{let t=await b(r,n,`mvp_geocode`,Object.assign({q:e,limit:`1`},m)),i=t.data&&t.data.features&&t.data.features[0];if(!i)throw Error(`adresse introuvable (BAN)`);let a=i.properties||{};x={label:a.label||e,lon:i.geometry.coordinates[0],lat:i.geometry.coordinates[1],insee:a.citycode||null,city:a.city||null,score:a.score==null?null:Math.round(a.score*100)/100,street:a.name||null,status:a.score==null||a.score>=.6?`VALIDATED`:`TO_CONFIRM`},y(`M1`,x.status===`VALIDATED`?`done`:`warn`,{summary:x.label+` — score `+x.score+` (`+x.status+`)`,data:x})}catch(e){return y(`M1`,`error`,{error:e.message}),{ok:!1,error:`GEOCODING_FAILED : `+e.message,steps:v}}let S=[x.lon,x.lat],C={lon:String(x.lon),lat:String(x.lat)};y(`M2`,`start`);let w=null;try{let e=await b(r,n,`mvp_parcelle`,Object.assign({},C,m)),t=s(e.data||{},x.lon,x.lat),o=t&&t.features||[],c=o.filter(e=>a(S,e.geometry)),l=c.length?c.sort((e,t)=>i(e.geometry)-i(t.geometry))[0]:null,u=!1;if(!l){let t=e.data&&e.data.source||`apicarto`,n=e.data&&e.data.source_detail||{},r=o.map(e=>{let t=e.properties||{};return{feature:e,id:t.idu||[t.code_dep,t.code_com,t.com_abs,t.section,t.numero].filter(Boolean).join(``),section:t.section||null,numero:t.numero||null,dist_m:Math.round(d(S,e.geometry)*10)/10,area_m2:Math.round(i(e.geometry))}}).sort((e,t)=>e.dist_m-t.dist_m);try{console.warn(`[M2 diag] Aucune parcelle ne contient le point BAN`,{point:S,source:t,source_detail:n,candidates:r.length}),console.table(r.map(e=>({id:e.id,section:e.section,numero:e.numero,dist_m:e.dist_m,area_m2:e.area_m2})))}catch{}if(f&&r.length){y(`M2`,`warn`,{summary:`Aucune parcelle ne contient le point — sélection manuelle demandée (`+r.length+` candidate(s))`});let e=await f(r);e&&e.feature&&(l=e.feature,u=!0)}if(!l){let e=` (source `+t+`, `+o.length+` parcelle(s) à proximité`;throw r.length&&(e+=`, la plus proche à `+r[0].dist_m+` m`),n.apicarto_status&&(n.apicarto_status>=400||n.apicarto_error)&&(e+=`, apicarto HTTP `+n.apicarto_status+(n.apicarto_error?` `+n.apicarto_error:``)),e+=`).`,Error(`Aucune parcelle cadastrale ne contient le point géocodé`+e+` Le point BAN est probablement sur la voirie — adresse à vérifier.`)}}let p=l.properties||{};w={id:p.idu||[p.code_dep,p.code_com,p.com_abs,p.section,p.numero].filter(Boolean).join(``),section:p.section||null,number:p.numero||null,surface_fiscal_m2:p.contenance==null?null:Number(p.contenance),surface_geometric_m2:l.geometry?i(l.geometry):null,geometry:l.geometry,source:e.data&&e.data.source||`IGN_APICARTO`,status:u?`MANUALLY_SELECTED`:`VALIDATED`,selection_reason:u?`user_selected`:`contains_address_point`},y(`M2`,`done`,{summary:(w.section&&w.number?w.section+` `+w.number:w.id)+` — `+Math.round(w.surface_geometric_m2||0)+` m² (géom.)`+(w.surface_fiscal_m2?` / `+w.surface_fiscal_m2+` m² (fisc.)`:``)+(u?` — choisie manuellement`:``),data:w})}catch(e){y(`M2`,`error`,{error:e.message});for(let e of xe)e.id!==`M1`&&e.id!==`M2`&&y(e.id,`blocked`,{summary:`Bloqué : parcelle non identifiée`});return{ok:!1,error:`PARCEL_NOT_FOUND_AT_POINT`,error_detail:e.message,steps:v}}y(`M3`,`start`);let T=[],E=[],D=[],O=null,k=null,Se=null,A=[];try{let e=s((await b(r,n,`mvp_batiments`,Object.assign({},C,m))).data||{},x.lon,x.lat);T=(e&&e.features||[]).map(ie);let t=T.reduce((e,t)=>(t.height_source===`BD_TOPO`?e.direct++:t.height_source===`BD_TOPO_ALTI`?e.alti++:t.height_source===`BD_TOPO_EPAISSEUR`&&e.epaisseur++,t.floors_above_ground>0&&e.withF++,!t.height_m&&!t.floors_above_ground&&e.neither++,e),{direct:0,alti:0,epaisseur:0,withF:0,neither:0});if(console.log(`[M3] BD TOPO bâtiments: `+T.length+` total — hauteur: `+t.direct+` directe, `+t.alti+` par altitudes, `+t.epaisseur+` par épaisseur, `+t.withF+` avec étages, `+t.neither+` sans info`),T.length<=20&&console.table(T.map(e=>({id:e.building_id,h_m:e.height_m,src:e.height_source,floors:e.floors_above_ground,m2:Math.round(e.footprint_m2),nature:e.nature,annex:e.is_annex}))),w&&w.geometry)for(let e of T){let t=o(e.geometry);(t&&a(t,w.geometry)?E:D).push(e)}let i=E.filter(e=>!e.is_annex);A=E.filter(e=>e.is_annex);let l=ae(T,S,w.geometry);if(!l.ok)try{console.warn(`[M3 diag] Bâtiment non identifié`,{point:S,detail:l.detail}),console.table(T.map(e=>{let t=o(e.geometry);return{id:e.building_id,annexe:!!e.is_annex,m2:Math.round(e.footprint_m2||0),h_m:e.height_m,sur_parcelle:E.indexOf(e)>=0,dist_m:t?Math.round(c(S,t)*10)/10:null,contient_point:a(S,e.geometry)}}))}catch{}if(console.log(`[M3] identifyMainBuilding result:`,JSON.stringify({ok:l.ok,reason:l.reason,building_id:l.building_id,confidence:l.confidence,candidates_count:l.candidates_count,error:l.error})),l.ok)k={building_id:l.building_id,selection_reason:l.reason,selection_confidence:l.confidence};else if(u){let e=i;e.length||(e=T.filter(e=>{if(e.is_annex)return!1;let t=o(e.geometry);return t&&c(S,t)<30}));let t=e.length?await u(e):null;t&&(k={building_id:t.building_id,selection_reason:`user_selected`,selection_confidence:1})}if(!k){let e=l.detail||`Bâtiment non identifié.`;y(`M3`,`error`,{error:e});for(let e of xe)v[e.id]||y(e.id,`blocked`,{summary:`Bloqué : bâtiment non identifié`});return{ok:!1,error:`BUILDING_NOT_IDENTIFIED`,error_detail:e,steps:v,parcel:w}}O=E.concat(D).find(e=>e.building_id===k.building_id)||null,O&&(O.is_main_building=!0,Se=oe(O)),y(`M3`,`done`,{summary:T.length+` bâtiment(s) — `+E.length+` sur parcelle (`+i.length+` principaux, `+A.length+` annexes) · principal : `+k.building_id+` (`+k.selection_reason+`, confiance `+k.selection_confidence+`)`,data:{count:T.length,on_parcel:E.length,main_candidates:i.length,annexes:A.length,main_building:k,building_data_quality:Se}})}catch(e){y(`M3`,`error`,{error:e.message});for(let e of xe)v[e.id]||y(e.id,`blocked`,{summary:`Bloqué : bâtiments indisponibles`});return{ok:!1,error:`BUILDINGS_FETCH_FAILED`,error_detail:e.message,steps:v,parcel:w}}y(`M4`,`start`);let j=[];try{O?(j=se(O,D.concat(E),.5),console.log(`[M4] mitoyens: `+j.length+` retenus sur `+D.concat(E).length+` candidats — IDs: `+j.map(e=>e.building_id).join(`, `)),y(`M4`,j.length?`done`:`warn`,{summary:j.length+` mitoyen(s) détecté(s)`+(j.length?` — hauteurs : `+j.map(e=>e.height_m==null?`?`:e.height_m+` m`).join(`, `):``),data:{adjoining_count:j.length,adjoining_buildings:j.map(e=>({building_id:e.building_id,height_m:e.height_m,floors_above_ground:e.floors_above_ground,footprint_m2:e.footprint_m2,geometry:e.geometry}))}})):y(`M4`,`warn`,{summary:`Pas de bâtiment principal — mitoyens non calculables`})}catch(e){y(`M4`,`error`,{error:e.message})}y(`M5`,`start`);let M={found:!1,status:`NOT_FOUND`};try{let e=await b(r,n,`mvp_document`,Object.assign({},C,m));M=me(e.data&&e.data.features||[]),y(`M5`,M.found?`done`:`warn`,{summary:M.found?(M.document_type||`?`)+` — `+(M.territory_name||``):`Aucun document GPU (RNU possible)`,data:M})}catch(e){y(`M5`,`error`,{error:e.message})}y(`M6`,`start`);let N={found:!1,status:`NOT_FOUND`};try{let e=await b(r,n,`mvp_zone_urba`,Object.assign({},C,m));N=pe(e.data&&e.data.features||[]),y(`M6`,N.found?`done`:`warn`,{summary:N.found?`Zone `+N.name+(N.multiple_zones?` (+`+(N.zones_count-1)+` autre(s) — MULTI_ZONE)`:``):`Aucune zone au point`,data:N})}catch(e){y(`M6`,`error`,{error:e.message})}y(`M7`,`start`);let P=[],F={detected:!1,status:`NOT_DETECTED`},I=0;try{let e=await b(r,n,`mvp_prescriptions`,Object.assign({},C,m));P=(e.data&&e.data.features||[]).map(de),F=fe(P);let t=`servitudes indisponibles`;try{let e=await b(r,n,`mvp_servitudes`,Object.assign({},C,m));I=(e.data&&e.data.features||[]).length,t=I+` servitude(s)`}catch{}y(`M7`,`done`,{summary:P.length+` prescription(s) · `+t+` · hauteur : `+F.status,data:{prescriptions:P,height_prescription:F,servitudes_count:I}})}catch(e){y(`M7`,`error`,{error:e.message})}y(`M8`,`start`);let L={status:`CONNECTOR_UNAVAILABLE`,values_m:[],max_value_m:null};if(t.adminKey&&N.found&&N.name)try{L=ge((await b(r,n,`airtable_plu`,Object.assign({zoneId:N.name},m),{method:`POST`,headers:{"X-Admin-Key":t.adminKey,"Content-Type":`application/json`},body:JSON.stringify({urbanZoneParams:{id:N.name,name:N.name,libelong:N.label||``,type:`PLU`}})})).data),y(`M8`,`done`,{summary:L.values_m.length+` hauteur(s) repérée(s)`+(L.max_value_m?` — max `+L.max_value_m+` m`:``),data:L})}catch(e){y(`M8`,`warn`,{summary:`Connecteur indisponible — statut MISSING (aucune valeur inventée)`,error:e.message})}else y(`M8`,`skip`,{summary:t.adminKey?`Zone inconnue — connecteur non interrogeable`:`Pas de connecteur règlement sur ce canal — briques MISSING`});y(`M9`,`start`);let R=[];try{let e=await b(r,n,`mvp_troncon`,Object.assign({},C,m));R=e.data&&e.data.features||[],y(`M9`,R.length?`done`:`warn`,{summary:R.length+` tronçon(s) récupéré(s)`,data:{count:R.length}})}catch(e){y(`M9`,`error`,{error:e.message})}y(`M10`,`start`);let z=O?le(O):{value_m:null,status:`HAUTEUR_NON_DISPONIBLE`,confidence:0},Ce=j.map(e=>e.height_m==null?null:e.height_m).filter(e=>e!=null),we=D.map(e=>e.height_m==null?null:e.height_m).filter(e=>e!=null),B=O&&O.floors_above_ground?O.floors_above_ground*3:null,V={api_height_m:O&&O.height_m!=null?O.height_m:null,floors_above_ground:O?O.floors_above_ground:null,floors_x3_m:B,delta_m:O&&O.height_m!=null&&B!=null?Math.round((O.height_m-B)*10)/10:null};y(`M10`,z.value_m==null?`warn`:`done`,{summary:(z.value_m==null?`Hauteur non disponible — statut explicite, pas d'invention`:z.value_m+` m (`+z.method+`)`)+(B==null?``:` · niveaux×3 m : `+V.floors_above_ground+`×3 = `+B+` m`+(V.delta_m==null?``:` (écart API : `+(V.delta_m>0?`+`:``)+V.delta_m+` m)`))+` · `+Ce.length+` mitoyen(s) · `+we.length+` voisin(s)`,data:{existing_height:z,height_check:V,adjoining_heights:Ce,neighbor_heights:we}}),y(`M11`,`start`);let Te=x.street||null,H=he(R,S,Te),U=null;if(O&&H.found&&H.street)try{let e=D.filter(e=>{if(!e.geometry)return!1;let t=o(e.geometry);if(!t)return!1;let n=c(S,t);return n>5&&n<80});if(e.length&&O.geometry&&(O.geometry.type===`Polygon`?O.geometry.coordinates[0]:O.geometry.type===`MultiPolygon`&&O.geometry.coordinates[0][0])){let t=1/0;for(let n of e){let e=ce(O,n);e<t&&e>3&&(t=e)}t<100&&(U=Math.round(t*10)/10)}}catch{}H.estimated_row_width_m=U;let Ee=H.roadway_width_m!=null&&U!=null&&Math.abs(H.roadway_width_m-U)>6;Ee&&(H.width_status=`TO_VERIFY`);let De=[],W=p(S,R),Oe=ne(x.insee),G=(e,t,n,r,i)=>De.push(Object.assign({method:e,label:t,coverage:n,reliability:r},i)),ke={value_m:null,status:`NO_AXIS`,detail:`axe de voie introuvable (BD TOPO)`},Ae={value_m:null,status:`NOT_COVERED`,detail:`hors Paris`},K=async(e,t)=>(await b(r,n,e,Object.assign({},t||{},C,m))).data||{};if(!Oe)G(`PVP_EMPRISE`,`PVP — emprise de voirie`,`Paris`,`maximale`,Ae);else if(!W)G(`PVP_EMPRISE`,`PVP — emprise de voirie`,`Paris`,`maximale`,ke);else try{let e=await K(`mvp_pvp`,{layer:`emprises`});G(`PVP_EMPRISE`,`PVP — emprise de voirie`,`Paris`,`maximale`,h(W.anchor,W.dir_m,_(e),{mode:`span`}))}catch(e){G(`PVP_EMPRISE`,`PVP — emprise de voirie`,`Paris`,`maximale`,{value_m:null,status:`ERROR`,detail:e.message})}if(!W)G(`PARCELLES_OPPOSEES`,`Parcelles cadastrales opposées`,`National`,`fiable`,ke);else try{let e=s(await K(`mvp_parcelles_zone`),x.lon,x.lat);G(`PARCELLES_OPPOSEES`,`Parcelles cadastrales opposées`,`National`,`fiable`,g(W.anchor,W.dir_m,(e&&e.features||[]).map(e=>e.geometry),{}))}catch(e){G(`PARCELLES_OPPOSEES`,`Parcelles cadastrales opposées`,`National`,`fiable`,{value_m:null,status:`ERROR`,detail:e.message})}if(!Oe)G(`APUR_TRONCON`,`APUR — tronçon enrichi`,`Paris/IDF`,`bonne (à vérifier)`,Ae);else try{G(`APUR_TRONCON`,`APUR — tronçon enrichi`,`Paris/IDF`,`bonne (à vérifier)`,ee(await K(`mvp_apur`)))}catch(e){G(`APUR_TRONCON`,`APUR — tronçon enrichi`,`Paris/IDF`,`bonne (à vérifier)`,{value_m:null,status:`ERROR`,detail:e.message})}if(G(`BDTOPO_CHAUSSEE`,`BD TOPO — largeur chaussée`,`National`,`sous-estime (chaussée ≠ alignement)`,H.roadway_width_m==null?{value_m:null,status:`NOT_FOUND`,detail:`aucun tronçon avec largeur de chaussée`}:{value_m:H.roadway_width_m,status:`COMPUTED`,detail:H.street&&H.street.name||`tronçon le plus proche`}),G(`FACADE_A_FACADE`,`Façade à façade (BD TOPO bâti)`,`National`,`proxy tissu continu (faux si recul)`,U==null?{value_m:null,status:`NOT_FOUND`,detail:`pas de bâti opposé exploitable`}:{value_m:U,status:`COMPUTED`,detail:`min. entre bâtis opposés de part et d'autre de l'axe`}),!Oe)G(`PVP_CHAUSSEE_TROTTOIRS`,`PVP — chaussée + trottoirs`,`Paris`,`précise (assemblage)`,Ae);else if(!W)G(`PVP_CHAUSSEE_TROTTOIRS`,`PVP — chaussée + trottoirs`,`Paris`,`précise (assemblage)`,ke);else try{let e=h(W.anchor,W.dir_m,_(await K(`mvp_pvp`,{layer:`chaussees`})),{mode:`span`}),t=h(W.anchor,W.dir_m,_(await K(`mvp_pvp`,{layer:`trottoirs`})),{mode:`sum`});e.value_m!=null&&t.value_m!=null?G(`PVP_CHAUSSEE_TROTTOIRS`,`PVP — chaussée + trottoirs`,`Paris`,`précise (assemblage)`,{value_m:Math.round((e.value_m+t.value_m)*10)/10,status:`COMPUTED`,detail:`chaussée `+e.value_m+` m + trottoirs `+t.value_m+` m`}):G(`PVP_CHAUSSEE_TROTTOIRS`,`PVP — chaussée + trottoirs`,`Paris`,`précise (assemblage)`,{value_m:null,status:`PARTIAL`,detail:`chaussée : `+(e.value_m==null?e.status:e.value_m+` m`)+` · trottoirs : `+(t.value_m==null?t.status:t.value_m+` m`)})}catch(e){G(`PVP_CHAUSSEE_TROTTOIRS`,`PVP — chaussée + trottoirs`,`Paris`,`précise (assemblage)`,{value_m:null,status:`ERROR`,detail:e.message})}G(`LIDAR_HD`,`LiDAR HD / MNS (IGN)`,`National`,`très précise`,{value_m:null,status:`NOT_IMPLEMENTED`,detail:`ingestion 3D lourde — à intégrer si le LiDAR sert aussi aux hauteurs`});try{G(`OSM_WIDTH`,`OSM — tag width`,`National`,`partielle non vérifiée`,te(await K(`mvp_osm_width`),S))}catch(e){G(`OSM_WIDTH`,`OSM — tag width`,`National`,`partielle non vérifiée`,{value_m:null,status:`ERROR`,detail:e.message})}let je=De.filter(e=>e.value_m!=null).length;y(`M11`,H.found?`done`:`warn`,{summary:(H.found?(H.street.name||`voie`)+` — chaussée `+(H.roadway_width_m==null?`?`:H.roadway_width_m+` m`)+(U==null?``:` · emprise est. `+U+` m`)+(Ee?` ⚠ divergence`:``)+` · accès `+(H.access.vehicle_access_possible?`véhicule OK`:`à vérifier`):`Aucune voie proche identifiée`)+` · comparatif largeur : `+je+`/8 méthodes avec valeur`,data:Object.assign({},H,{width_methods:De})}),y(`M12`,`start`);let q=ue(w?w.surface_geometric_m2:null,E),J=E.filter(e=>!e.is_annex),Y=null;if(J.length>=2){let e=1/0;for(let t=0;t<J.length;t++)for(let n=t+1;n<J.length;n++){let r=ce(J[t],J[n]);r<e&&(e=r)}e<1/0&&(Y=Math.round(e*10)/10)}let Me=Math.round(E.reduce((e,t)=>e+(t.footprint_m2||0),0)*10)/10;y(`M12`,q.status===`COMPUTED`?`done`:`warn`,{summary:q.status===`COMPUTED`?`Emprise `+Math.round(q.existing_coverage_ratio*100)+` % · libre `+Math.round(q.unbuilt_area_m2)+` m²`+(Y==null?``:` · dist. min bât. `+Y+` m`):`Parcelle indisponible — NOT_COMPUTABLE`,data:Object.assign({},q,{min_building_distance_m:Y,total_building_footprint_m2:Me})}),y(`M13`,`start`);let X=[],Z=null,Ne=null;F.detected&&F.value_m!=null&&(Z=F.value_m,Ne=`GRAPHIC_PRESCRIPTION`),L.max_value_m!=null&&(Z==null?(Z=L.max_value_m,Ne=`STRUCTURED_REGULATION`):Math.abs(Z-L.max_value_m)>.5&&X.push({rule_ids:[`height_prescription`,`airtable_max_height`],conflict_type:`VALUE_MISMATCH`,values:[Z,L.max_value_m],resolution:`GRAPHIC_RULE_PREVAILS`})),y(`M13`,`done`,{summary:Z==null?`Aucun plafond sourcé — le calcul basculera sur l'harmonisation mitoyens`:`Plafond retenu : `+Z+` m (`+Ne+`)`+(X.length?` — `+X.length+` conflit(s) tracé(s)`:``),data:{allowed_height_m:Z,source:Ne,rule_conflicts:X}}),y(`M14`,`start`);let Pe=Ce.length>=2?Ce:we,Q=_e({existingHeight:z,allowedHeightM:Z,neighborHeights:Pe,roofAreaM2:O?O.footprint_m2:null}),$=ve({unbuilt:q,footprintRuleRatio:null,accessDetected:H.access?H.access.vehicle_access_possible:null}),Fe=ye(Q,$),Ie=w&&w.section&&w.number?w.section+` `+w.number:w?w.id:null,Le=be({address:x.label,zone:N.found?N:null,parcelId:Ie,mainBuilding:O,existingHeight:z,vertical:Q,horizontal:$,prescriptions:P,servitudesCount:I}),Re={ok:!0,action:`building_rights`,data:{searched_address:x,parcel:w,buildings_count:T.length,main_building:O,main_building_selection:k,secondary_buildings:A.map(e=>({building_id:e.building_id,footprint_m2:e.footprint_m2,height_m:e.height_m,nature:e.nature,is_annex:!0,geometry:e.geometry})),on_parcel_buildings:T.filter(e=>O&&e.building_id===O.building_id||re(e.geometry,w.geometry)).map(e=>({building_id:e.building_id,footprint_m2:e.footprint_m2,is_annex:!!e.is_annex,geometry:e.geometry})),adjoining_buildings:j.map(e=>({building_id:e.building_id,height_m:e.height_m,floors_above_ground:e.floors_above_ground,footprint_m2:e.footprint_m2,geometry:e.geometry})),context_buildings:T.filter(e=>e.geometry&&(!O||e.building_id!==O.building_id)&&!j.some(t=>t.building_id===e.building_id)).map(e=>({building_id:e.building_id,height_m:e.height_m,floors_above_ground:e.floors_above_ground,geometry:e.geometry})),all_buildings:T.filter(e=>e.geometry).map(e=>({building_id:e.building_id,height_m:e.height_m,floors_above_ground:e.floors_above_ground,footprint_m2:e.footprint_m2,geometry:e.geometry})),urbanism_document:M,urban_zone:N,prescriptions:P,height_prescription:F,servitudes_count:I,street:H,street_width_methods:De,structured_rules:L,rule_conflicts:X,height_check:V,vertical_potential:Q,horizontal_potential:$,combined_potential:Fe,total_building_footprint_m2:Me,min_building_distance_m:Y},quality:{geocoding:x.status,parcel:w?w.status:`MISSING`,buildings:O?`VALIDATED`:`TO_VERIFY`,building_selection_reason:k?k.selection_reason:null,building_selection_confidence:k?k.selection_confidence:null,vertical_confidence:Q.confidence,horizontal_confidence:$.confidence,overall_confidence:Math.round((Q.confidence+$.confidence)/2*100)/100,human_review_required:!0},fiche:Le,steps:v};return y(`M14`,`done`,{summary:Le.verdict_label+` — vertical `+Q.status+` / horizontal `+$.status,data:{vertical_potential:Q,horizontal_potential:$,combined_potential:Fe,fiche:Le}}),Re}export{x as n,xe as t};