sabato, dicembre 21, 2013

Revit Add Ons

Tim Grimm di Revit Add-ons mi ha fatto una bella sorpresa offrendosi di ospitare gratuitamente un banner che rimanda al mio blog per darmi più visibilità.


Revit Add-ons è letteralmente una miniera di strumenti per Revit, sia a pagamento sia gratuiti, che permettono di migliorare il nostro flusso di lavoro con il software. Le recensioni sono essenziali e ben fatte e contribuiscono molto a sensibilizzare e guidare gli utenti alla scelta degli strumenti migliori per il loro lavoro senza troppi giri di parole.

Thanks Tim!

venerdì, dicembre 20, 2013

View Depth Override - Alcune considerazioni



Il grande Jeremy Tammik di The Building Coder mi ha fatto l'onore di pubblicare sul suo blog il mio codice relativo al View Depth Override sia per viste 2D sia per viste 3D.
Nei commenti, un lettore di nome Ning, ha delle perplessità riguardo alle coordinate che ho utilizzato nel codice, questa la mia risposta nel tentativo di dipanare i suoi dubbi.
E' una breve storia (ancora non conclusa per altro) del processo che mi ha condotto a determinate scelte per impostare il codice, la scrivo in inglese (perdonate gli erroracci) ma se qualcuno non capisse posso tradurla in italiano nei commenti... ogni aiuto o suggerimento in tal senso è ben accetto!

Questo quanto chiede Ning:

"hi Paolo and Jeremy,

i'm trying to understand that 3DView Depth Override stuff, by using my own simplified code, works OK for plan / section / elevation views, but i have trouble to understand the coordinate system in terms of relationship between 3DView's Cropbox and Outline used in BoundingBoxIntersectsFilter, i assume the followings:
1) Boundingbox of 3DView's Cropbox is in coordinate system on top of the computer screen in which Z is perpendicular to the computer screen
2) Outline used in BoundingBoxIntersectsFilter is in Revit coordinate system

a bit description in your blog will be great, perhaps Jeremy can give a more technical detailed explanation in the future"

Questa la mia risposta:

Hi Ning,
sorry for the late reply, I'll try to make myself clear about what you're asking.
When I tried to code this macro I was at the beginning of my "API journey" and I'm sure I wouldn't be making the same choices if I had to do it again from scratch.
You're assumptions are correct: View BoundingBox has to be transformed into absolute coordinates to work properly as an Outline.
All started with 2D views: view coordinates are realtive to each view and there are three vectors defining the space: the RightDirection (let's say local x axis), the UpDirection (local y axis) and ViewDirection (local z axis, which is orthogonal to the screen as you mentioned).
That said, I guess one can obtain the Outline necessary to the BoundingBoxFilter from here, taking a shortcut and simplyfing the code a bit, but still, you need to convert from local to absolute coordinates to build a proper Outline.
This is also important to implement the subfunction called "Integral", which collects all ElementIds in a series of smaller BoundingBoxes (200 subdivisions for each one of the three segments of the main BoundingBox), because in case of views that are not parallel to the edges of the screen, a single BoundingBox would generate errors in the selection.
When I began to study a macro for 3D views I decided to restrict the code only for perspective views because that made more sense to me; I tried to reuse as much as possible the code I had for 2D views, but I took a different approach to determine the Bounding Box: I choosed to consider the entire Bounding Box of the model (this is the part where Jeremy's blog comes in), then I rotated (it's better say projected, transformed) this overall BoundingBox "parellel" to the perspective view (but keeping the top and the bottom faces parallel to the ground) and then execute the same code for 2D Views.
It's a work in progress though, I couldn't find the Bounding Box of a perspective view as I did before for a 2D view, and that's an issue still opened since I hadn't look into it since I published the code. I'm open to all the help I can get :)
I hope this helped you in a better understanding of what's behind the code.

Cheers


-Paolo


If you are happy with my code you can show me some gratitude paying what you want on PayPal:

puntorevit@gmail.com

mercoledì, dicembre 18, 2013

External Command: Site XYZ Family In & Out



Questo external command esporta le coordinate delle famiglie riferite alle coordinate del Survey Base Point e per differenziarlo da quello precedente il file CSV ha un suffisso "-Site" ma viene sempre salvato sul desktop con il nome del progetto.

Ovviamente il comando considera la project location corrente e non tutte le altre che possono essere presenti.

Qui si trova il codice, qui la DLL, e qui l'ADDIN, i file sono da copaire qui:

C:\ProgramData\Autodesk\Revit\Addins\2014\

Potrebbe essere utile anche consultare questo articolo per sbloccare i file .dll

If you are happy with my code you can show me some gratitude paying what you want on PayPal:

puntorevit@gmail.com

External command: XYZ Family In & Out - Update






Ho apportato qualche modifica al codice del post precedente, la versione aggiornata si può trovare qui ed ora consente di aggiornare la posizione delle famiglie modificando il file CSV associato al progetto.
Ho corretto l'esportazione che ora utilizza il punto come separatore decimale così non si confonde con la "," del CSV.
Quando si vuole modificare una famiglia su host da CSV potrebbero verificarsi risultati inattesi poichè prevale la relazione che intercorre tra host e famiglia (quindi lo spostamento c'è ma avviene lungo l'host).

Qui invece l'external command con DLL e ADDIN che vanno copiati in questa directory:

C:\ProgramData\Autodesk\Revit\Addins\2014\

Potrebbe essere utile anche consultare questo articolo per sbloccare i file .dll
If you are happy with my code you can show me some gratitude paying what you want on PayPal:

puntorevit@gmail.com

lunedì, dicembre 16, 2013

External Command: Family XYZ Location Point to CSV


Questo comando esterno permette di ricavare un file CSV contenente per ciascuna riga le informazioni relative alle sole famiglie con un singolo punto di inserimento che vengono selezionate:

[Category] , [Family Name] , [ID] , [X] , [Y] , [Z]

Il file CSV viene salvato sul desktop con il nome del file del progetto. Con qualche modifica si può fare per tutte le famiglie di questo tipo senza intervenire con la selezione manuale.

Qui si può leggere il codice sorgente, da qui si può scaricare il file DLL e il relativo ADDIN che vanno copiati in questa directory:

C:\ProgramData\Autodesk\Revit\Addins\2014\

Potrebbe essere utile anche consultare questo articolo per sbloccare i file .dll
If you are happy with my code you can show me some gratitude paying what you want on PayPal:

puntorevit@gmail.com

mercoledì, dicembre 11, 2013

External Commands: Miter Joint By Picking - Lines Chain Total Length






Su richiesta ecco gli external commands di queste due macro che avevo pubblicato in precedenza qui e qui.

Lines Chain Total Length (addin) (dll)

Wall Miter Joint by Picking: (addin) (dll)

Tutti i file sono da copiare in questa directory:

C:\ProgramData\Autodesk\Revit\Addins\2014\

Potrebbe essere utile anche consultare questo articolo per sbloccare i file .dll

lunedì, dicembre 09, 2013

Formule utili per parametrizzare una tangente a due archi


Può tornare utile per parametrizzare dei profili o dei tracciati.

Update:

Nel caso si volesse trovare l'altra tangente non speculare a quella precedente, il metodo grafico da utilizzare è lo stesso ma le formule cambiano leggermente:



Chain Dimension

Per oggetti modello (muri e linee) esiste la possibilità di restituire la lunghezza totale di una concatenazione di elementi.
Questa funzionalità però non esiste per le linee di dettaglio, con questa macro è possibile ottenere la lunghezza delle linee selezionate (sia di modello sia di dettaglio), sia concatenate sia separate.
La macro tiene conto dell'unità di misura del progetto e restituisce il valore in metri se il sistema utilizzato è quello metrico e in piedi se è imperiale. Se serve posso fare l'external command.

Filled region on 3D Views - My EUR RTC 2013 Trick



Durante il Revit Technology Conference 2013 a Delft c'è stata una sessione di "Tips and Tricks", e alla fine ognuno poteva contribuire con un proprio suggerimento se lo desiderava.
Io ho descritto la procedura per inserire una filled region in tavola, ma senza Revit sotto mano, solo raccontadolo a parole, questo il vecchio post a cui facevo riferimento.
Sono stato deriso, preso per pazzo, criticato... io però credo sia worthsharing, meritevole di essere condiviso.

Un piccolo video per dimostrare un'applicazione possibile, come ad esempio creare delle filled region per delle viste 3D, senza ricorrere a stratagemmi più complessi.

giovedì, dicembre 05, 2013

Miter joint by picking






In questo video si vede come si possa cambiare il tipo di join terminali dei muri semplicemente cliccandoci sopra. Credit a Harry Mattison di Boost Your BIM da cui ho preso spunto.

WallJoinMiterByPick source code

mercoledì, dicembre 04, 2013

View Depth Override - the CAD side of the moon



Qualche tempo fa mi è stato chiesto nei commenti come poter unificare le linee delle diverse tonalità di grigio una volta esportate da Revit dopo avere utilizzato il View Depth Override.
Per prima cosa si deve impostare l'esportazione dei formati CAD da Revit su TrueColour e utilizzare le impostazioni byLayer e le sostituzioni byEntity.
Una volta in AutoCAD si deve caricare il GreyMerge.lsp alla riga di comando digitando "appload".
Digitando poi GREYMERGE si richiama il comando che inserisce i due layer "_Grey-1" e "_Grey-2" attribuendo loro rispettivamente i colori RGB 128,128,128 e 192,192,192.
Successivamente gli oggetti vengono spostati di layer concordemente al loro colore, si potrà quindi impostare tutto su byLayer.

GreyMerge.lsp

Trovare il raggio di un arco ribassato



Qualche volta capita di dover realizzare dei componenti parametrici con la forma in figura di cui però non si conosce esattamente il valore del raggio dell'arco, come ad esempio da un rilievo.
Mentre la costruzione geometrica è abbastanza semplice, la parametrizzazione può essere più complessa se non si tengono presente alcune proprietà geometriche dei triangoli e delle circonferenze.
Sapendo che l'angolo alla circonferenza del diametro di un cerchio è sempre a 90°, usando il teorema di Pitagora e le proporzioni tra triangoli simili è possibile ricavare in modo abbastanza semplice i parametri che servono a definire il componente come da formula riportata in figura.




venerdì, novembre 29, 2013

giovedì, novembre 21, 2013

Auto Floor Maker - External Command


Per coloro i quali volessero provare Auto Floor Maker ma non hanno dimestichezza con le macro, ho creato l'External Command e il relativo addin manifest, potete usarlo a vostro rischio e pericolo :D

Se copiate i due file in questa posizione dovrebbe comparire tra gli External Command al primo riavvio di Revit 2014:

C:\ProgramData\Autodesk\Revit\Addins\2014

AutoFloorMaker.addin

AutoFloorMaker.dll

Ecco un video di come usare il comando:



Probabilmente sarà necessario togliere il blocco al file AutoFloorMaker.dll cliccando con il tasto destro > Proprietà e poi "Annulla blocco" in basso a destra e poi riavviate Revit:


Primavera - Update


Ecco un aggiornamento del progetto "primavera" di Antonio Citterio Patricia Viel and Partners.


lunedì, novembre 18, 2013

Drawing shadows - test




Ho appena scoperto la possibilità di tracciare le ombre di oggetti solidi in Revit, ho provato a giocare con il codice presente nel developer manual delle API 2014.
Interessante....

Scavare una superficie topografica



Una delle cose che non si può fare correttamente in Revit è scavare una superficie topografica, ossia creare un volume interrato e ricoprirlo di nuovo con il terreno.
Si possono creare delle famiglie in-place, oppure, più elegantemente, copiare la superficie topografica in un file esterno da collegare, ritagliare la superficie topografica seguendo l'impronta della piattaforma (pad) e impostare per quel file la profondità del retino della topografia pari alla quota dell'estradosso della soletta del volume interrato.
Nelle viste 2D si può vedere che si può intervenire facendo l'override localmente degli elementi in vista e in sezione delle superfici topografiche interessate. In questo modo si può evitare di ricorrere alle filled regione ( i retini) per mascherare la parte di terreno di riporto.

inFORM - Interacting With a Dynamic Shape Display


Fantastico!

sabato, novembre 16, 2013

3D View Tag



In questo post dal blog di Steve Stafford Revit OpEd si ricorda che non si dispone ancora di annotazioni in grado di segnalare la posizione delle viste 3D.
Ho preso spunto da qui per poter creare una macro che inserisse una famiglia di modello generico per ciascuna vista di prospettiva, orientandola correttamente e riportando il nome della vista.
Ovviamente è solo l'effetto finale quello che avevo in mente, non è per niente simile alle annotazioni di Revit che si aggiornano automaticamente con le proprietà delle viste collegate, però funziona per quello che abbiamo a disposizione ora.

Ecco il codice sorgente e la famiglia utilizzata (c'è da inserire un parametro condiviso ma credo siate in grado di ricavarlo da soli):

Codice sorgente 2014

Famiglia GM-3DView.rfa

3D View Depth Override - Update


In questo nuovo video mostro come funziona la versione del View Depth Override per le viste prospettiche.
Dato che non è possibile azionare le macro da una vista prospettica ho trovato un sistema per aggirare il problema.
Con la macro ViewListWrite viene creato un file di testo sul desktop chiamato [MyProjectName]-3DViews.txt, in cui vengono elencate per ciascuna riga le viste di prospettiva presenti nel progetto.
Con la macro ViewListRead viene eseguito il View Depth Override tante volte quante sono le viste elencate nel file di testo. Questo file di testo è editabile dall'utente ed è quindi possibile decidere su quali viste far eseguire la macro.
Il codice è migliorato dalla prima versione, grazie anche a degli spunti che ho trovato sul blog di Jeremy Tammik the Building Coder, in particolare per l'uso del Linq per determinare i punti di massimo e minimo.
Ho introdotto anche l'uso del Transform per rendere più leggibili le operazioni di calcolo dei punti del BoundingBoxXYZ orientato come la vista, la qual cosa si può felicemente applicare alla versione 2D del View Depth Override.

Si tratta sempre di un work in progress, i commenti sono bene accetti per cercare di migliorare :)

Codice sorgente:
Versione 2012
Versione 2014

venerdì, novembre 15, 2013

Step by step how to use macro code samples


Alcuni lettori non hanno molta dimestichezza con i codici delle macro che rendo pubblici e vorrebbero utilizzarli, così ho realizzato questo piccolo video per guidare passo passo nella creazione delle macro.
Nell'esempio ho utilizzato il codice di Auto Floor Sketch - Update


  1. Creare un nuovo modulo in C#
  2. Creare una nuova macro
  3. Copiare gli using statements all'inizio del codice nell'editor delle macro
  4. Copiare il codice della macro dopo quello generato automaticamente da Revit
  5. Controllare che non ci siano errori
  6. Compilare il codice
  7. Se non ci sono errori adesso si può utilizzare la macro

Gli using statements che inserisco all'inizio del codice sono generalmente i seguenti:

using System;
using System.Collections.Generic;
using Autodesk.Revit.DB;
using Autodesk.Revit.DB.Events;
using Autodesk.Revit.ApplicationServices;
using Autodesk.Revit.UI;
using Autodesk.Revit.UI.Selection;
using Autodesk.Revit.Collections;
using System.IO;
using System.Linq;


Spero possa essere utile.

giovedì, novembre 14, 2013

Auto Floor Sketch - Update


Questo è un aggiornamento della macro che ora aggiunge dei vuoti nel pavimento di finitura basati sul perimetro degli eventuali altri oggetti che definiscono le chiusure dei locali.
In particolare per i locali sottotetto considera l'altezza di calcolo dei livelli pari a zero temporaneamente per creare il pavimento sulla massima estensione possibile, dopo di che lo riporta nella posizione scelta dall'utente.
E' leggermente più lento ma è più preciso. I locali che non sono propriamente racchiusi non vengono considerati, mentre i locali ottenuti anche dalle linee di delimitazione invece si.

mercoledì, novembre 13, 2013

Ordinare Alfabeticamente i Riquadri di Definizione - Sort Scope Boxes Alphabetically

Una delle seccature maggiori in Revit riguarda l'impossibilità di ordinare alfabeticamente alcuni oggetti che invece seguono l'ordine di creazione.
Fra questi ci sono i riquadri di definizione, gli scope boxes, che quando sono molti obbligano gli utenti a scrollare in tutta la lista senza avere la possibilità di ritrovare in ordine alfabetico i nomi che sono stati assegnati ai singoli oggetti.
In realtà non è possibile fare molto da questo punto di vista se non adeguarsi a come Revit ripropone questo elenco di oggetti (a quanto pare in base all'ID dell'oggetto che, anche se può variare, purtroppo non può essere modificato direttamente dall'utente).
Per questo motivo ho creato una macro che aggiunge in automatico al nome degli scope boxes un prefisso numerico crescente che corrisponde alla posizione di ciascun oggetto nell'elenco.
Il flusso di lavoro potrebbe essere il seguente: dopo aver creato gli scope boxes che servono, si assegna contestualmente un nome significativo per poterli distinguere. Si effettua un'associazione alle viste di pianta e solo dopo si procede con la macro.

Partendo da una situazione di questo tipo, con i nomi non in ordine alfabetico:



Facendo agire la macro si ottiene questo:


In questo modo è possibile almeno rendersi conto di quale "numero" si deve usare a riferimento per quel tipo particolare di piante rendendo più rapido rintracciare gli scope boxes nell'elenco.

Di seguito il codice sorgente per Revit 2012.



venerdì, novembre 08, 2013

Superficie Topografica da linee - la mia versione



Poco tempo fa Matt Harrison di Boost Your BIM ha pubblicato sull'App Exchange di Autodesk un add-in per la creazione di superfici topografiche direttamente selezionando delle linee di modello in Revit.
Nel mio percorso per imparare ad utilizzare le API di Revit ho cercato di replicare il comportamento di questa add-in e ho aggiunto la possibilità di salvare sul desktop un file .CSV con le coordinate dei punti espresse in millimetri.
Non so se sia esattamente questo il tipo di codice che ha usato Matt, ma dall'esecuzione posso notare che il risultato è persino più preciso di quello che si otterrebbe collegando un DWG con le linee di modello.
Resta sempre la limitazione di non poter realizzare direttamente superfici concave per via dell'algoritmo di triangolazione utilizzato da Revit.



using System;
using System.Collections.Generic;
using Autodesk.Revit.DB;
using Autodesk.Revit.DB.Events;
using Autodesk.Revit.ApplicationServices;
using Autodesk.Revit.UI;
using Autodesk.Revit.UI.Selection;
using Autodesk.Revit.Collections;
using System.Diagnostics;
using System.IO;
using System.Linq;

//Constant to make a conversion from imperial to metric
const double _FeetTomm = 304.8;
//Here is how we can convert units
public static double FeetTomm(double ftValue)
{
return ftValue * _FeetTomm;
}
//New class to limit the selection only to Model Lines
public class LinePickFilter : ISelectionFilter
        {
            public bool AllowElement(Element e)
            {
                return (e.Category.Id.IntegerValue.Equals(
                    (int)BuiltInCategory.OST_Lines));
            }

            public bool AllowReference(Reference r, XYZ p)
            {
                return false;
            }
        }
//Here starts the code
public void TopoFromCurves()
{
UIDocument uidoc = this.ActiveUIDocument;
Document doc = uidoc.Document;
Selection sel = uidoc.Selection;
LinePickFilter LinePickFilter = new LinePickFilter();
//Prompt the user to select lines
IList curves = sel.PickObjects(ObjectType.Element,
LinePickFilter, "Select source lines for topo surface");
IList p =new List();
//Determining the path of the .CSV file
string dtop = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
string path = String.Concat(dtop, "\\" +
doc.Title.Remove(doc.Title.Length - 4) + "-TopoFromLines.csv");
string output = "";
//We need to start a transaction in order to modify the database of the file
//The title will be visible in the commands list and the journal file
//the using () structure prevents bad behaviours from happening
using (Transaction t = new Transaction(doc, "Topo From Lines"))
{
t.Start();
foreach (Reference r in curves)
{
//Cast each element in the selection as ModelCurves
//to have access to specific properties
ModelCurve e = doc.GetElement(r) as ModelCurve;
foreach (XYZ q in e.GeometryCurve.Tessellate())
{
//Collect all the points from the lines
p.Add(q);
}
}
//Here writes the .CSV file converting from decimal feets to mm
//replacing the comma with a point as a decimal separator
using (StreamWriter sw = new StreamWriter(path, false))
{
foreach (XYZ v in p)
{
output = FeetTomm(v.X).ToString().Replace(",", ".") + ","
+ FeetTomm(v.Y).ToString().Replace(",", ".") + ","
+ FeetTomm(v.Z).ToString().Replace(",", ".");
sw.WriteLine(output);
}
}
//Create the TopoSurface, Refresh and commit the transaction
doc.Create.NewTopographySurface(p);
uidoc.RefreshActiveView();
t.Commit();
}
}

mercoledì, novembre 06, 2013

Trovare l'inclinazione di un piano partendo da 3 quote - metodo grafico


Trovare l'inclinazione di un pavimento è importante per evitare di ricorrere alla modifica degli elementi secondari, in questo modo saremo certi che il pavimento risultante abbia spessore costante e mantenga la capacità di fungere da host per gli elementi ringhiera, senza dare errori nelle quantità dei materiali.
Geometricamente un piano è definito quando conosciamo le quote (Z) di tre punti che vi appartengono.
Nell'immagine sopra ho riportato il metodo grafico per ottenere la linea di massima pendenza del piano.
Si può sfruttare il principio del metodo grafico anche senza conoscere le quote esatte, come spiegherò in un post successivo


lunedì, novembre 04, 2013

Linee di riferimento - Parametrizzare l'angolo di un solido



Nell'editor delle famiglie possiamo utilizzare le linee di riferimento per vincolare le linee che costituiscono il profilo di un solido di estrusione ad esempio per potere controllare l'angolo tra queste linee e dei piani di riferimento.
Il concetto chiave è che la rotazione viene controllata da un parametro angolo su un particolare oggetto, la linea di riferimento, che viene individuata dall'intersezione di due piani.
Le estremità delle linee di riferimento si possono vincolare alle intersezioni fra i piani utilizzando il comando allinea e successivamente bloccando il lucchetto che compare per stabilire il vincolo.
Per tracciare la linea di riferimento è meglio partire da un punto qualsiasi e terminare in corrispondenza dell'intersezione fra i piani di riferimento per favorire le quote automatiche (di default sono nascoste ma sono alla base della relazionalità geometrica di Revit).
Per posizionare la quota angolare invece è meglio partire dal piano di riferimento che resterà fisso e poi cliccare sulla linea di riferimento.
Quando si entra in modalità di tracciamento si deve fare attenzione a selezionare per ciascuna linea il piano di lavoro appropriato: aiutandosi con il tasto TAB e deselezionando dalla toolbar delle opzioni il concatena, si può realizzare il tipo di relazione desiderata.
Questo tipo di procedura si può seguire anche per i componenti di dettaglio.

giovedì, ottobre 31, 2013

Automatic Floor Sketch


Partendo da una selezione dei locali traccia i pavimenti di finitura corrispondenti. Considera solo gli elementi che delimitano il locale.

mercoledì, ottobre 23, 2013

AEC You and Me

Blog interesessantissimo di Julien Benoit, che ho avuto il piacere di conoscere al Revit Technology Conference di Delft.
Una persona squisita, intelligente e appassionata del proprio lavoro come si può facilmente capire dai primi post che sta pubblicando in questi giorni.
Julien è uno dei moderatori di Revitforum.org, collaboratora per uno dei maggiori general contractor in Francia, Bouygues Construction.
Sta cominciando a condividere i progressi che sta facendo nell'esplorazione delle potenzialità di Dynamo nel lavoro di tutti i giorni.
Da seguire.

martedì, ottobre 22, 2013

Text Type Replacement - Codice Sorgente

Visto l'interesse al post precedente pubblico il codice sorgente per la versione 2012




giovedì, ottobre 17, 2013

View Depth Override - 3D


Questa volta sto lavorando sulle viste 3D in prospettiva degli esterni, come si vede dal video l'algoritmo non è ancora perfetto a causa degli errori introdotti dall'angolo tra il punto di vista e il modello.
Ho trovato però un modo più elegante ed efficiente di eseguire i calcoli anche per la macro delle viste 2D.
La fase successiva interesserà le viste 3D degli interni, e quando finalmente sarò pronto per l'Addin si potrà pensare anche all'aggiornamento automatico delle viste dove viene applicato il comando.

Analytical Tracer - Codice Sorgente

Questo il codice sorgente per la versione 2014, funziona solo per elementi quali pilastri strutturali e travi lineari.
Nella versione 2012 purtroppo non sono riuscito a capire come mai non riuscisse a tracciare correttamente le aste analitiche dei pilastri.
Si potrebbero anche differenziare i tipi di linea per travi e pilastri ma occorre differenziarli poi anche nella tabella dell'esportazione in DWG.

Qui si può scaricare il file sorgente:




If you are happy with my code you can show me some gratitude paying what you want on PayPal:

puntorevit@gmail.com

martedì, ottobre 15, 2013

Analytical Tracer


Con questa macro si possono esportare dei modelli unifilari per elementi strutturali rettilinei che altrimenti risulterebbero divisi in 3 segmenti per ciascuna asta del modello analitico.
Ho fatto una prova veloce con la 2014 si accettano suggerimenti :)

lunedì, ottobre 14, 2013

View Depth Override 2014 - Codice Sorgente

A questo link potete trovare il codice per la versione 2014, in questo caso si possono sostituire graficamente anche i motivi di superficie degli oggetti ma non è possibile agire sulle ombre.



TextNote Type Replacement


Ho dovuto scrivere questa piccola macro per controllare che i testi con lo stesso contenuto inseriti su più tavole avessero il tipo associato corretto.
Morale: non usate i testi!
PLEASE DON'T USE TEXTNOTES!!!

mercoledì, ottobre 09, 2013

View Depth Override - Codice Sorgente


Ecco il codice sorgente per il View Depth Override. Per quelli che non conoscono le API ancora un po' di pazienza e pubblicherò l'add-in per il comando, quella sopra sarà l'icona che pensavo di utilizzare, rende l'idea?

Tanto per cominciare è scritto in C#, testato su Revit Architecture 2012, ecco gli using statements da inserire all'inizio:

using System;
using System.Collections.Generic;
using Autodesk.Revit.DB;
using Autodesk.Revit.UI;
using System.Linq;

Ed ecco il codice vero e proprio, ho inserito dei commenti in inglese per renderlo comprensibile a più persone, nel caso non fosse chiaro chiedete e proverò a spiegarmi meglio:

private XYZ MaxVertex2(XYZ a, XYZ b)
        {
            //Given two points determines the maximum of the Bounding Box that encloses them
            double X = a.X;
            double Y = a.Y;
            double Z = a.Z;
            if (Math.Round(b.X, 5) > X)
                X = b.X;
            if (Math.Round(b.Y, 5) > Y)
                Y = b.Y;
            if (Math.Round(b.Z, 5) > Z)
                Z = b.Z;
            XYZ max = new XYZ(X, Y, Z);
            return max;
        }
        private XYZ MinVertex2(XYZ a, XYZ b)
        {
            //Given two points determines the minimum of the Bounding Box that encloses them
            double X = a.X;
            double Y = a.Y;
            double Z = a.Z;
            if (Math.Round(b.X, 5) < X)
                X = b.X;
            if (Math.Round(b.Y, 5) < Y)
                Y = b.Y;
            if (Math.Round(b.Z, 5) < Z)
                Z = b.Z;
            XYZ min = new XYZ(X, Y, Z);
            return min;
        }
        private ICollection Integral(XYZ min1, XYZ max1, XYZ min2, XYZ max2)
        {
            //If the view is not parrallel to X or Y axis in Global Coordinates,
            //the selecting process is done using an integral approach
            //each segment is subdivided into a high number of subdivisions (200)
            //and smaller bounding boxes are used to filter the objects
            //that's the reason why with a non-parallel view the command is slower
            //This is the list of ElementId created and immediatly cleared
            ICollection ids = new FilteredElementCollector(this.ActiveUIDocument.Document)
            .WhereElementIsNotElementType()
            .ToElementIds();
            ids.Clear();
            foreach (Document doc in this.Application.Documents)
            {
                int subdivisions = 200;
                //Here determines the minimum and the maximum point for the segment based on the four vertices
                //that have been passed from the other function
                XYZ a = MinVertex2(min1, max1);
                XYZ a1 = a;
                XYZ b = MaxVertex2(min1, max1);
                XYZ c = MinVertex2(min2, max2);
                XYZ d = MaxVertex2(min2, max2);
                XYZ increment = (d - b) / subdivisions;
                for (int i = 0; i < subdivisions; i++)
                {
                    //This is tricky: sometimes if the view is perfectly parallel something
                    //about the vertices goes wrong (I guess there's a small tolerance)
                    //Anyway to reduce the amount of calculations if the coordinates are the same
                    //at the fifth decimal digit I assumed the coordinates to be equal
                    //I know it isn't perfect but it worked for me
                    if (Math.Round(a.X, 5) == Math.Round(b.X, 5) || Math.Round(a.Y, 5) == Math.Round(b.Y, 5))
                    {
                        i = subdivisions + 1;
                        a = MinVertex2(a1, d);
                        b = MaxVertex2(a1, d);
                    }
                    Outline ol = new Outline(a, b);
                    if (ol.IsEmpty == false)
                    {
                        //Here comes the filtering part where I tried to avoid all kinds of objects
                        //that are not useful for this task because they can't be overridden
                        //such as Element Types or Sketches of Floors/Roofs/ ceilings and so on
                        BoundingBoxIntersectsFilter BBIIF = new BoundingBoxIntersectsFilter(ol);
                        IEnumerable elems = new FilteredElementCollector(doc)
                        .WherePasses(BBIIF)
                        .WhereElementIsNotElementType()
                        .WhereElementIsViewIndependent()
                        .Cast()
                        .Where(q => q.Category != null && q.Category.HasMaterialQuantities);
                        if (elems.Count() > 0)
                        {
                            foreach (Element e in elems)
                            {
                                ids.Add(e.Id);
                            }
                        }
                    }
                    else
                    {
                        a = a + increment;
                        b = b + increment;
                    }
                    a = a + increment;
                    b = b + increment;
                }
            }
            return ids;
        }
        private ICollection IntegralCollection(View view, int i)
        {
            //Here is where the coordinates of the Bounding Box of the view are calculated
            //I don't like that this calculations are repeted each time this function is called (one for each segment)
            //it could be done more efficiently and for sure more clearly using the Transform...
            //but I didn't even know what that was when I recorded the video
            //the double scale is set to 1 because at first I started from the UV Bounding Box,
            //which contains also annotations and not just the model categories
            //I then used the Bounding BOX XYZ and reused the code I wrote before
            XYZ CurrentViewOrigin = view.Origin;
            double scale = 1;
            XYZ VRight = view.RightDirection;
            XYZ VUp = view.UpDirection;
            XYZ Vdir = view.ViewDirection;
            XYZ Vmin = view.CropBox.Min;
            XYZ Vmax = view.CropBox.Max;
            //I used letters for the Vertices of the main Bounding Box
            //rather then numbers for the inner box that defines the middle segment
            //I know this part looks messy but it was good to refresh some algebra concepts :)
            //here is were I should use the Transform
            XYZ Va = new XYZ(CurrentViewOrigin.X + scale * (Vmin.X * VRight.X + Vmin.Y * VUp.X) + Vmax.Z * Vdir.X, CurrentViewOrigin.Y + scale * (Vmin.X * VRight.Y + Vmin.Y * VUp.Y) + Vmax.Z * Vdir.Y, CurrentViewOrigin.Z + scale * (Vmin.X * VRight.Z + Vmin.Y * VUp.Z) + Vmax.Z * Vdir.Z);
            XYZ Vb = new XYZ(CurrentViewOrigin.X + scale * (Vmin.X * VRight.X + Vmax.Y * VUp.X) + Vmax.Z * Vdir.X, CurrentViewOrigin.Y + scale * (Vmin.X * VRight.Y + Vmax.Y * VUp.Y) + Vmax.Z * Vdir.Y, CurrentViewOrigin.Z + scale * (Vmin.X * VRight.Z + Vmax.Y * VUp.Z) + Vmax.Z * Vdir.Z);
            XYZ Vc = new XYZ(CurrentViewOrigin.X + scale * (Vmax.X * VRight.X + Vmax.Y * VUp.X) + Vmax.Z * Vdir.X, CurrentViewOrigin.Y + scale * (Vmax.X * VRight.Y + Vmax.Y * VUp.Y) + Vmax.Z * Vdir.Y, CurrentViewOrigin.Z + scale * (Vmax.X * VRight.Z + Vmax.Y * VUp.Z) + Vmax.Z * Vdir.Z);
            XYZ Vd = new XYZ(CurrentViewOrigin.X + scale * (Vmax.X * VRight.X + Vmin.Y * VUp.X) + Vmax.Z * Vdir.X, CurrentViewOrigin.Y + scale * (Vmax.X * VRight.Y + Vmin.Y * VUp.Y) + Vmax.Z * Vdir.Y, CurrentViewOrigin.Z + scale * (Vmax.X * VRight.Z + Vmin.Y * VUp.Z) + Vmax.Z * Vdir.Z);
            XYZ Ve = new XYZ(CurrentViewOrigin.X + scale * (Vmin.X * VRight.X + Vmin.Y * VUp.X) + Vmin.Z * Vdir.X, CurrentViewOrigin.Y + scale * (Vmin.X * VRight.Y + Vmin.Y * VUp.Y) + Vmin.Z * Vdir.Y, CurrentViewOrigin.Z + scale * (Vmin.X * VRight.Z + Vmin.Y * VUp.Z) + Vmin.Z * Vdir.Z);
            XYZ Vf = new XYZ(CurrentViewOrigin.X + scale * (Vmin.X * VRight.X + Vmax.Y * VUp.X) + Vmin.Z * Vdir.X, CurrentViewOrigin.Y + scale * (Vmin.X * VRight.Y + Vmax.Y * VUp.Y) + Vmin.Z * Vdir.Y, CurrentViewOrigin.Z + scale * (Vmin.X * VRight.Z + Vmax.Y * VUp.Z) + Vmin.Z * Vdir.Z);
            XYZ Vg = new XYZ(CurrentViewOrigin.X + scale * (Vmax.X * VRight.X + Vmax.Y * VUp.X) + Vmin.Z * Vdir.X, CurrentViewOrigin.Y + scale * (Vmax.X * VRight.Y + Vmax.Y * VUp.Y) + Vmin.Z * Vdir.Y, CurrentViewOrigin.Z + scale * (Vmax.X * VRight.Z + Vmax.Y * VUp.Z) + Vmin.Z * Vdir.Z);
            XYZ Vh = new XYZ(CurrentViewOrigin.X + scale * (Vmax.X * VRight.X + Vmin.Y * VUp.X) + Vmin.Z * Vdir.X, CurrentViewOrigin.Y + scale * (Vmax.X * VRight.Y + Vmin.Y * VUp.Y) + Vmin.Z * Vdir.Y, CurrentViewOrigin.Z + scale * (Vmax.X * VRight.Z + Vmin.Y * VUp.Z) + Vmin.Z * Vdir.Z);
            XYZ V1 = Ve + (Va - Ve) * 2 / 3;
            XYZ V2 = Vf + (Vb - Vf) * 2 / 3;
            XYZ V3 = Vg + (Vc - Vg) * 2 / 3;
            XYZ V4 = Vh + (Vd - Vh) * 2 / 3;
            XYZ V5 = Ve + (Va - Ve) / 3;
            XYZ V6 = Vf + (Vb - Vf) / 3;
            XYZ V7 = Vg + (Vc - Vg) / 3;
            XYZ V8 = Vh + (Vd - Vh) / 3;
            //This function returns a list of ElementId to be overridden depending on which one of
            //the three segments the objects fall in
            ICollection list = new FilteredElementCollector(ActiveUIDocument.Document)
            .WhereElementIsNotElementType()
            .ToElementIds();
            list.Clear();
            if (i == 0)
            {
                list = Integral(Va, V2, Vd, V3);
            }
            else
            {
                if (i == 1)
                {
                    list = Integral(V1, Vf, V4, Vg);
                }
                else
                {
                    list = Integral(V5, Vf, V8, Vg);
                }
            }

            return list;
        }
        public void ViewDepthOverride()
        {
            //known issues: doesn't work with linked files and 3D Views
            UIDocument uidoc = this.ActiveUIDocument;
            Document doc = uidoc.Document;
            //Creates the lists of ElementId to pass to the Projection Color Override by Element
            //those are just empty container at the moment
            ICollection ids0 = new FilteredElementCollector(doc).OfCategory(BuiltInCategory.OST_Levels).ToElementIds();
            ICollection ids1 = new FilteredElementCollector(doc).OfCategory(BuiltInCategory.OST_Levels).ToElementIds();
            ICollection ids2 = new FilteredElementCollector(doc).OfCategory(BuiltInCategory.OST_Levels).ToElementIds();
            ids0.Clear();
            ids1.Clear();
            ids2.Clear();
            View CurrentView = doc.ActiveView;
            //It works fine for 2D views, building sections and elevations for example
            //it should work also with floor plans and even tilted Detail Views
            //but it wasn't my goal when I started
            //won't work for a 3D View
            int clip = CurrentView.get_Parameter(BuiltInParameter.VIEWER_BOUND_FAR_CLIPPING).AsInteger();
            //If the far clipping is not active the default depth is 10 feet and won't work correctly
            if (clip == 0)
            {
                TaskDialog.Show("View Depth Override", "In order to use this macro far clipping must be activated.");
            }
            else
            {
                //If the far clipping is active then the view depth can be subdivided into 3 segments:
                //foreground (0)
                //middle (1)
                //background (2)
                ids0 = IntegralCollection(CurrentView, 0);
                ids1 = IntegralCollection(CurrentView, 1);
                ids2 = IntegralCollection(CurrentView, 2);
                //Just a check to handle some common errors, for instance not even one
                //ElementId was found in the foreground view interval
                if (ids0.Count == 0)
                {
                    TaskDialog.Show("View Depth Override", "Something went wrong in the closer segment.\n\nPlease adjust the view depth to include some objects.");
                    ElementId e = new FilteredElementCollector(doc).OfCategory(BuiltInCategory.OST_Walls).FirstElement().Id;
                    ids0.Add(e);
                    ids1.Add(e);
                    ids2.Add(e);
                }
                else
                {
                    //Again just a check to handle some common errors, in this case not even one
                    //ElementId was found in the background view interval
                    //because the view depth is too much rather then just enough to enclos
                    //the objects in the model
                    if (ids2.Count == 0)
                    {
                        TaskDialog.Show("View Depth Override", "Something went wrong in the farther segment to be overridden in Grey 192.\n\nPlease check that the view depth in the current view is just enough to include the objects you need.");
                        ElementId e = new FilteredElementCollector(doc).OfCategory(BuiltInCategory.OST_Walls).FirstElement().Id;
                        ids2.Add(e);
                        ids1.Add(e);
                    }
                }
            }
            //Begins the transaction to override the elements
            using (Transaction t = new Transaction(doc, "View Depth Override"))
            {
                t.Start();
                while (ids0.Count > 0)
                {
                    //Stores the color for the foreground
                    Color Color0 = CurrentView.get_ProjColorOverrideByElement(ids0);
                    if (ids1.Count != 0)
                    {
                        //Overrides the middle segment
                        CurrentView.set_ProjColorOverrideByElement(ids1, new Color((byte)128, (byte)128, (byte)128));
                    }
                    else
                    {
                        //Just a precaution, not sure it is really necessary
                        TaskDialog.Show("View Depth Override", "Something went wrong in the middle segment to be overridden in Grey 128.\n\nPlease check that the view depth in the current view is just enough to include the objects you need.");
                        break;
                    }
                    if (ids2.Count != 0)
                    {
                        CurrentView.set_ProjColorOverrideByElement(ids2, new Color((byte)192, (byte)192, (byte)192));
                    }
                    else
                    {
                        //Overrides the background segment
                        TaskDialog.Show("View Depth Override", "Something went wrong in the farther segment to be overridden in Grey 192.\n\nPlease check that the view depth in the current view is just enough to include the objects you need.");
                        break;
                    }
                    //Resets the foreground color in case of objects overlapping
                    //foreground and middle segment
                    CurrentView.set_ProjColorOverrideByElement(ids0, Color0);
                    break;
                }
                doc.Regenerate();
                uidoc.RefreshActiveView();
                t.Commit();
            }
        }  


martedì, ottobre 08, 2013

View Depth Override

Da qualche tempo mi sto interessando più da vicino al mondo della personalizzazione di Revit attraverso l'implementazione delle API.
Una dei primi comandi su cui sto lavorando è il View Depth Override ossia la sostituzione automatica delle linee di proiezione degli oggetti in funzione della profondità di campo della vista.

Qui c'è un video dimostrativo:



Il concetto è semplice: per viste di sezione o prospetto, si imposta la profondità della vista e si esegue il comando. La profondità della vista viene divisa in tre settori (primo piano, intermedio e sfondo), vengono effettuate delle sostituzioni grafiche (grigio 128 per il settore intermedio e grigio 192 per quello di sfondo) per simulare la profondità della vista.
Il comando viene eseguito anche se non ci sono oggetti in primo piano, quindi la posizione della vista rispetto al modello ha effettivamente rilevanza per il risultato finale.
Al momento non funziona per i file collegati ed è un comando di tipo "fire and forget" ossia viene eseguito una volta e poi non si aggiorna automaticamente se intervengono cambiamenti nel modello, ma non escludo si possa intervenire per eliminare questi inconvenienti.
Se interessa posso pubblicare il comando ma devo prima testarlo sulle release successive, tenuto conto che lo faccio più per passione e non intendo diventare un programmatore :)

Update qui!

sabato, settembre 28, 2013

Revit Technology Conference 2013 - Giorno 2

La giornata è cominciata con una piccola dimostrazione di forza di Autodesk, in verità sotto l’evocativo titolo della lezione “quando le famiglie diventeranno coscienti” sono stati mostrati i risultati di un progetto di ricerca interno ad Autodesk (nome in codice Honeycomb, nido d'ape) che cerca di fondere insieme i benefici di un approccio tradizionale alla creazione di famiglie con quello più analitico attraverso script esterni o procedure più complesse (leggi varie implementazioni di Dynamo o più specifici linguaggi di programmazione).
Il concetto è che la maggior parte di questi comandi esterni implementati attraverso le API oppure attraverso la programmazione visuale di Dynamo, sono poco affidabili in quanto non vengono aggiornati costantemente, sono sotto questo aspetto contrari alla natura specifica di Revit. Inoltre quando il file del progetto viene fatto circolare al di fuori del proprio studio e finisce ad un consulente che non possiede questi particolari script, queste funzionalità aggiuntive cessano di esistere, non sono quindi replicabili. Il progetto Honeycomb vorrebbe quindi integrare la leggerezza di un semplice codice all’interno della tecnologia di un progetto o incorporare dei comportamenti all’interno dei diversi componenti, siano essi di sistema oppure no, per poter garantire la congruenza di comportamento attraverso il passaggio di file da uno studio ad un altro ad esempio.
Le implicazioni potrebbero essere molteplici: la prima applicazione utile che mi è venuta in mente potrebbe essere quella di compilare un abaco delle finiture per i locali e far in modo che il materiale di finitura dei muri possa cambiare automaticamente in accordo con quanto definito nell’abaco. Sono stati portati esempi di componenti autoadattanti che sono molto più performanti di una serie di vincoli che possiamo esplicitare in una famiglia ad esempio.
Non ho apprezzato molto l’intento di Autodesk in questo senso perché sono state mostrate delle caratteristiche che potrebbero non entrare mai a far parte del software, mentre invece ci sono problemi sanguinosi ancora aperti oppure strumenti da rifinire e completare nelle funzionalità che non si sono guadagnati ancora il diritto di entrare a far parte delle lista di cose da fare assolutamente ma che avrebbero un impatto molto pesante in senso positivo sul lavoro di tutti i giorni.
La seconda sessione del mattino che ho seguito è stata tenuta da Harry Mattison di Boost your BIM, un ex collaboratore di Charles River Soft che poi ha preso il nome di Revit Technology fino all’acquisizione da parte di Autodesk. Dal 1998 al 2012 ha lavorato nella stanza dei bottoni di Revit e lo conosce in modo profondo. Quello che ha cercato di dimostrare in pochi esempi è come sia possibile rendere i nostri progetti addirittura più intelligenti attraverso l’utilizzo delle API. Anche in Italia con Diego Minato e Renato Caenaro ho potuto vedere cose piuttosto complesse gestite con un’applicazione esterna realizzata appositamente per gestire dati di un modello BIM e produrre documentazione standard di layout di supermercati ad esempio. Questi sono strumenti che fanno risparmiare tempo senza dubbio ma quelli che ha mostrato Harry sono esempi in cui le applicazioni esterne aiutano a fare scelte progettuali mentre si lavora, ad esempio tenendo sotto controllo la lunghezza dei percorsi per raggiungere una particolare stanza e quindi riformulare la forma dell’edificio sulla scorta di un piano tipo ottimizzato, piuttosto che tenere sotto controllo la distanza dalle vie d’uscita ed intervenire su altri aspetti progettuali sempre prima nella concezione del progetto.
Si possono anche ridefinire dei comandi attraverso le API o attivarne di altri in funzione di determinati eventi di innesco come ad esempio l’apertura di una vista, il salvataggio o l’apertura di un documento ecc. ad esempio è possibile definire le proprie finestre di dialogo e impostare i valori di default di quando si collega un oggetto da "Auto: centro a centro" a "Auto: origine a origine".
La particolarità di Harry è la velocità con cui riesce a realizzare strumenti utili al volo: giusto il tempo di un panino ed è tornato con un video fatto per spiegare un comando che rispondeva ad una richiesta che un altro partecipante gli aveva posto per individuare quando un elemento attraversa, ad esempio, un controsoffitto o una parete che abbia una determinata resistenza al fuoco e che quindi deve essere monitorato per i fini della manutenzione con una frequenza particolare e che deve essere quantificato in un report esterno. Vedendolo lavorare sembra davvero tutto semplice, ed è un po’ questo ciò che meraviglia di una persona con un talento come il suo.
Chiacchierando un po' con lui gli ho chiesto se esistesse un modo per aggirare il problema delle annotazioni in Revit attraverso le API ma lì il suo disappunto sulla questione è venuto fuori e si è sfogato di quanto poco ancora sia stato fatto per risolvere questo tipo di problematiche (ad esempio le etichette della categoria dei montanti di facciata continua mancante, o l'inconsistenza delle viste collegate per quanto riguarda le quote che si riferiscono ad elementi collegati in un primo file come associati e poi ricollegati in un altro file... provate: dentro il file A collegate un file B nel quale è collegato un file C come associato, se in B tracciate delle quote che interessano gli elementi di C e successivamente collegate la vista  di B in A non riuscirete a vedere le quote sugli elementi di C).
Durante la tarda mattinata si è tenuta una prima parte della lezione dedicata allo sviluppo di standard di utilizzo Revit per l’Europa, in realtà doveva essere proprio il filo portante della conferenza, trovare dei punti in comune per avere del materiale valido da cui partire. C’era una vignetta esplicativa: due persone parlano e una fa all’altra “hey ci sono 14 tipi di standard concorrenti, dobbiamo fare qualcosa” e l’altro ribatte “si abbiamo bisogno di un solo standard” ed il risultato è che di lì a poco ci sarebbero stati 15 tipi di standard.
Ognuno sembra avere una specie di ricetta, molti dichiarano di utilizzare uno standard di riferimento ma non tutti sono veramente in grado di garantire la consistenza e la completa aderenza ad uno standard proprio per la natura collettiva del lavoro, altri sono partiti dalla codifica delle categorie e dei materiali, delle tipologie costruttive, della forme e hanno ottenuto un complessissimo codice parlante da utilizzare per dare un nome agli oggetti o ai parametri contenuti in essi. Usando una serie di strumenti automatizzati è possibile non essere inghiottiti da questa giungla di codici ma ovviamente una volta implementato e visto funzionare resta ancora qualche limite linguistico da superare, di localizzazione, perché a quanto pare quasi tutti riescono a vedere il valore di avere uno standard per la collaborazione con altri progettisti, ma non tutti per la verità condividono questo punto di vista. O meglio la questione non è tanto semplice da dirimere apparentemente perché purtroppo non è ben chiaro cosa sia uno standard e quando c’è confusione su una cosa fondamentale come questa difficilmente si può venire a capo di qualcosa di utile, soprattutto in un dibattito di un’oretta scarsa.
Dal mio punto di vista non si deve confondere lo standard di utilizzo di Revit con l’aderenza alla normativa di un determinato Paese, o, peggio ancora, con un protocollo di scambio dati come ad esempio l’IFC.
Quello che costituisce uno standard sono le pratiche da adottare nella realizzazione dei modelli per far si che si possano eseguire tutte le analisi possibili sul progetto partendo dall’insieme dei modelli interdisciplinari che lo costituiscono.
Ci sono regole da rispettare per ottemperare alle esigenze di ciascun tipo di analisi, da quelle energetiche che richiedono ad esempio che i muri siano un solo oggetto multi strato per poterne computare i correttamente i valori di trasmittanza con una certa affidabilità nei nodi per la modellazione dei ponti termici, a quelle strutturali dove ad esempio si devono modellare le giunzioni tra un muro e un solaio, quindi il muro non potrà essere unico dalla base alla sommità ma dovrà essere interrotto in corrispondenza dell’intersezione dei diaframmi orizzontali, ancora ci sono le analisi dei costi cui strumenti come le parti possono portare seri benefici a garanzia dell’attendibilità del modello e tutto questo quindi porta a definire quale livello di dettaglio e affidabilità si vuole avere nel modello.
In poche parole si deve codificare la prassi da seguire nel nostro lavoro per parlare effettivamente di collaborazione, partendo dal basso per i contenuti da includere e partendo dall’alto per stabilirne l’obbligatorietà all’interno di un progetto. Si tratta di un processo che va in due sensi e si spera trovi un punto di incontro a metà strada tra la fattibilità e l’utilità di una scelta simile per l’intera filiera delle costruzioni.
Si può obiettare che è un processo complicato e complesso, che dipende dalle abitudini locali o dagli standard interni ecc… forse perché sono in Olanda, mi è venuta in mente questa immagine esplicativa: quando si impara ad andare in bicicletta si stanno eseguendo una serie coordinata di movimenti, se dovessimo metterci a pensare a cosa dobbiamo fare ogni volta che saliamo su una bicicletta non ci sarebbe nemmeno il piacere di fare una passeggiata, mentre invece ci viene naturale, eseguiamo una serie complessa di operazioni in un ambiente in costante evoluzione, circondati da fonti di pericolo potenziali quando andiamo in strada, ma tuttavia sappiamo andare ugualmente spediti sia in Italia sia in Inghilterra dove hanno un codice della strada diverso dal nostro e guidano dal lato opposto della carreggiata: andare in bicicletta in modo corretto resta essenzialmente la stessa cosa ovunque. Perché non possiamo realizzare i nostri modelli BIM con la stessa naturalezza e grado di confidenza indipendentemente dal Paese in cui ci troviamo a lavorare?
Dai commenti che ho sentito e dagli interventi che altri partecipanti facevano sull’argomento sembra che Revit sia utilizzato come modellatore, non ci sono però informazioni nel modello, o semplicemente sono impostate male e rendono il modello inaffidabile. La sfida è quindi riuscire a realizzare modelli affidabili al 100% inserendo programmaticamente gli obiettivi da raggiungere e le metodologie da seguire in un contratto. Sembra che al di là dell’Atlantico questo tipo di approccio legale funzioni piuttosto bene e qualora ci siano consulenti che non siano in grado di fornire questo tipo di  prestazioni saranno costretti a dotarsi in breve tempo di una forma di outsourcing se vogliono rimanere competitivi sul mercato europeo e successivamente interiorizzarla nel proprio processo di lavoro.
Al termine di questa sessione ci sono state due lezioni di alleggerimento: la prima di “tips and tricks” per lo più cose arcinote, alcune molto banali, altre più sofisticate, ma nel complesso valevoli di essere menzionate e ricordate. La seconda è stata una carrellata di ultimi ritrovati tecnologici che avevano poco a che fare con Revit o il mondo delle costruzioni ad eccezioni di droni miniaturizzati per eseguire il laser scanning di un edificio. Non si sono toccati minimamente temi come sostenibilità tecnologica, servizi in cloud o nuove piattaforme di collaborazione  purtroppo.
A quanto pare questa prima edizione del Revit Technology Conference in Europa ha smosso un po’ gli animi su questioni più o meno spinose, ha portato allo scoperto i difetti di una cultura frammentaria ma che si sta a fatica mettendo a regime per dialogare con il resto del mondo.
La prossima edizione si terrà nel 2014 in agosto a Dublino, resterà con la formula a numero chiuso dei partecipanti per consentire l’interazione su una scala umana e avere uno scambio di idee in forma più sociale e proattiva.