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();
}
}

Nessun commento:

Posta un commento