<?
xml version="1.0" encoding="utf-8"
?>
< Openings >
< Opening WallId ="618644" >
< PT1 X ="-46.4673223917839" Y ="25.9434404529416" Z ="9.8753280839895" />
< PT2 X ="-46.4673223917839" Y ="24.2374037075347" Z ="8.16929133858268" />
</ Opening >
< Opening WallId ="618699" >
< PT1 X ="28.3358272145153" Y ="24.2374037075345" Z ="9.8753280839895" />
< PT2 X ="28.3358272145153" Y ="25.9434404529413" Z ="8.16929133858268" />
</ Opening >
< Opening WallId ="618722" >
< PT1 X ="-10.7125018356066" Y ="57.0806634229704" Z ="9.8753280839895" />
< PT2 X ="-12.4185385810134" Y ="57.0806634229704" Z ="8.16929133858268" />
</ Opening >
< Opening WallId ="618662" >
< PT1 X ="-20.8620650191645" Y ="-1.31828670826329" Z ="9.8753280839895" />
< PT2 X ="-19.1560282737577" Y ="-1.31828670826329" Z ="8.16929133858268" />
</ Opening >
</ Openings >
< Openings >
< Opening WallId ="618644" >
< PT1 X ="-46.4673223917839" Y ="25.9434404529416" Z ="9.8753280839895" />
< PT2 X ="-46.4673223917839" Y ="24.2374037075347" Z ="8.16929133858268" />
</ Opening >
< Opening WallId ="618699" >
< PT1 X ="28.3358272145153" Y ="24.2374037075345" Z ="9.8753280839895" />
< PT2 X ="28.3358272145153" Y ="25.9434404529413" Z ="8.16929133858268" />
</ Opening >
< Opening WallId ="618722" >
< PT1 X ="-10.7125018356066" Y ="57.0806634229704" Z ="9.8753280839895" />
< PT2 X ="-12.4185385810134" Y ="57.0806634229704" Z ="8.16929133858268" />
</ Opening >
< Opening WallId ="618662" >
< PT1 X ="-20.8620650191645" Y ="-1.31828670826329" Z ="9.8753280839895" />
< PT2 X ="-19.1560282737577" Y ="-1.31828670826329" Z ="8.16929133858268" />
</ Opening >
</ Openings >
//
根据导出开洞信息开洞
[Transaction(TransactionMode.Manual)]
[Regeneration(RegenerationOption.Manual)]
public class cmdOpening : IExternalCommand
{
public Result Execute(ExternalCommandData cmdData, ref string msg, ElementSet elements)
{
UIDocument uiDoc = cmdData.Application.ActiveUIDocument;
Document doc = uiDoc.Document;
Selection sel = uiDoc.Selection;
Transaction ts = new Transaction(doc, " http://revit.5d6d.com ");
ts.Start();
string strPath = @" C:\Users\HongYe\Desktop\OpeningInfo.xml ";
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(strPath);
foreach (XmlNode node in xmlDoc.DocumentElement.ChildNodes)
{
// ;
Wall wall = doc.get_Element( new ElementId(Convert.ToInt32(node.Attributes[ " WallId "].Value))) as Wall;
XmlNode nodePt1 = node.SelectSingleNode( " PT1 ");
XYZ pt1 = new XYZ( double.Parse(nodePt1.Attributes[ " X "].Value), double.Parse(nodePt1.Attributes[ " Y "].Value), double.Parse(nodePt1.Attributes[ " Z "].Value));
XmlNode nodePt2 = node.SelectSingleNode( " PT2 ");
XYZ pt2 = new XYZ( double.Parse(nodePt2.Attributes[ " X "].Value), double.Parse(nodePt2.Attributes[ " Y "].Value), double.Parse(nodePt2.Attributes[ " Z "].Value));
doc.Create.NewOpening(wall, pt1, pt2);
}
ts.Commit();
return Result.Succeeded;
}
}
[Transaction(TransactionMode.Manual)]
[Regeneration(RegenerationOption.Manual)]
// 导出开洞信息
public class cmd : IExternalCommand
{
/// <summary>
/// 找到链接文档中与风管相交的墙
/// </summary>
/// <param name="doc"></param>
/// <param name="duct"></param>
/// <returns></returns>
public static List<Wall> FindDuctWall(Document doc, Duct duct)
{
List<Wall> listWall = new List<Wall>();
// 找到outLine
BoundingBoxXYZ bb = duct.get_BoundingBox(doc.ActiveView);
Outline outline = new Outline(bb.Min, bb.Max);
//
FilteredElementCollector collector = new FilteredElementCollector(doc);
BoundingBoxIntersectsFilter invertFilter = new BoundingBoxIntersectsFilter(outline, false);
IList<Element> noIntersectWalls = collector.OfClass( typeof(Wall)).WherePasses(invertFilter).ToElements();
foreach (Element el in noIntersectWalls)
{
Wall wall = el as Wall;
if (wall != null)
listWall.Add(wall);
}
return listWall;
}
public Result Execute(ExternalCommandData cmdData, ref string msg, ElementSet elements)
{
UIDocument uiDoc = cmdData.Application.ActiveUIDocument;
UIApplication uiApp = cmdData.Application;
Document doc = uiDoc.Document;
Selection selection = uiDoc.Selection;
try
{
Transaction ts = new Transaction(doc, " http://revit.5d6d.com ");
ts.Start();
string strPath = @" C:\Users\HongYe\Desktop\OpeningInfo.xml ";
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(strPath);
List< string> listPath = GetLinkFilePaths(doc);
Document docLink = uiApp.Application.OpenDocumentFile(listPath[ 0]);
//
FilteredElementCollector collIns = new FilteredElementCollector(doc); //
collIns.OfClass( typeof(Instance)).OfCategory(BuiltInCategory.OST_RvtLinks); // RevitLinkType
Transform transForm = null;
foreach (Element elDoc in collIns)
{
Instance ins = elDoc as Instance;
if (ins != null)
{
transForm = ins.GetTransform();
}
}
// 风管
FilteredElementCollector collDuct = new FilteredElementCollector(doc);
collDuct.OfClass( typeof(Duct)).OfCategory(BuiltInCategory.OST_DuctCurves);
foreach (Element elDuct in collDuct)
{
Duct duct = elDuct as Duct;
List<Wall> listWall = FindDuctWall(docLink, duct); // 找到链接文档中与风管相交的墙
foreach (Wall wall in listWall)
{
// 求面和线的交点
Face face = FindWallFace(wall);
Curve curve = FindDuctCurve(duct);
XYZ xyz = FindFaceCurve(face, curve);
// 墙线的向量
XYZ wallVector = FindWallVector(wall);
// 找到风管的宽和高
double dWidth = GetDuctWidth(duct);
double dHeigh = GetDuctHeight(duct);
int iUp = 100;
int iDown = 100;
int iLeft = 100;
int iRight = 100;
// 左上角
XYZ pt1 = xyz + new XYZ( 0, 0, 1) * (dHeigh / 2 + iUp) / 304.8;
pt1 = pt1 - wallVector.Normalize() * (dWidth / 2 + iLeft) / 304.8;
pt1 = pt1 - transForm.Origin;
// 右下角
XYZ pt2 = xyz + new XYZ( 0, 0, - 1) * (dHeigh / 2 + iDown) / 304.8;
pt2 = pt2 + wallVector.Normalize() * (dWidth / 2 + iRight) / 304.8;
pt2 = pt2 - transForm.Origin;
// 开洞
// doc.Create.NewOpening(wall, pt1, pt2);
// wall.Id.IntegerValue.ToString();
// pt1.X;
XmlElement xmlEl = xmlDoc.CreateElement( " Opening ");
xmlEl.SetAttribute( " WallId ", wall.Id.IntegerValue.ToString());
XmlElement elPt1 = xmlDoc.CreateElement( " PT1 ");
elPt1.SetAttribute( " X ", pt1.X.ToString());
elPt1.SetAttribute( " Y ", pt1.Y.ToString());
elPt1.SetAttribute( " Z ", pt1.Z.ToString());
xmlEl.AppendChild(elPt1);
XmlElement elPt2 = xmlDoc.CreateElement( " PT2 ");
elPt2.SetAttribute( " X ", pt2.X.ToString());
elPt2.SetAttribute( " Y ", pt2.Y.ToString());
elPt2.SetAttribute( " Z ", pt2.Z.ToString());
xmlEl.AppendChild(elPt2);
xmlDoc.DocumentElement.AppendChild(xmlEl);
}
}
ts.Commit();
xmlDoc.Save(strPath);
}
catch (Exception ex)
{
WinFormTools.MsgBox(ex.ToString());
}
return Result.Succeeded;
}
// 找到风管宽度
public static double GetDuctWidth(Duct duct)
{
double dWidth = 0;
foreach (Parameter p in duct.Parameters)
{
if (p.Definition.Name == " 宽度 ")
{
dWidth = double.Parse(p.AsValueString());
break;
}
}
return dWidth;
}
// 找到风管高度
public static double GetDuctHeight(Duct duct)
{
double dHeigh = 0;
foreach (Parameter p in duct.Parameters)
{
if (p.Definition.Name == " 高度 ")
{
dHeigh = double.Parse(p.AsValueString());
break;
}
}
return dHeigh;
}
/// <summary>
/// 找到墙线的向量
/// </summary>
/// <param name="wall"></param>
/// <returns></returns>
public static XYZ FindWallVector(Wall wall)
{
LocationCurve lCurve = wall.Location as LocationCurve;
XYZ xyz = lCurve.Curve.get_EndPoint( 1) - lCurve.Curve.get_EndPoint( 0);
return xyz;
}
/// <summary>
/// 求线和面的交点
/// </summary>
/// <param name="face"></param>
/// <param name="curve"></param>
/// <returns></returns>
public static XYZ FindFaceCurve(Face face, Curve curve)
{
// 求交点
IntersectionResultArray intersectionR = new IntersectionResultArray(); // 交点集合
SetComparisonResult comparisonR; // Comparison比较
comparisonR = face.Intersect(curve, out intersectionR);
XYZ intersectionResult = null; // 交点坐标
if (SetComparisonResult.Disjoint != comparisonR) // Disjoint不交
{
if (!intersectionR.IsEmpty)
{
intersectionResult = intersectionR.get_Item( 0).XYZPoint;
}
}
return intersectionResult;
}
/// <summary>
/// 找到风管对应的曲线
/// </summary>
/// <param name="duct"></param>
/// <returns></returns>
public Curve FindDuctCurve(Duct duct)
{
// 得到风管曲线
IList<XYZ> list = new List<XYZ>();
ConnectorSetIterator csi = duct.ConnectorManager.Connectors.ForwardIterator();
while (csi.MoveNext())
{
Connector conn = csi.Current as Connector;
list.Add(conn.Origin);
}
Curve curve = Line.get_Bound(list.ElementAt( 0), list.ElementAt( 1)) as Curve;
curve.MakeUnbound();
return curve;
}
/// <summary>
/// 找到墙的正面
/// </summary>
/// <param name="wall"></param>
/// <returns></returns>
public Face FindWallFace(Wall wall)
{
Face normalFace = null;
//
Options opt = new Options();
opt.ComputeReferences = true;
opt.DetailLevel = Autodesk.Revit.DB.DetailLevels.Medium;
//
GeometryElement e = wall.get_Geometry(opt);
/* 下版改进
IEnumerator<GeometryObject> enm = e.GetEnumerator();
while (enm.MoveNext())
{
Solid solid = enm.Current as Solid;
} */
foreach (GeometryObject obj in e.Objects) // 待改2013
{
Solid solid = obj as Solid;
if (solid != null && solid.Faces.Size > 0)
{
foreach (Face face in solid.Faces)
{
PlanarFace pf = face as PlanarFace;
if (pf != null)
{
if (pf.Normal.AngleTo(wall.Orientation) < 0.01) // 数值在0到PI之间
{
normalFace = face;
}
}
}
}
}
return normalFace;
}
/// <summary>
/// 取得链接文件路径
/// </summary>
/// <param name="doc"></param>
/// <returns></returns>
public List< string> GetLinkFilePaths(Document doc)
{
List< string> listPath = new List< string>();
foreach (ElementId elId in ExternalFileUtils.GetAllExternalFileReferences(doc))
{
if (doc.get_Element(elId).IsExternalFileReference())
{
ExternalFileReference fileRef = doc.get_Element(elId).GetExternalFileReference();
if (ExternalFileReferenceType.RevitLink == fileRef.ExternalFileReferenceType)
listPath.Add(ModelPathUtils.ConvertModelPathToUserVisiblePath(fileRef.GetAbsolutePath()));
}
}
return listPath;
}
/// <summary>
/// 根据链接文件名称找到对应链接路径,模糊匹配,待改进
/// </summary>
/// <param name="listPath"></param>
/// <param name="strKey"></param>
/// <returns></returns>
private string GetPath(List< string> listPath, string strKey)
{
foreach ( string strPath in listPath)
{
if (strPath.Contains(strKey))
return strPath;
}
return "";
}
}
[Transaction(TransactionMode.Manual)]
[Regeneration(RegenerationOption.Manual)]
public class cmdOpening : IExternalCommand
{
public Result Execute(ExternalCommandData cmdData, ref string msg, ElementSet elements)
{
UIDocument uiDoc = cmdData.Application.ActiveUIDocument;
Document doc = uiDoc.Document;
Selection sel = uiDoc.Selection;
Transaction ts = new Transaction(doc, " http://revit.5d6d.com ");
ts.Start();
string strPath = @" C:\Users\HongYe\Desktop\OpeningInfo.xml ";
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(strPath);
foreach (XmlNode node in xmlDoc.DocumentElement.ChildNodes)
{
// ;
Wall wall = doc.get_Element( new ElementId(Convert.ToInt32(node.Attributes[ " WallId "].Value))) as Wall;
XmlNode nodePt1 = node.SelectSingleNode( " PT1 ");
XYZ pt1 = new XYZ( double.Parse(nodePt1.Attributes[ " X "].Value), double.Parse(nodePt1.Attributes[ " Y "].Value), double.Parse(nodePt1.Attributes[ " Z "].Value));
XmlNode nodePt2 = node.SelectSingleNode( " PT2 ");
XYZ pt2 = new XYZ( double.Parse(nodePt2.Attributes[ " X "].Value), double.Parse(nodePt2.Attributes[ " Y "].Value), double.Parse(nodePt2.Attributes[ " Z "].Value));
doc.Create.NewOpening(wall, pt1, pt2);
}
ts.Commit();
return Result.Succeeded;
}
}
[Transaction(TransactionMode.Manual)]
[Regeneration(RegenerationOption.Manual)]
// 导出开洞信息
public class cmd : IExternalCommand
{
/// <summary>
/// 找到链接文档中与风管相交的墙
/// </summary>
/// <param name="doc"></param>
/// <param name="duct"></param>
/// <returns></returns>
public static List<Wall> FindDuctWall(Document doc, Duct duct)
{
List<Wall> listWall = new List<Wall>();
// 找到outLine
BoundingBoxXYZ bb = duct.get_BoundingBox(doc.ActiveView);
Outline outline = new Outline(bb.Min, bb.Max);
//
FilteredElementCollector collector = new FilteredElementCollector(doc);
BoundingBoxIntersectsFilter invertFilter = new BoundingBoxIntersectsFilter(outline, false);
IList<Element> noIntersectWalls = collector.OfClass( typeof(Wall)).WherePasses(invertFilter).ToElements();
foreach (Element el in noIntersectWalls)
{
Wall wall = el as Wall;
if (wall != null)
listWall.Add(wall);
}
return listWall;
}
public Result Execute(ExternalCommandData cmdData, ref string msg, ElementSet elements)
{
UIDocument uiDoc = cmdData.Application.ActiveUIDocument;
UIApplication uiApp = cmdData.Application;
Document doc = uiDoc.Document;
Selection selection = uiDoc.Selection;
try
{
Transaction ts = new Transaction(doc, " http://revit.5d6d.com ");
ts.Start();
string strPath = @" C:\Users\HongYe\Desktop\OpeningInfo.xml ";
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(strPath);
List< string> listPath = GetLinkFilePaths(doc);
Document docLink = uiApp.Application.OpenDocumentFile(listPath[ 0]);
//
FilteredElementCollector collIns = new FilteredElementCollector(doc); //
collIns.OfClass( typeof(Instance)).OfCategory(BuiltInCategory.OST_RvtLinks); // RevitLinkType
Transform transForm = null;
foreach (Element elDoc in collIns)
{
Instance ins = elDoc as Instance;
if (ins != null)
{
transForm = ins.GetTransform();
}
}
// 风管
FilteredElementCollector collDuct = new FilteredElementCollector(doc);
collDuct.OfClass( typeof(Duct)).OfCategory(BuiltInCategory.OST_DuctCurves);
foreach (Element elDuct in collDuct)
{
Duct duct = elDuct as Duct;
List<Wall> listWall = FindDuctWall(docLink, duct); // 找到链接文档中与风管相交的墙
foreach (Wall wall in listWall)
{
// 求面和线的交点
Face face = FindWallFace(wall);
Curve curve = FindDuctCurve(duct);
XYZ xyz = FindFaceCurve(face, curve);
// 墙线的向量
XYZ wallVector = FindWallVector(wall);
// 找到风管的宽和高
double dWidth = GetDuctWidth(duct);
double dHeigh = GetDuctHeight(duct);
int iUp = 100;
int iDown = 100;
int iLeft = 100;
int iRight = 100;
// 左上角
XYZ pt1 = xyz + new XYZ( 0, 0, 1) * (dHeigh / 2 + iUp) / 304.8;
pt1 = pt1 - wallVector.Normalize() * (dWidth / 2 + iLeft) / 304.8;
pt1 = pt1 - transForm.Origin;
// 右下角
XYZ pt2 = xyz + new XYZ( 0, 0, - 1) * (dHeigh / 2 + iDown) / 304.8;
pt2 = pt2 + wallVector.Normalize() * (dWidth / 2 + iRight) / 304.8;
pt2 = pt2 - transForm.Origin;
// 开洞
// doc.Create.NewOpening(wall, pt1, pt2);
// wall.Id.IntegerValue.ToString();
// pt1.X;
XmlElement xmlEl = xmlDoc.CreateElement( " Opening ");
xmlEl.SetAttribute( " WallId ", wall.Id.IntegerValue.ToString());
XmlElement elPt1 = xmlDoc.CreateElement( " PT1 ");
elPt1.SetAttribute( " X ", pt1.X.ToString());
elPt1.SetAttribute( " Y ", pt1.Y.ToString());
elPt1.SetAttribute( " Z ", pt1.Z.ToString());
xmlEl.AppendChild(elPt1);
XmlElement elPt2 = xmlDoc.CreateElement( " PT2 ");
elPt2.SetAttribute( " X ", pt2.X.ToString());
elPt2.SetAttribute( " Y ", pt2.Y.ToString());
elPt2.SetAttribute( " Z ", pt2.Z.ToString());
xmlEl.AppendChild(elPt2);
xmlDoc.DocumentElement.AppendChild(xmlEl);
}
}
ts.Commit();
xmlDoc.Save(strPath);
}
catch (Exception ex)
{
WinFormTools.MsgBox(ex.ToString());
}
return Result.Succeeded;
}
// 找到风管宽度
public static double GetDuctWidth(Duct duct)
{
double dWidth = 0;
foreach (Parameter p in duct.Parameters)
{
if (p.Definition.Name == " 宽度 ")
{
dWidth = double.Parse(p.AsValueString());
break;
}
}
return dWidth;
}
// 找到风管高度
public static double GetDuctHeight(Duct duct)
{
double dHeigh = 0;
foreach (Parameter p in duct.Parameters)
{
if (p.Definition.Name == " 高度 ")
{
dHeigh = double.Parse(p.AsValueString());
break;
}
}
return dHeigh;
}
/// <summary>
/// 找到墙线的向量
/// </summary>
/// <param name="wall"></param>
/// <returns></returns>
public static XYZ FindWallVector(Wall wall)
{
LocationCurve lCurve = wall.Location as LocationCurve;
XYZ xyz = lCurve.Curve.get_EndPoint( 1) - lCurve.Curve.get_EndPoint( 0);
return xyz;
}
/// <summary>
/// 求线和面的交点
/// </summary>
/// <param name="face"></param>
/// <param name="curve"></param>
/// <returns></returns>
public static XYZ FindFaceCurve(Face face, Curve curve)
{
// 求交点
IntersectionResultArray intersectionR = new IntersectionResultArray(); // 交点集合
SetComparisonResult comparisonR; // Comparison比较
comparisonR = face.Intersect(curve, out intersectionR);
XYZ intersectionResult = null; // 交点坐标
if (SetComparisonResult.Disjoint != comparisonR) // Disjoint不交
{
if (!intersectionR.IsEmpty)
{
intersectionResult = intersectionR.get_Item( 0).XYZPoint;
}
}
return intersectionResult;
}
/// <summary>
/// 找到风管对应的曲线
/// </summary>
/// <param name="duct"></param>
/// <returns></returns>
public Curve FindDuctCurve(Duct duct)
{
// 得到风管曲线
IList<XYZ> list = new List<XYZ>();
ConnectorSetIterator csi = duct.ConnectorManager.Connectors.ForwardIterator();
while (csi.MoveNext())
{
Connector conn = csi.Current as Connector;
list.Add(conn.Origin);
}
Curve curve = Line.get_Bound(list.ElementAt( 0), list.ElementAt( 1)) as Curve;
curve.MakeUnbound();
return curve;
}
/// <summary>
/// 找到墙的正面
/// </summary>
/// <param name="wall"></param>
/// <returns></returns>
public Face FindWallFace(Wall wall)
{
Face normalFace = null;
//
Options opt = new Options();
opt.ComputeReferences = true;
opt.DetailLevel = Autodesk.Revit.DB.DetailLevels.Medium;
//
GeometryElement e = wall.get_Geometry(opt);
/* 下版改进
IEnumerator<GeometryObject> enm = e.GetEnumerator();
while (enm.MoveNext())
{
Solid solid = enm.Current as Solid;
} */
foreach (GeometryObject obj in e.Objects) // 待改2013
{
Solid solid = obj as Solid;
if (solid != null && solid.Faces.Size > 0)
{
foreach (Face face in solid.Faces)
{
PlanarFace pf = face as PlanarFace;
if (pf != null)
{
if (pf.Normal.AngleTo(wall.Orientation) < 0.01) // 数值在0到PI之间
{
normalFace = face;
}
}
}
}
}
return normalFace;
}
/// <summary>
/// 取得链接文件路径
/// </summary>
/// <param name="doc"></param>
/// <returns></returns>
public List< string> GetLinkFilePaths(Document doc)
{
List< string> listPath = new List< string>();
foreach (ElementId elId in ExternalFileUtils.GetAllExternalFileReferences(doc))
{
if (doc.get_Element(elId).IsExternalFileReference())
{
ExternalFileReference fileRef = doc.get_Element(elId).GetExternalFileReference();
if (ExternalFileReferenceType.RevitLink == fileRef.ExternalFileReferenceType)
listPath.Add(ModelPathUtils.ConvertModelPathToUserVisiblePath(fileRef.GetAbsolutePath()));
}
}
return listPath;
}
/// <summary>
/// 根据链接文件名称找到对应链接路径,模糊匹配,待改进
/// </summary>
/// <param name="listPath"></param>
/// <param name="strKey"></param>
/// <returns></returns>
private string GetPath(List< string> listPath, string strKey)
{
foreach ( string strPath in listPath)
{
if (strPath.Contains(strKey))
return strPath;
}
return "";
}
}