Revit Macro: Generate sections and views of beams and columns

This macro creates sections and views of beams and columns.
Macro works with beams in plane and inclined beams.And also with usual and inclined columns.
In current example macro creates one side view to beam/column and 3 cross sections along beam/column. This sections can be used to show rebars in RC structures, for example:



/*
* Created by SharpDevelop.
* User: Nikolai.B
* Date: 02.10.2019
* Time: 10:05
*
* To change this template use Tools | Options | Coding | Edit Standard Headers.
*/
using System;
using Autodesk.Revit.UI;
using Autodesk.Revit.DB;
using Autodesk.Revit.UI.Selection;
using System.Collections.Generic;
using System.Linq;
namespace BeamSections
{
[Autodesk.Revit.Attributes.Transaction(Autodesk.Revit.Attributes.TransactionMode.Manual)]
[Autodesk.Revit.DB.Macros.AddInId("51385248-3728-4704-B8CB-A3761C5E7AEC")]
public partial class ThisDocument
{
//Rename it according to template:
string sectionViewTemplate = "70 - Sh - RC Section"; //Template for section
string detailViewTemplate = "70 - Sh - RC Detail"; //Template for detail
private void Module_Startup(object sender, EventArgs e)
{
}
private void Module_Shutdown(object sender, EventArgs e)
{
}
private void CreateBeamSection (Document doc, string sectionViewTemplate, FamilyInstance beam, double locat, bool parallel = false)
{
ViewFamilyType vft = null;
FilteredElementCollector coll = new FilteredElementCollector(doc).OfClass(typeof(ViewFamilyType));
foreach (Element element in coll)
{
if (element.Name.Equals(sectionViewTemplate))
{
vft = element as ViewFamilyType;
}
}
if (vft == null)
{
TaskDialog.Show("Error", "Template "+sectionViewTemplate+" not found");
}
else
{
LocationCurve beamline = beam.Location as LocationCurve;
Line line = beamline.Curve as Line;
XYZ p = line.GetEndPoint( 0 ); //начало балки
XYZ q = line.GetEndPoint( 1 ); //конец балки
XYZ v = q - p;
BoundingBoxXYZ bb = beam.get_BoundingBox( null );
double minZ = bb.Min.Z; //верх балки
double maxZ = bb.Max.Z; //низ балки
double w = v.GetLength(); //длина балки
double h = maxZ - minZ; //высота балки
double offset = 0.1 * w; //отступ вида по краям балки
// min max для разреза вдоль балки
XYZ min = new XYZ( -offset, minZ - offset, -offset );
XYZ max = new XYZ( offset, maxZ + offset, 0 );
XYZ beamdir = v.Normalize();
XYZ midpoint = (p + locat * v)+beamdir*offset;
XYZ upbasis = XYZ.BasisZ;
XYZ viewdir = -beamdir.CrossProduct( upbasis );
XYZ up = beamdir.CrossProduct( viewdir );
up=up.Normalize();
viewdir=viewdir.Normalize();
Transform t = Transform.Identity;
t.Origin = midpoint;
t.BasisX = viewdir;
t.BasisY = up;
t.BasisZ = beamdir;
if (parallel) //изменение параметров для разреза вдоль балки
{
min = new XYZ( -w/2-offset, minZ - offset, -offset );
max = new XYZ( w/2+offset, maxZ + offset, offset/2 );
midpoint = (p + 0.5 * v);
t.Origin = midpoint;
XYZ newX=new XYZ(beamdir.X, beamdir.Y, 0).Normalize();
t.BasisX = newX;
t.BasisY = XYZ.BasisZ;
t.BasisZ = newX.CrossProduct(XYZ.BasisZ).Normalize();
}
BoundingBoxXYZ sectionBox = new BoundingBoxXYZ();
sectionBox.Transform = t;
sectionBox.Min = min;
sectionBox.Max = max;
var section= ViewSection.CreateSection( doc, vft.Id, sectionBox );
}
}
private void CreateColumnSection (Document doc, string detailViewTemplate, FamilyInstance column, double locat, bool parallel = false)
{
ViewFamilyType vft = null;
FilteredElementCollector coll = new FilteredElementCollector(doc).OfClass(typeof(ViewFamilyType));
foreach (Element element in coll)
{
if (element.Name.Equals(detailViewTemplate))
{
vft = element as ViewFamilyType;
}
}
if (vft == null)
{
TaskDialog.Show("Error", "Template "+detailViewTemplate+" not found");
}
else
{
try
{
LocationPoint columnbase = column.Location as LocationPoint;
XYZ basePoint = columnbase.Point as XYZ; //Основание колонны
BoundingBoxXYZ bb = column.get_BoundingBox( null );
double minZ = bb.Min.Z;
double maxZ = bb.Max.Z;
double minX = bb.Min.X;
double maxX = bb.Max.X;
double minY = bb.Min.Y;
double maxY = bb.Max.Y;
XYZ p= new XYZ(basePoint.X,basePoint.Y,minZ); //основание колонны
XYZ q= new XYZ(basePoint.X,basePoint.Y,maxZ); //верх колонны
XYZ v = q - p; //вектор колонны
double w = v.GetLength(); //длина балки
double h = maxZ - minZ; //высота балки
double offset = 0.1 * w; //отступ вида по краям балки
// min max для разреза вдоль балки
XYZ min = new XYZ( -(maxX-minX), -(maxY-minY), -offset );
XYZ max = new XYZ( (maxX-minX), (maxY-minY), 0 );
XYZ beamdir = v.Normalize();
XYZ midpoint = (p + locat * v)-beamdir*offset;
XYZ up = XYZ.BasisZ;
//XYZ viewdir = beamdir.CrossProduct( up );
XYZ toX = XYZ.BasisX;
XYZ toY = XYZ.BasisY;
Transform t = Transform.Identity;
t.Origin = midpoint;
t.BasisX = toX;
t.BasisY = -toY;
t.BasisZ = -up;
if (parallel) //изменение параметров для разреза вдоль балки
{
min = new XYZ( -(maxX-minX),-w/2-offset,-(maxY-minY) );
max = new XYZ( (maxX-minX), w/2+offset,(maxY-minY) );
midpoint = (p + 0.5 * v);
t.Origin = midpoint;
t.BasisX = -toX;
t.BasisY = up;
t.BasisZ = toY;
}
BoundingBoxXYZ sectionBox = new BoundingBoxXYZ();
sectionBox.Transform = t;
sectionBox.Min = min;
sectionBox.Max = max;
var section= ViewSection.CreateDetail( doc, vft.Id, sectionBox );
}
catch(Exception e)
{
TaskDialog.Show("Error", e.ToString());
}
}
}
public void CreateSections()
{
//var uidoc = this.ActiveUIDocument; //use this line if you are adding it to application
var uidoc = Application.ActiveUIDocument; //and for project
Document doc = uidoc.Document;
Selection sel = uidoc.Selection;
ICollection<ElementId> selectedIds = uidoc.Selection.GetElementIds();
FamilyInstance beam=null;
FamilyInstance column=null;
// check user selection
if (selectedIds.Count < 1)
{
TaskDialog.Show("Создать разрезы по балке/колонне", "Выберите балку или колонну для создания разрезов");
return;
}
else
if (selectedIds.Count > 1)
{
TaskDialog.Show("Создать разрезы по балке/колонне", "Выберите только 1 балку или колонну для создания разрезов");
return;
}
else
{
foreach (ElementId idd in selectedIds)
{
Element elem = doc.GetElement(idd);
if (elem.Category.Name.Equals("Structural Framing"))
{
beam = elem as FamilyInstance;
}
else
if(elem.Category.Name.Equals("Structural Columns"))
{
//проверка на наклонную колонну, если колонна наклонная сечения строятся как для балки
var col=elem as FamilyInstance;
if(col.IsSlantedColumn)
{
beam = elem as FamilyInstance;
}
else
column=elem as FamilyInstance;
}
else
TaskDialog.Show("error", "Балка или колонна не найдены");
}
using (Transaction tt = new Transaction(doc, "Create Sections"))
{
tt.Start();
if(beam!=null)
{
//параллельный разрез
CreateBeamSection (doc, sectionViewTemplate, beam, 0.5, true);
//перпендикулярные разрезы:
CreateBeamSection (doc, sectionViewTemplate, beam, 0.2);
CreateBeamSection (doc, sectionViewTemplate, beam, 0.5);
CreateBeamSection (doc, sectionViewTemplate, beam, 0.8);
}
else
if (column!=null)
{
//параллельный разрез
CreateColumnSection (doc, detailViewTemplate, column, 0.5, true);
//перпендикулярные разрезы:
CreateColumnSection (doc, detailViewTemplate, column, 0.2);
CreateColumnSection (doc, detailViewTemplate, column, 0.5);
CreateColumnSection (doc, detailViewTemplate, column, 0.8);
}
tt.Commit();
}
}
}
#region Revit Macros generated code
private void InternalStartup()
{
this.Startup += new System.EventHandler(Module_Startup);
this.Shutdown += new System.EventHandler(Module_Shutdown);
}
#endregion
}
}

Comments

Popular posts from this blog

Revit Plug-in: Avoid MEP Clashes