当前位置:网站首页>Revit secondary development - wall opening
Revit secondary development - wall opening
2022-07-07 22:22:00 【Hey, hey, hey, hey, hey】
This function should be realized Pipelines and structures ( wall 、 beam 、 floor 、 The ceiling 、 roof ) Hole at intersection , And connect the pipeline with the hole .
The first is to open a hole , Take the wall as an example
General train of thought :1、 Get the horizontal plane of the wall
2、 Get the two points where the pipeline intersects with the wall , And calculate the midpoint
3、 Create an opening family at the midpoint and perform a cut
private void OpeningHole(Element wall,Curve line)
{
// Get the face of the wall
List<Face> lstFace = Get_ElementFace(wall);
// Get the intersection of the pipeline and the wall
List<XYZ> lstIntersection = Get_Intersection(line, lstFace);
// Calculate the center point
XYZ ptIntersection = (lstIntersection[0] + lstIntersection[1]) / 2
Transaction trans = new Transaction(doc, "opening");
trans.Start();
try
{
// Create an opening
FamilyInstance instance = doc.Create.NewFamilyInstance(ptIntersection, fs, StructuralType.NonStructural);
// Perform the cut
InstanceVoidCutUtils.AddInstanceVoidCut(doc, wall, instance);
trans.Commit();
}
catch
{
trans.RollBack();
}
}
/// <summary>
/// Find the face of the host
/// </summary>
public static List<Face> Get_ElementFace(Element element)
{
Options opt = new Options();
opt.ComputeReferences = true;
opt.DetailLevel = ViewDetailLevel.Fine;
GeometryElement geometryElement = element.get_Geometry(opt);
Face normalFace = null;
List<Face> lstFace = new List<Face>();
foreach (var go in geometryElement)
{
if(go is Solid)
{
Solid solid = go as Solid;
if (solid != null && solid.Faces.Size > 0)
{
foreach (Face face in solid.Faces)
{
PlanarFace planarFace = face as PlanarFace;
if (planarFace != null)
{
lstFace.Add(face);
}
}
}
}
else if(go is GeometryInstance)
{
GeometryInstance gins = goas GeometryInstance;
if (gins != null)
{
GeometryElement ge = gins.GetInstanceGeometry();
foreach (GeometryObject go in ge)
{
Solid solid = go as Solid;
if (solid != null && solid.Faces.Size > 0)
{
foreach (Face face in solid.Faces)
{
PlanarFace planarFace = face as PlanarFace;
if (planarFace != null)
{
lstFace.Add(face);
}
}
}
}
}
}
}
return lstFace;
}
/// <summary>
/// Get the focus of line and structure surface
/// </summary>
public static List<XYZ> Get_Intersection(Curve pipeLine, List<Face> lstFace)
{
List<XYZ> lstIntersection = new List<XYZ>();
foreach (Face item in lstFace)
{
XYZ ptJd = CaculateIntersection(item, pipeLine);
if (ptJd != null)
{
lstIntersection.Add(ptJd);
}
}
return lstIntersection;
}
/// <summary>
/// Find the intersection of surface and line
/// </summary>
public XYZ CaculateIntersection(Face face, Curve curve)
{
XYZ intersection = null;
try
{
IntersectionResultArray resultArray = new IntersectionResultArray();
SetComparisonResult setComparisonResult = face.Intersect(curve, out resultArray);
if (SetComparisonResult.Disjoint != setComparisonResult && resultArray != null)
{
if (!resultArray.IsEmpty)
{
intersection = resultArray.get_Item(0).XYZPoint;
}
}
}
catch (Exception ex)
{ }
return intersection;
}
Then there are pipelines and openings / Casing connection ,
General train of thought :1、 Statistics need data ; such as The cave id, wall id wait
2、 Write the data into the pipeline extension attribute while opening the hole
3、 utilize “IUpdater” Interface , When the user changes the model, it will trigger , After triggering :
① Get the recorded data , And get examples of openings and walls ② Calculate the new intersection of pipeline and wall , And set it for the opening ( And the length of the pipeline / wide / radius )
In this way, the function of associating the opening with the pipeline is realized .
//key: The cave id,value: On the wall id
Dictionary<string,string> dicData = new Dictionary<string,string>();
private void OpeningHole(Element wall,Element duct)
{
// Get the center line of the air duct
LocationCurve lc = duct.Location as LocationCurve;
Curve curve = lc.Curve;
// Get the face of the wall
List<Face> lstFace = Get_ElementFace(wall);
// Get the intersection of the pipeline and the wall
List<XYZ> lstIntersection = Get_Intersection(curve, lstFace);
// Calculate the center point
XYZ ptIntersection = (lstIntersection[0] + lstIntersection[1]) / 2
Transaction trans = new Transaction(doc, "opening");
trans.Start();
try
{
// Create an opening
FamilyInstance instance = doc.Create.NewFamilyInstance(ptIntersection, fs, StructuralType.NonStructural);
// Perform the cut
InstanceVoidCutUtils.AddInstanceVoidCut(doc, wall, instance);
dicData.Add(instance.Id,wall.Id);
// Add data to extended attributes
Add_Data(duct,dicData);
trans.Commit();
}
catch
{
trans.RollBack();
}
}Registration update
public class OpeningApplication : IExternalApplication
{
ElementUpdate Updater;
/// <summary>
/// Registration update
/// </summary>
/// <param name="addInId"></param>
private void Init(AddInId addInId)
{
try
{
// Set the trigger element type
ElementFilter pipe = new ElementCategoryFilter(BuiltInCategory.OST_PipeCurves);
ElementFilter duct = new ElementCategoryFilter(BuiltInCategory.OST_DuctCurves);
List<ElementFilter> lstFilters = new List<ElementFilter>();
lstFilters.Add(pipe);
lstFilters.Add(duct);
// Registration update
Updater = new ElementUpdate(addInId);
UpdaterRegistry.RegisterUpdater(Updater);
LogicalOrFilter filter = new LogicalOrFilter(lstFilters);
UpdaterRegistry.AddTrigger(Updater.GetUpdaterId(), filter, Element.GetChangeTypeAny());
}
catch(Exception ex)
{
System.Windows.Forms.MessageBox.Show(ex.Message);
}
}
public Result OnShutdown(UIControlledApplication application)
{
if(Updater != null)
{
// Log out of updates
UpdaterRegistry.UnregisterUpdater(Updater.GetUpdaterId());
}
return Result.Succeeded;
}
public Result OnStartup(UIControlledApplication application)
{
Init(application.ActiveAddInId);
return Result.Succeeded;
}
}
Realization IUpdater Interface
public class ElementUpdate : IUpdater
{
private AddInId addInId = null;
Guid guid = new Guid("FBFBF6B2-4C06-42d4-97C1-D1B4EB593EFF");
public ElementUpdate(AddInId addin)
{
this.addInId = addin;
}
public void Execute(UpdaterData data)
{
Document doc = data.GetDocument();
List<ElementId> lstModefieIds = data.GetModifiedElementIds().ToList();
// Update elements , Transactions cannot be opened in this interface , Because the changes in the document have not been submitted when this interface is triggered
foreach(ElementId eid in lstModefieIds)
{
Element duct = doc.GetElement(eid);
LocationCurve lc = duct.Location as LocationCurve;
Curve curve = lc.Curve;
Dictionary<string,string> dicData = Get_ExtendedData(duct);
foreach(string cid in dicData)
{
FamilyInstance cave = doc.GetElement(new ElementId(Convert.ToInt32(cid))) as FamilyInstance;
Element wall = doc.GetElement(new ElementId(Convert.ToInt32(dicData[cid])));
// Get the face of the wall
List<Face> lstFace = Get_ElementFace(wall);
// Get the intersection of the pipeline and the wall
List<XYZ> lstIntersection = Get_Intersection(curve, lstFace);
// Calculate the center point
XYZ ptIntersection = (lstIntersection[0] + lstIntersection[1]) / 2;
LocationPoint lp = cave.Location as LocationPoint;
lp.Point = ptIntersection;
}
}
}
public string GetAdditionalInformation()
{
return "add";
}
public ChangePriority GetChangePriority()
{
return ChangePriority.FloorsRoofsStructuralWalls;
}
public UpdaterId GetUpdaterId()
{
return new UpdaterId(addInId, guid);
}
public string GetUpdaterName()
{
return "update";
}
}
Methods of operating extended attributes
/// <summary>
/// Get the extended attribute data of the specified element
/// </summary>
public static Dictionary<string, string> Get_ExtendedData(Element elem)
{
Dictionary<string, string> dicData = new Dictionary<string, string>();
IList<Guid> listGuid = elem.GetEntitySchemaGuids();
if (listGuid.Count == 0)
return dicData;
Schema sa = Schema.Lookup(listGuid[0]);
Entity entity = elem.GetEntity(sa);
IDictionary<string, string> dicMap = entity.Get<IDictionary<string, string>>(sa.GetField(" Fitting collection "));
for (int i = 0; i < dicMap.Count; i++)
{
dicData.Add(dicMap.Keys.ElementAt(i), dicMap.Values.ElementAt(i));
}
return dicData;
}
/// <summary>
/// Overwrite the original extended attribute
/// </summary>
private static void Cover_Data(Element elem, string guid, string name, IDictionary<string, string> data)
{
if (GbvSchema == null)
{
// Set up Schema Data structure framework
SchemaBuilder schemaBuilder = new SchemaBuilder(new Guid(guid));
// Set the readability and Writeability of this structural framework
schemaBuilder.SetReadAccessLevel(AccessLevel.Public);
schemaBuilder.SetWriteAccessLevel(AccessLevel.Public);
// Set the general name of this framework
schemaBuilder.SetSchemaName(name);
// Set the type of this framework and the name of the data
schemaBuilder.AddMapField(name, typeof(string), typeof(string));
// Add the data structure framework to Schema in
GbvSchema = schemaBuilder.Finish();
}
// Create a new data object
Entity entity = new Entity(GbvSchema);
// obtain Revit Data object with corresponding name in
Field field = GbvSchema.GetField(name);
// Then give the data object entity assignment
entity.Set(field, data);
// Finally, add data to the wall
elem.SetEntity(entity);
}
/// <summary>
/// Add extended properties
/// </summary>
public static void Add_Data(Element elem, IDictionary<string, string> data)
{
Dictionary<string, string> tempData = Get_ExtendedData(elem);
if (tempData.Count > 0)
{
foreach (string item in tempData.Keys)
{
if (data.Keys.Contains(item))
continue;
data.Add(item, tempData[item]);
}
}
if (data.Count > 0)
{
Cover_Data(elem, "f0c28996-670d-438f-a2be-b81b14aeb8dd", " Fitting collection ", data);
}
}
That's about it , The code is reduced and simplified , I haven't run Just for reference .
Leave a message if you have any questions .
边栏推荐
- 客户案例|华律网,通过观测云大幅缩短故障定位时间
- [JDBC Part 1] overview, get connection, CRUD
- Reinforcement learning - learning notes 9 | multi step TD target
- Tsconfig of typescript TS basics JSON configuration options
- 大数据开源项目,一站式全自动化全生命周期运维管家ChengYing(承影)走向何方?
- Oracle advanced (VI) Oracle expdp/impdp details
- 三元表达式、各生成式、匿名函数
- Main functions of OS, Sys and random Standard Libraries
- [interview arrangement] 0211 game engine server
- Win11U盘不显示怎么办?Win11插U盘没反应的解决方法
猜你喜欢

嵌入式开发:如何为项目选择合适的RTOS?

Tcp/ip protocol stack

Paint basic graphics with custompaint
![Jerry's initiation of ear pairing, reconnection, and opening of discoverable and connectable cyclic functions [chapter]](/img/14/1c8a70102c106f4631853ed73c4d82.png)
Jerry's initiation of ear pairing, reconnection, and opening of discoverable and connectable cyclic functions [chapter]

Ternary expressions, generative expressions, anonymous functions

Display optimization when the resolution of easycvr configuration center video recording plan page is adjusted

Px4 autonomous flight

你可曾迷茫?曾经的测试/开发程序员,懵懂的小菜C鸟升级......

使用 BlocConsumer 同时构建响应式组件和监听状态

The whole network "chases" Zhong Xuegao
随机推荐
Matplotlib快速入门
PDF文档签名指南
【colmap】稀疏重建转为MVSNet格式输入
为什么Win11不能显示秒数?Win11时间不显示秒怎么解决?
It's worth seeing. Interview sites and interview skills
OpenGL homework - Hello, triangle
Restapi version control strategy [eolink translation]
Use json Stringify() to realize deep copy, be careful, there may be a huge hole
Jerry's test box configuration channel [chapter]
QT compile IOT management platform 39 alarm linkage
强化学习-学习笔记9 | Multi-Step-TD-Target
Ternary expressions, generative expressions, anonymous functions
双塔模型的最强出装,谷歌又开始玩起“老古董”了?
Pdf document signature Guide
vite Unrestricted file system access to
建立自己的网站(18)
变量与常量
UWA问答精选
Node:504 error reporting
PKPM 2020软件安装包下载及安装教程