当前位置:网站首页>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 write an augmented matrix into TXT file
- Reptile combat (VII): pictures of the king of reptiles' heroes
- Attitude estimation (complementary filtering)
- Get the exact offset of the element
- Kirin Xin'an operating system derivative solution | storage multipath management system, effectively improving the reliability of data transmission
- OpenGL jobs - shaders
- MIT6.S081-Lab9 FS [2021Fall]
- Matplotlib drawing interface settings
- Firefox browser installation impression notes clipping
- Debugging and handling the problem of jamming for about 30s during SSH login
猜你喜欢
Node:504 error reporting
Anti climbing killer
[azure microservice service fabric] start the performance monitor in the SF node and set the method of capturing the process
为什么Win11不能显示秒数?Win11时间不显示秒怎么解决?
Ad domain group policy management
使用 CustomPaint 绘制基本图形
反爬通杀神器
嵌入式开发:如何为项目选择合适的RTOS?
Google SEO external chain backlinks research tool recommendation
PDF文档签名指南
随机推荐
Overseas agent recommendation
Reptile combat (VII): pictures of the king of reptiles' heroes
OpenGL jobs - shaders
Cv2.resize function reports an error: error: (-215:assertion failed) func= 0 in function ‘cv::hal::resize‘
【Azure微服务 Service Fabric 】在SF节点中开启Performance Monitor及设置抓取进程的方式
Px4 autonomous flight
双塔模型的最强出装,谷歌又开始玩起“老古董”了?
The cyberspace office announced the measures for data exit security assessment, which will come into force on September 1
Reinforcement learning - learning notes 9 | multi step TD target
Main functions of OS, Sys and random Standard Libraries
Implementation method of data platform landing
Leetcode SQL first day
Jerry's fast pairing does not support canceling pairing [article]
应用实践 | 数仓体系效率全面提升!同程数科基于 Apache Doris 的数据仓库建设
用语雀写文章了,功能真心强大!
NVR硬盘录像机通过国标GB28181协议接入EasyCVR,设备通道信息不显示是什么原因?
How to realize the movement control of characters in horizontal game
[open source] Net ORM accessing Firebird database
vite Unrestricted file system access to
Vs custom template - take the custom class template as an example