最近开始翻模旅程,根据跟群友讨论和网上的搜寻。初步方法为先拾取CAD梁的线段,根据线段所在图层,取得所有梁的最长的那2段线。这样情况下,一条梁仅有2段相等的且平行的直线(不在是一个矩形),具体如图1-1所示!。
图 1- 1 测试模型中对于梁的整图
这里要感谢一下CSDN niuge8905版主 https://blog.csdn.net/niuge8905/article/details/77160646 和 JohnnyWu0918 https://me.csdn.net/mye918 从他们的文章中找到了读取CAD线段的一些方法。
接下来上代码。
using Autodesk.Revit.ApplicationServices;
using Autodesk.Revit.DB;
using Autodesk.Revit.UI;
using Autodesk.Revit.UI.Selection;
using Autodesk.Revit.DB.Structure;
[Autodesk.Revit.Attributes.Transaction(Autodesk.Revit.Attributes.TransactionMode.Manual)]
class ReadCadCommand : IExternalCommand
{
Application app;
Document doc;
UIDocument uidoc;
/// <summary>
/// 正常梁宽度
/// </summary>
const double NormBeamWidth = 1000;//1000mm
/// <summary>
/// 所有正常梁宽度集合
/// </summary>
List<double> WidthList = new List<double>();
public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
{
uidoc = commandData.Application.ActiveUIDocument;
app = commandData.Application.Application;
doc = uidoc.Document;
Reference r;
try
{
r = uidoc.Selection.PickObject(ObjectType.PointOnElement,“选择梁的一边”);//选择一个元素
}
catch(Exception ex)
{
message = "您取消了本次操作!";
return Result.Failed;
}
//Reference r = uidoc.Selection.PickObject(ObjectType.PointOnElement);//选择一个元素
string ss = r.ConvertToStableRepresentation(doc);
Element elem = doc.GetElement(r);
GeometryElement geoElem = elem.get_Geometry(new Options());
GeometryObject geoObj = elem.GetGeometryObjectFromReference(r);
//获取选中的cad图层
Category targetCategory = null;
ElementId graphicsStyleId = null;
if (geoObj.GraphicsStyleId != ElementId.InvalidElementId)
{
graphicsStyleId = geoObj.GraphicsStyleId;
GraphicsStyle gs = doc.GetElement(geoObj.GraphicsStyleId) as GraphicsStyle;
if (gs != null)
{
targetCategory = gs.GraphicsStyleCategory;
var name = gs.GraphicsStyleCategory.Name;
}
}
//隐藏选中的cad图层
Transaction trans = new Transaction(doc, "隐藏图层");
trans.Start();
if (targetCategory != null)
doc.ActiveView.SetCategoryHidden(targetCategory.Id, false);
trans.Commit();
if (geoElem == null || graphicsStyleId == null)
{
message = "几何元素或ID不存在!";
return Result.Failed;
}
List<CADModel> curveArray_List = getCurveArray( doc,geoElem,graphicsStyleId);
List<CADModel> curveArray_List_copy = new List<CADModel>();//复制得到的模型
foreach (var OrginCADModle in curveArray_List)
{
curveArray_List_copy.Add(OrginCADModle);
}
//取得的模型的线的总数量
int LineNumber = curveArray_List.Count();
//存放不匹配的梁的相关线
List<CADModel> NotMatchCadModel = new List<CADModel>();
//存放模型数组的数组
List<List<CADModel>> CADModelList_List = new List<List<CADModel>>();
//int i = 0;
//筛选模型
while (curveArray_List.Count() > 0)
{
//存放距离
List<double> distanceList = new List<double>();
//存放对应距离的CADModel
List<CADModel> cADModel_B_List = new List<CADModel>();
var CadModel_A = curveArray_List[0];
curveArray_List.Remove(CadModel_A);//去除取出的梁的二段线段之一
if (curveArray_List.Count() >= 1)
{
foreach (var CadModel_B in curveArray_List)
{
//梁的2个段线非同一长度最大误差为50mm,方向为绝对值(然而sin120°=sin60°)
if ((float)Math.Abs(CadModel_A.rotation) == (float)Math.Abs(CadModel_B.rotation) && Math.Abs(CadModel_A.length - CadModel_B.length)<0.164)
{
double distance = CadModel_A.location.DistanceTo(CadModel_B.location);
distanceList.Add(distance);
cADModel_B_List.Add(CadModel_B);
}
}
if (distanceList.Count() != 0 && cADModel_B_List.Count != 0)
{
double distanceTwoLine = distanceList.Min();
//筛选不正常的宽度,如发现不正常,将CadModel_B继续放入数组
if (distanceTwoLine * 304.8 < NormBeamWidth && distanceTwoLine>0)
{
//TaskDialog.Show("1", (distanceTwoLine * 304.8).ToString());
var CadModel_shortDistance = cADModel_B_List[distanceList.IndexOf(distanceTwoLine)];
curveArray_List.Remove(CadModel_shortDistance);
//1对梁的模型装入数组
List<CADModel> cADModels = new List<CADModel>();
cADModels.Add(CadModel_A);
cADModels.Add(CadModel_shortDistance);
CADModelList_List.Add(cADModels);
//TaskDialog.Show("1", CadModel_A.location.ToString() + "\n" + CadModel_shortDistance.location.ToString());
}
}
else
{
NotMatchCadModel.Add(CadModel_A);
}
}
else
{
NotMatchCadModel.Add(CadModel_A);
}
}
TaskDialog.Show("1","未匹配的线有:"+ NotMatchCadModel.Count().ToString()+" 条!\n"+"匹配上的有:"+ CADModelList_List.Count().ToString()+" 对!\n"+"丢失:"+ (LineNumber- NotMatchCadModel.Count()- CADModelList_List.Count()*2).ToString()+" 条!\n");
//梁类别
FamilySymbol BeamTypeName = doc.GetElement(new ElementId(342873)) as FamilySymbol;
//默认标高2
Level level = LevelFilter(doc);
int tranNumber = 0;//用于改变事务的ID
//生成梁
foreach (var cadModelList in CADModelList_List)
{
CADModel cADModel_A = cadModelList[0];
CADModel cADModel_B = cadModelList[1];
//TaskDialog.Show("1", cADModel_A.location.ToString() + "\n" + cADModel_B.location.ToString());
var cADModel_A_StratPoint = cADModel_A.curveArray.get_Item(0).GetEndPoint(0);
var cADModel_A_EndPoint = cADModel_A.curveArray.get_Item(0).GetEndPoint(1);
var cADModel_B_StratPoint = cADModel_B.curveArray.get_Item(0).GetEndPoint(0);
var cADModel_B_EndPoint = cADModel_B.curveArray.get_Item(0).GetEndPoint(1);
XYZ ChangeXYZ = new XYZ();
var LineLength = (GetMiddlePoint(cADModel_A_StratPoint, cADModel_B_StratPoint)).DistanceTo(GetMiddlePoint(cADModel_A_EndPoint, cADModel_B_EndPoint));
if (LineLength <0.00328)//梁的2段线起点非同一端。2段线非同一长度,又非同一端的,中间点的误差选择为1mm
{
ChangeXYZ = cADModel_B_StratPoint;
cADModel_B_StratPoint = cADModel_B_EndPoint;
cADModel_B_EndPoint = ChangeXYZ;
}
Curve curve = Line.CreateBound((GetMiddlePoint(cADModel_A_StratPoint, cADModel_B_StratPoint)), GetMiddlePoint(cADModel_A_EndPoint, cADModel_B_EndPoint));
double distance = cADModel_A.location.DistanceTo(cADModel_B.location);
distance = Math.Round(distance * 304.8, 1);//作为梁_b的参数
WidthList.Add(distance);//梁宽度集合
string beamName = "ZBIM矩形梁 " + (float)(distance) + "*" + (float)(600) + "mm";//类型名 宽度*高度
if (!familSymbol_exists(beamName, "ZBIM - 矩形梁", doc))
{
MakeBeamType(beamName, "ZBIM - 矩形梁");
EditBeamType(beamName, (float)(distance), (float)(600));
}
//用于数据显示和选择,已注释
#region
//List<string> columnTypes = new List<string>();
//columnTypes = getBeamTypes(doc);
//bool repeat = false;
//foreach (string context in columnTypes)
//{
// if (context == beamName)
// {
// repeat = true;
// break;
// }
//}
//if (!repeat)
//{
// columnTypes.Add(beamName);
//}
#endregion
using (Transaction transaction = new Transaction(doc))
{
transaction.Start("Beadm Strart Bulid" + tranNumber.ToString());
FilteredElementCollector collector = new FilteredElementCollector(doc);
collector.OfClass(typeof(FamilySymbol)).OfCategory(BuiltInCategory.OST_StructuralFraming);
foreach (FamilySymbol beamType in collector)
{
if (beamType.Name == beamName)
{
if (!beamType.IsActive)
{
beamType.Activate();
}
FamilyInstance beamInstance = doc.Create.NewFamilyInstance(curve, beamType, level, StructuralType.Beam);
var Elevation = beamInstance.get_Parameter(BuiltInParameter.INSTANCE_REFERENCE_LEVEL_PARAM);
break;
}
}
transaction.Commit();
}
}
//取得未匹配的和丢失的CADModel
foreach (var cadModelList in CADModelList_List)
{
CADModel cADModel_A = cadModelList[0];
CADModel cADModel_B = cadModelList[1];
curveArray_List_copy.Remove(cADModel_A);
curveArray_List_copy.Remove(cADModel_B);
}
//一个方向的梁
List<CADModel> UpBeamCAdModel = new List<CADModel>();
//一个方向的梁
List<CADModel> CrossBeamCAdModel = new List<CADModel>();
//最大梁宽度
double MaxBeamWidth;
if (WidthList.Count() == 0)
{
MaxBeamWidth = 1000;//1000mm
}
else
{
MaxBeamWidth = WidthList.Max();
}
//判断是否位空
if (curveArray_List_copy.Count() > 1)
{
var OrginRotation = Math.Abs(curveArray_List_copy[0].rotation);
//分流,横在一起,竖在一起
foreach (var cadModle in curveArray_List_copy)
{
if (Math.Abs(cadModle.rotation) == OrginRotation)
{
CrossBeamCAdModel.Add(cadModle);
}
else
{
UpBeamCAdModel.Add(cadModle);
}
}