当前位置:网站首页>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 .
边栏推荐
- . Net automapper use
- 648. Word replacement
- 【Azure微服务 Service Fabric 】在SF节点中开启Performance Monitor及设置抓取进程的方式
- Win11时间怎么显示星期几?Win11怎么显示今天周几?
- Application practice | the efficiency of the data warehouse system has been comprehensively improved! Data warehouse construction based on Apache Doris in Tongcheng digital Department
- Tcp/ip protocol stack
- Open source OA development platform: contract management user manual
- OpeGL personal notes - lights
- Pre sale 179000, hengchi 5 can fire? Product power online depends on how it is sold
- Preparing for the interview and sharing experience
猜你喜欢
How to choose the appropriate automated testing tools?
为什么Win11不能显示秒数?Win11时间不显示秒怎么解决?
TCP/IP 协议栈
It's worth seeing. Interview sites and interview skills
应用实践 | 数仓体系效率全面提升!同程数科基于 Apache Doris 的数据仓库建设
Firefox browser installation impression notes clipping
Tcp/ip protocol stack
使用 CustomPaint 绘制基本图形
ByteDance Android interview, summary of knowledge points + analysis of interview questions
PKPM 2020软件安装包下载及安装教程
随机推荐
Use blocconsumer to build responsive components and monitor status at the same time
Overseas agent recommendation
Get the exact offset of the element
23. Merge K ascending linked lists -c language
TCP/IP 协议栈
【Azure微服务 Service Fabric 】如何转移Service Fabric集群中的种子节点(Seed Node)
Win11如何解禁键盘?Win11解禁键盘的方法
Tcp/ip protocol stack
How to make agile digital transformation strategy for manufacturing enterprises
Anti climbing killer
Codemail auto collation code of visual studio plug-in
Remember that a development is encountered in the pit of origin string sorting
Jerry's manual matching method [chapter]
QT compile IOT management platform 39 alarm linkage
[开源] .Net ORM 访问 Firebird 数据库
Implementation method of data platform landing
Time standard library
[interview arrangement] 0211 game engine server
VTOL in Px4_ att_ Control source code analysis [supplement]
【Azure微服务 Service Fabric 】在SF节点中开启Performance Monitor及设置抓取进程的方式