当前位置:网站首页>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 .
边栏推荐
- How to realize the movement control of characters in horizontal game
- Can I open a stock account directly online now? Is it safe?
- OpenGL jobs - shaders
- How to write an augmented matrix into TXT file
- NVR硬盘录像机通过国标GB28181协议接入EasyCVR,设备通道信息不显示是什么原因?
- 【JDBC Part 1】概述、获取连接、CRUD
- Jerry's initiation of ear pairing, reconnection, and opening of discoverable and connectable cyclic functions [chapter]
- The difference between NPM uninstall and RM direct deletion
- Ad domain group policy management
- [colmap] sparse reconstruction is converted to mvsnet format input
猜你喜欢
ByteDance Android interview, summary of knowledge points + analysis of interview questions
100million single men and women "online dating", supporting 13billion IPOs
Matplotlib快速入门
Why can't win11 display seconds? How to solve the problem that win11 time does not display seconds?
Implementation method of data platform landing
【JDBC Part 1】概述、获取连接、CRUD
Firefox browser installation impression notes clipping
三元表达式、各生成式、匿名函数
【Azure微服务 Service Fabric 】在SF节点中开启Performance Monitor及设置抓取进程的方式
How to realize the movement control of characters in horizontal game
随机推荐
Record a garbled code during servlet learning
648. Word replacement
Ternary expressions, generative expressions, anonymous functions
EasyCVR配置中心录像计划页面调整分辨率时的显示优化
How does win11 time display the day of the week? How does win11 display the day of the week today?
戴森官方直营店免费造型服务现已开放预约 先锋科技诠释护发造型理念,助力消费者解锁多元闪耀造型
QT compile IOT management platform 39 alarm linkage
【Azure微服务 Service Fabric 】如何转移Service Fabric集群中的种子节点(Seed Node)
Programming mode - table driven programming
如何选择合适的自动化测试工具?
Application practice | the efficiency of the data warehouse system has been comprehensively improved! Data warehouse construction based on Apache Doris in Tongcheng digital Department
强化学习-学习笔记9 | Multi-Step-TD-Target
OpenGL homework - Hello, triangle
Which futures company is the safest to open a futures account?
用语雀写文章了,功能真心强大!
Add get disabled for RC form
海外代理推荐
变量与常量
[开源] .Net ORM 访问 Firebird 数据库
Firefox browser installation impression notes clipping