Robitex's Blog
Ideas in the web
Il computo metrico con Lua
Pubblicato da su 12/12/2011
Scarica l’articolo in formato PDF per la stampa
Sommario
Certi tipi di opere edili possono essere così articolate da mettere in difficoltà l’utente che intendesse gestirle con un tradizionale software di computazione.
In questo post si svilupperà un’idea che può risolvere il problema di efficienza, secondo la quale i dati sono descritti da un opportuno linguaggio così da esprimere in modo diretto e concettuale le particolarità dell’opera edilizia.
Computi metrici
Un computo metrico di un opera consiste in una serie di voci che definiscono i singoli componenti edilizi quantificate secondo una specifica unità di misura. Inserire le misure è una di quelle attività leggermente noiose e poco attraenti…
Con un linguaggio specifico è possibile rendere efficiente l’inserimento manuale di queste quantità, in particolare se si desidera che i dati siano raggruppati in livelli strutturati.
Il linguaggio dei solai
Se l’opera in progetto è composta da diversi edifici a più piani, dovremo calcolare le superfici dei solai raggruppando i dati secondo la doppia classificazione piano/edificio. Saremo così in grado di fornire le superfici di solaio per ciascun piano, quelle totali per singolo edificio e quelle complessive per piano.
Un linguaggio semplice che descrive questa struttura informativa potrebbe essere questo:
solaio{
edificio = "A",
piano = 1,
superficie = 4.50*3.25,
}
La sintassi che riscontriamo leggendo il frammento di codice, si basa su un costrutto chiave = valore ciascuno separato con una virgola e racchiuso in un coppia di parentesi graffe.
I valori testo sono racchiusi tra doppi apici mentre i valori numerici utilizzano il punto e non la virgola per separare la parte decimale.
Vi anticipo che il codice precedente corrisponde alla sintassi di Lua, un linguaggio di programmazione libero e multi-piattaforma, più volte trattato sul blog.
Continuando a tagliare su misura il codice per renderlo perfettamente adatto ad esprimere le quantità che vorremmo computare, osserviamo che non ci occorre identificare i singoli solai di uno stesso piano di uno stesso edificio. Alla chiave superficie assegniamo allora non un singolo valore o espressione, ma un elenco di espressioni corrispondenti alla geometria dell’impalcato, per esempio (possiamo commentare il codice inserendo due trattini):
-- cambiamo nome all'oggetto :-)
solaiDiPiano{
edificio = "A",
piano = 1,
superficie = {
2*4.50*3.25, -- qui due solai uguali
3.80*3.25,
4.64*4.20 - 0.40*0.70, -- qui una detrazione di una botola!
4.24*(4.20 + 3.50),
5.50*3.60, -- la virgola finale è opzionale
}, -- ma rende più comode successive
} -- aggiunte di valori
Osservazioni operative
L’ambiente in cui si memorizza il codice è un editor di testo ASCII. La comodità sta nel fatto che i dati sono immediatamente disponibili su qualsiasi sistema operativo per eventuali modifiche o verifiche, e possiamo eseguire le operazioni con poca fatica.
Nel frattempo ho aggiunto altri dati come potete vedere dal prossimo frammento di codice:
solaiDiPiano{edificio="A", piano=1,
superficie = {
2*(1.60+3.60+2.07)*(4.345+4.245),
1.92*2.64,
3.60*(0.55+1.05)*2,
}
}
solaiDiPiano{edificio="A", piano=2,
superficie = {
2*(1.60+3.60+2.07)*(4.345+4.245),
1.92*2.64,
3.60*(0.55+1.05)*2,
}
}
solaiDiPiano{edificio="A", piano=3,
superficie = {
2*(1.65+3.60+2.12)*(4.42+4.32),
1.92*2.64,
3.60*(0.55+1.05)*2,
}
}
solaiDiPiano{edificio="B", piano=1,
superficie = {
2*(2.54+2.54+2.56+2.545)*(4.345+4.245),
2*1.00*2.64
}
}
solaiDiPiano{edificio="B", piano=2,
superficie = {
2*(2.54+2.54+2.56+2.545)*(4.345+4.245),
2*1.00*2.64
}
}
solaiDiPiano{edificio="C", piano=1,
superficie = {
2*(1.60+3.60+2.07)*(4.345+4.245),
1.92*2.64,
3.60*(0.55+1.05)*2,
}
}
solaiDiPiano{edificio="C", piano=2,
superficie = {
2*(1.60+3.60+2.07)*(4.345+4.245),
1.92*2.64,
3.60*(0.55+1.05)*2,
}
}
solaiDiPiano{edificio="C", piano=3,
superficie = {
2*(1.65+3.60+2.12)*(4.42+4.32),
1.92*2.64,
3.60*(0.55+1.05)*2,
}
}
Elaborare i dati
Ma come si elaborano i dati?
Il codice scritto corrisponde esattamente ad una serie di chiamate alla funzione Lua solaiDiPiano() a cui passiamo una tabella.
Eseguendo il codice, verranno calcolate le espressioni delle superfici e le istruzioni contenute nella funzione.
Elaborazione diretta
Proviamo a scrivere la funzione in modo da ottenere la superficie totale dei solai:
-- superficie totale
local totsup = 0
-- definizione della funzione
function solaiDiPiano(s)
-- campi in s:
-- s.superficie -> array di valori
-- sommo tutti i valori in s.superficie
-- e li inserisco nel totale
for _, val in ipairs(s.superficie) do
totsup = totsup + val
end
end
-- carico il file dati
dofile("solai.lua")
-- stampo il risultato
print(string.format("Superficie totale : %0.3f",totsup))
Una volta installato sul sistema Lua, inseriamo i dati dei solai così come si è deciso di descriverli nel file testo “solai.lua”. Salviamo in un secondo file il codice che li elabora “calcsuptot.lua”, ed infine apriamo il terminale o la console ed eseguiamo il comando:
> lua calcsuptot.lua
Fatto! La schermata rappresentativa dell’operazione in Windows è la seguente, dove si può notare l’uso del comando cd per spostarsi nella directory dove avevo salvato i due file.
Elaborazione strutturata
Diamo una definizione strutturata della funzione solaiDiPiano() in modo da costruire una tabella dati chiamata Solai che potremo leggere in modi diversi. Questa è la via sicuramente più flessibile e potente.
-- serve un contenitore per i dati:
local Solai = {}
-- creazione della tabella dati
function solaiDiPiano(s)
-- ricordiamo i nomi dei campi in s
-- s.edificio := nome edificio
-- s.piano := numero di piano
-- s.superficie := array di valori
-- se non esiste ancora creiamo
-- una tabella per edificio
-- rispetto al nome
-- es.: Solai.A
if not Solai[s.edificio] then
Solai[s.edificio] = {}
end
-- prendiamoci un riferimento più comodo
-- alla singola tabella edificio
local edificio = Solai[s.edificio]
-- calcoliamo la somma delle superfici
local suppiano = 0
for _, val in ipairs(s.superficie) do
suppiano = suppiano + val
end
-- intenderemo la tabella edificio
-- come un array dove l'indice sarà
-- il numero di piano ed il valore
-- corrispondente, la superficie
if edificio[s.piano] then
edificio[s.piano] = edificio[s.piano] + suppiano
else
edificio[s.piano] = suppiano
end
end
Fatto questo, potremo elaborare decine od anche migliaia di elementi si solaio. Tutti i dati saranno memorizzati nella tabella Solaio Solaio.
A questo punto scriviamo la funzione di reporting che opererà in lettura. Vogliamo stampare per esempio i totali di piano per edificio:
-- report piano/edificio
function reportPianoEdificio()
-- Solai contiene i dati in modo strutturato
-- Al primo livello ci sono le tabelle edificio
local totsup = 0
for nomeEd, arraysup in pairs(Solai) do
print(string.format("Edificio %s: --------------------", nomeEd))
-- stampiamo le superfici piano per piano
local totsupEd = 0
for level, sup in pairs(arraysup) do
totsupEd = totsupEd + sup
print(string.format("Piano %2d, superficie %10.3f", level, sup))
end
totsup = totsup + totsupEd
print("--------------------------------")
print(string.format("Tot. sup. edificio %s: %10.3f", nomeEd, totsupEd))
print("--------------------------------")
end
print("--------------------------------")
print(string.format("Tot. superfici %10.3f", totsup))
print("--------------------------------")
end
In console ottengo questo:
Se volessimo stampare le superfici piano per piano dovremo costruire una funzione in lettura di questo tipo:
-- report per piani
function reportPiani()
-- una tabella per le sup di piano
local suppiani = {}
-- ciclo per singolo edificio
-- primo livello della struttura dati Solaio
for nomeEd, arraySup in pairs(Solai) do
-- ciclo interno di lettura delle sup
for piano, sup in pairs(arraySup) do
if suppiani[piano] then
suppiani[piano] = suppiani[piano] + sup
else
suppiani[piano] = sup
end
end
end
-- stampa
local ts = 0
for level, sup in pairs(suppiani) do
ts = ts + sup
print(string.format("Livello %2d: sup = %10.3f",level,sup))
end
print("--------------------------")
print(string.format("Totale sup = %10.3f",ts))
end
--[[
-- l'output con i soliti dati è questo
Livello 1: sup = 463.233
Livello 2: sup = 463.233
Livello 3: sup = 290.833
--------------------------
Totale sup = 1217.299
--]]
Conclusioni
L’idea proposta è originale? No! Volendo, si possono fare molti esempi tratti dal mondo dell’informatica dove un linguaggio testuale descrive dati strutturati. Con Lua è semplice creare il proprio linguaggio ed elaborare i dati, pensiamo per esempio al caso più complesso riguardante la costruzione dei libretti dei ferri…
Naturalmente, potremo preparare report molto più professionali che non un semplice output in console, per esempio compilando un opportuno sorgente LaTeX per l’uscita in PDF, direttamente con le funzioni Lua di reporting.
Uno svantaggio consiste nella necessità di scrivere qualche linea di codice Lua, ma del resto questo consente la massima libertà di cucire la soluzione sul problema e non è poi così terribilmente difficile. A voi dunque l’onore e l’onere di rendere un po’ più attraente la stesura dei computi metrici!
Note tecniche
Il software occorrente per utilizzare la procedura è il seguente: un editor di testi, consiglio SciTE perché in grado di far eseguire il codice premendo semplicemente il tasto F5, e l’interprete Lua, quindi tutto software libero, gratuito e legalmente installabile anche in ambito professionale, infine un pizzico di fantasia.
Per imparare Lua non vi è niente di meglio del PiL.
Un saluto.


Pingback: Visto nel Web – 3 « Ok, panico