对于模型线ModelCurve的偏移,研究了好几天,终于搞定。先稍微谈下自己中间遇到的情况。
1.首先,API中并没有提供直接的方法对ModelCurve进行偏移;
2.考虑到模型线的创建,需要用到参数Curve,因此想到了对先Curve进行偏移,API提供了相应的方法:Curve.CreatOffset
3.对Curve偏移过后,发现对应的模型线并未改变。然后才发现,需要对modelCurve.GeometryCurve重新赋值才行。
4.其中有个细节,在本例中为什么先创建了模型线,然后再进行偏移,而不是创建和偏移一步到位?我做了测试,效果明显不同。
如果是创建和偏移同时进行,即没有预先做好模型线,那偏移完后的线是散开的,或者是交叉的;
而如果先创建了模型线,(本例中,先创建了封闭一圈的墙,然后根据墙基线创建的模型线),此时模型线自动形成封闭图形,各自已有关联性。然后再对Curve进行偏移,对GeometryCurve进行修改,各自的ModelCurve还是会继续关联。不过也正是因为关联性,所以会引出新的问题:同一条线上,有3个Curve,偏移了一根,其他两根也会跟着动,那遍历的时候怎么办?会自动偏移三次。比如想偏移500mm,实际结果却是500*3=1500mm。
5.偏移命令中有一个参数,XYZ normal,研究了好半天,才终于搞明白如何运用:
简单来说,通常我们的Curve都是在XY平面中进行操作,因此XYZ可以直接取值(0,0,1),也就是Z轴方向。其实所谓的偏移方向由两个向量的叉乘得来,即偏移方向=Curve方向 叉乘 参考向量normal方向。(右手螺旋法则:大拇指指向为偏移后线的方向)
设想一下,XY平面内的Curve,如何在叉乘一个参考向量后,还在XY平面内呢?显然这个参考向量必须是垂直于XY平面的,那我们就直接取Z轴方向(0,0,1)即可。附图作为参考,白线为XY平面内的Curve,红线为偏移后的状态,绿线为Z轴
下面上一段代码,对REVIT中的模型,拾取其墙列表,然后获得墙的基线,最后根据基线,创建模型线,并对其进行偏移。
UIDocument uidoc = commandData.Application.ActiveUIDocument;
Document doc = uidoc.Document;
//获取墙List
FilteredElementCollector wallCollector = new FilteredElementCollector(doc);
List
wallCollector.OfCategory(BuiltInCategory.OST_Walls).OfClass(typeof(Wall)).
ToList().ConvertAll(x=>x as Wall);
//获取墙的基线List
ElementId wallLevelID = null;
List
foreach(Wall wall in wallList)
{
Curve wallCurve = (wall.Location as LocationCurve).Curve;
curveList.Add(wallCurve);
wallLevelID = wall.LevelId;
}
//创建模型线
List
foreach(var curve in curveList)
{
Transaction ts1 = new Transaction(doc, "info");
ts1.Start();
SketchPlane sktchPlane = SketchPlane.Create(doc, wallLevelID);
ModelCurve modelCurve = doc.Create.NewModelCurve(curve,sktchPlane);
ts1.Commit();
modelCurveList.Add(modelCurve);
}
//对modelCurve进行偏移。modelCurve.GeometryCurve是可读可写的,一定要注意
//另外,还需注意要对modelCurve.GeometryCurve重新进行赋值。
//此处只是对CUVve进行了偏移,而没重新建立模型线
//而如果,先对Curve进行偏移,再生成模型线呢?==>试过了,这样就没有关联性。
foreach (var modelCurve in modelCurveList)
{
Transaction ts1 = new Transaction(doc, "info");
ts1.Start();
//下面这行一定要注意,如果只写curve.CreateOffset(500 / 304.8, new XYZ(0,0,1));
//是没有变化的,只是使用了方法,但是并没有给curve重新赋值。
modelCurve.GeometryCurve=
modelCurve.GeometryCurve.CreateOffset(500 / 304.5, new XYZ(0, 0, 1));
ts1.Commit();
}
return Result.Succeeded;
之前有个误区,想改变ModelCurve,就想的改变对应的Curve就行,其实没问题。不过并没有想到直接对GeometryCurve进行修改(可读可写),而且就算想到了,也会忘记重新赋值。
可读可写这个思路,来自由叶先生的blog,以后还需多多光顾才是。