1.项目基点获取:
// 获取项目原点位置
ProjectPosition projectPosition = doc.ActiveProjectLocation.GetProjectPosition(XYZ.Zero);
XYZ translationVector = new XYZ(projectPosition.EastWest, projectPosition.NorthSouth, 0);
Transform translationTransform = Transform.CreateTranslation(translationVector);
Transform rotationTransform = Transform.CreateRotation(XYZ.BasisZ, projectPosition.Angle);
Transform finalTransform = translationTransform.Multiply(rotationTransform);
2.链接文件坐标转换为模型坐标
///
/// 获取当前文档中的连接文件
///
///
///
public static List GetLinkDoc(Document doc)
{
FilteredElementCollector linkInstances = new FilteredElementCollector(doc);
linkInstances = linkInstances.WherePasses(new ElementClassFilter(typeof(RevitLinkInstance)));
if (linkInstances != null && linkInstances.Any())
{
List listElementInfo = new List();
foreach (RevitLinkInstance linkIns in linkInstances)
{
var listLinkInsts = LinkInstanceAnalyse(doc, linkIns);
if (listLinkInsts != null)
{
listElementInfo.AddRange(listLinkInsts);
}
}
return listElementInfo;
}
return null;
}
///
/// 链接文件实例解析
///
///
///
///
public static List LinkInstanceAnalyse(Document doc, RevitLinkInstance linkIns)
{
var linkdDocTrans = linkIns.GetTransform();
Autodesk.Revit.DB.Document linkDoc = linkIns.GetLinkDocument();
if (linkDoc != null)
{
//选取你想要的构件
var instances = RevitUtil.GetFamilyInstances(linkDoc);
CategorySet categorySet = RevitUtil.DocBindingParamCategory(linkDoc);
//其他专业有很多元素不是族实例,为线和片段,所以这里根据元数据编码的大类来批量获取
//即可获取族实例,也可以获取其他片段和线段数据
if (categorySet != null)
{
instances = RevitUtil.GetElements(linkDoc, categorySet);
}
List listElementInfo = new List();
foreach (var element in instances)
{
//调用链接文件的解析方式
ElementInfo elementInfo = RevitUtil.ElInstanceToInfo(element, doc.ActiveView);
if (elementInfo.CenterXyz != null)
{
//通过链接模型实例转换器,将链接文件中的坐标转为当前文件打开视图的全局坐标
elementInfo.CenterXyz = linkdDocTrans.OfPoint(elementInfo.CenterXyz);
if (elementInfo.MaxLocation != null)
{
//通过链接模型实例转换器,将链接文件中的坐标转为当前文件打开视图的全局坐标
elementInfo.MaxLocation = linkdDocTrans.OfPoint(elementInfo.MaxLocation);
}
if (elementInfo.MinLocation != null)
{
//通过链接模型实例转换器,将链接文件中的坐标转为当前文件打开视图的全局坐标
elementInfo.MinLocation = linkdDocTrans.OfPoint(elementInfo.MinLocation);
}
listElementInfo.Add(elementInfo);
}
}
return listElementInfo;
}
return null;
}
3.将链接文件中构件的模型坐标,转为项目的基点坐标参考,projectLocationTransform为第一步获取的基点转换器
//读取链接文件的解析和当前文档中的解析数据
var linkInstElInfos = RevitUtil.GetLinkDoc(document);
//链接文件不为空时,解析
if (linkInstElInfos != null)
{
//将链接文件中的坐标点转为当前项目模型文件中的 基点坐标点和实际地理位置坐标对应
foreach (ElementInfo elementInfo in linkInstElInfos)
{
if (elementInfo.CenterXyz != null)
{
//将构件的中心点坐标转换为基点项目所在的坐标
var CenterXyz = projectLocationTransform.OfPoint(elementInfo.CenterXyz);
elementInfo.CenterXyz = RevitUtil.ConvertXyzToProjectUnit(document, CenterXyz);
if (elementInfo.MaxLocation != null)
{
//将构件的最大点坐标转换为基点项目所在的坐标
var MaxLocation = projectLocationTransform.OfPoint(elementInfo.MaxLocation);
elementInfo.MaxLocation = RevitUtil.ConvertXyzToProjectUnit(document, MaxLocation);
}
if (elementInfo.MinLocation != null)
{
//将构件的最小点坐标转换为基点项目所在的坐标
var MinLocation = projectLocationTransform.OfPoint(elementInfo.MinLocation);
elementInfo.MinLocation = RevitUtil.ConvertXyzToProjectUnit(document, MinLocation);
}
//链接文件放入集合中
listElementInfo.Add(elementInfo);
}
}
}
4.获取构件Element/族实例的坐标系,下面代码只是参考,因为只读取了最大最小两点,使用到了构件元素的参考点,试图裁剪,族坐标实例转换等方式。
public static void Getinfo_ElementLocation(Element elem, ref ElementInfo elInfo, View view)
{
try
{
if (elInfo != null)
{
//获取到Element的裁剪框。//三维矩形,立方体
BoundingBoxXYZ cropBox = elem.get_BoundingBox(view);
if (cropBox != null)
{
//获取到裁剪框的 最大和最小2个顶点。
elInfo.MaxLocation = cropBox.Transform.OfPoint(cropBox.Max);
elInfo.MinLocation = cropBox.Transform.OfPoint(cropBox.Min);
//计算构建的中心点位置坐标
elInfo.CenterXyz = new XYZ((elInfo.MaxLocation.X + elInfo.MinLocation.X) / 2, (elInfo.MaxLocation.Y + elInfo.MinLocation.Y) / 2, (elInfo.MaxLocation.Z + elInfo.MinLocation.Z) / 2);
}
//保存Element参考点坐标位置,不一定是中心点
var transform = Transform.Identity;
if (elem is FamilyInstance)
{
var fmInst = elem as FamilyInstance;
//获取实例的坐标点,覆盖计算的中心坐标点
LocationPoint location = fmInst.Location as LocationPoint;
if (location != null)
{
//判断当前坐标点不为零点,正常情况下,应该不为0,0,0
if (!location.Point.X.Equals(0) && !location.Point.Y.Equals(0))
{
elInfo.CenterXyz = location.Point;
}
}
//根据族中的包围盒大小,转换到模型中,计算最大最小
try
{
FamilySymbol familySymbol = fmInst.Symbol;
BoundingBoxXYZ bBoxSymbol = familySymbol.get_BoundingBox(view);
XYZ bBoxMax = bBoxSymbol.Max;
XYZ bBoxMin = bBoxSymbol.Min;
transform = fmInst.GetTransform();
if (bBoxMax != null && bBoxMin != null)
{
XYZ trbBoxMax = transform.OfPoint(bBoxMax);
XYZ trbBoxMin = transform.OfPoint(bBoxMin);
//获取到最大和最小2个顶点。
elInfo.MaxLocation = trbBoxMax;
elInfo.MinLocation = trbBoxMin;
//计算构建的中心点位置坐标
elInfo.CenterXyz = new XYZ((elInfo.MaxLocation.X + elInfo.MinLocation.X) / 2, (elInfo.MaxLocation.Y + elInfo.MinLocation.Y) / 2, (elInfo.MaxLocation.Z + elInfo.MinLocation.Z) / 2);
}
}
catch (Exception)
{ }
//计算是否有自由点参考引用,如果有,则采用参考点作为范围
IList listref = fmInst.GetFamilyPointPlacementReferences();
if (listref != null)
{
if (listref.Count > 1)
{
//参考值最大和最小2个顶点。
elInfo.MaxLocation = listref[0].Location.Origin;
elInfo.MinLocation = listref[1].Location.Origin;
//计算构建的中心点位置坐标
elInfo.CenterXyz = new XYZ((elInfo.MaxLocation.X + elInfo.MinLocation.X) / 2, (elInfo.MaxLocation.Y + elInfo.MinLocation.Y) / 2, (elInfo.MaxLocation.Z + elInfo.MinLocation.Z) / 2);
}
}
}
}
}
catch (Exception)
{ }
}
5.构件几何数据获取,下面代码只是参考,由于项目需要,暂时只获取的构件的轮廓坐标,需要所有坐标的话,把Mesh中的点都记录下来即可,获取的构件坐标,可以通过2步骤,转换为项目基点坐标系。
///
/// 获取元素构件的8个边的坐标值
///
///
public static List GetElementPoints(Element element)
{
List points = new List();
try
{
解析实例的几何数据
//FamilyInstance familyInstance = element as FamilyInstance;
//var familyTrans = familyInstance.GetTransform();
Options opt = new Options();
opt.ComputeReferences = false;
opt.DetailLevel = ViewDetailLevel.Undefined;
GeometryElement e = element.get_Geometry(opt);
//解析几何数据
foreach (GeometryObject obj in e)
{
if (obj is GeometryInstance)
{
GeometryInstance geoInstance = obj as GeometryInstance;
GeometryElement geoElement = geoInstance.GetInstanceGeometry();
foreach (GeometryObject obj2 in geoElement)
{
Solid solid = obj2 as Solid;
if (null == solid || 0 == solid.Faces.Size || 0 == solid.Edges.Size)
{
continue;
}
Transform instTransform = geoInstance.Transform;
// 从实体Solid获取面和边,提取轮廓不需要所有面的数据,只需要边即可
foreach (Edge edge in solid.Edges)
{
Curve curve = edge.AsCurve();
//按道理来说这里是需要进行族转换器进行坐标转换的
//取起点和终点即可
points.Add(curve.GetEndPoint(0));
points.Add(curve.GetEndPoint(1));
}
}
}
else if (obj is Solid)
{
Solid solid = obj as Solid;
if (null == solid || 0 == solid.Faces.Size || 0 == solid.Edges.Size)
{
continue;
}
// 从实体Solid获取面和边,提取轮廓不需要所有面的数据,只需要边即可
foreach (Edge edge in solid.Edges)
{
Curve curve = edge.AsCurve();
//按道理来说这里是需要进行族转换器进行坐标转换的
//取起点和终点即可
points.Add(curve.GetEndPoint(0));
points.Add(curve.GetEndPoint(1));
}
}
else if (obj is Mesh)
{
//Mesh mesh = obj as Mesh;
//mesh.get
//foreach (XYZ ii in mesh.Vertices)
//{
// //按道理来说这里是需要进行族转换器进行坐标转换的
// points.Add(ii);
//}
}
}
}
catch (Exception)
{ }
return points;
}
参考:
https://blog.csdn.net/Dai_Aixy/article/details/103150898