当前位置:网站首页>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 .
边栏推荐
- JS number is insufficient, and 0 is added
- Node:504 error reporting
- Debugging and handling the problem of jamming for about 30s during SSH login
- 三元表达式、各生成式、匿名函数
- 嵌入式开发:如何为项目选择合适的RTOS?
- Firefox browser installation impression notes clipping
- Welcome to CSDN markdown editor
- Leetcode SQL first day
- Matplotlib drawing interface settings
- How to make agile digital transformation strategy for manufacturing enterprises
猜你喜欢

Blender exchange group, welcome to the water group ~
![[azure microservice service fabric] how to transfer seed nodes in the service fabric cluster](/img/b6/e5d525d9c7c28f6ef04c3f59b40eb3.png)
[azure microservice service fabric] how to transfer seed nodes in the service fabric cluster
![[advanced MySQL] index details (I): index data page structure](/img/e7/fe4591a721a71c3c38d6e4448af6af.png)
[advanced MySQL] index details (I): index data page structure

反爬通杀神器

Reinforcement learning - learning notes 9 | multi step TD target

How to make agile digital transformation strategy for manufacturing enterprises

双塔模型的最强出装,谷歌又开始玩起“老古董”了?

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

The function is really powerful!

Index summary (assault version)
随机推荐
Matplotlib快速入门
Time standard library
L2:ZK-Rollup的现状,前景和痛点
Lingyun going to sea | saihe & Huawei cloud: jointly help the sustainable development of cross-border e-commerce industry
NVR硬盤錄像機通過國標GB28181協議接入EasyCVR,設備通道信息不顯示是什麼原因?
Main functions of OS, Sys and random Standard Libraries
The strongest installation of the twin tower model, Google is playing "antique" again?
100million single men and women "online dating", supporting 13billion IPOs
How does win11 time display the day of the week? How does win11 display the day of the week today?
Win11游戏模式怎么开启?Win11开启游戏模式的方法
Leetcode SQL first day
Blender exchange group, welcome to the water group ~
Get the week start time and week end time of the current date
Antd date component appears in English
[JDBC Part 1] overview, get connection, CRUD
你可曾迷茫?曾经的测试/开发程序员,懵懂的小菜C鸟升级......
Redis - basic use (key, string, list, set, Zset, hash, geo, bitmap, hyperloglog, transaction)
Jerry's about TWS pairing mode configuration [chapter]
VTOL in Px4_ att_ Control source code analysis [supplement]
为什么Win11不能显示秒数?Win11时间不显示秒怎么解决?