用的是几何的线相交的知识,通过以目标点往x轴一个方向做延长线,再判断与这一个闭合轮廓的线相交的情况,通过相交点的数量来最终得出是否在这个闭合轮廓内。
原文链接: https://blog.csdn.net/Oneal5354/article/details/108284693.
方法示例
public static class SomeMethod
{
public static bool IsInsideOutline(this XYZ TargetPoint, List<Line> lines)
{
bool result = true;
int insertCount = 0;
Line rayLine = Line.CreateBound(TargetPoint, TargetPoint.Add(XYZ.BasisX * 1000));
foreach (var areaLine in lines)
{
SetComparisonResult interResult = areaLine.Intersect(rayLine, out IntersectionResultArray resultArray);
IntersectionResult insPoint = resultArray?.get_Item(0);
if (insPoint != null)
{
insertCount++;
}
}
//如果次数为偶数就在外面,次数为奇数就在里面
if (insertCount % 2 == 0)//偶数
{
return result = false;
}
return result;
}
}
主程序调用
class test : IExternalCommand
{
public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
{
try
{
UIDocument uidoc = commandData.Application.ActiveUIDocument;
Document doc = uidoc.Document;
XYZ xyz = uidoc.Selection.PickPoint(ObjectSnapTypes.Endpoints, "Select Point");
TaskDialog.Show("Point", xyz.ToString());
Reference refer = uidoc.Selection.PickObject(ObjectType.Face, "Select Face");
Face face = doc.GetElement(refer).GetGeometryObjectFromReference(refer) as Face;
IList<CurveLoop> faceCurveLoopList = face.GetEdgesAsCurveLoops();
List<Line> faceLineList = new List<Line>();
foreach (CurveLoop curveloop in faceCurveLoopList)
{
foreach (Curve curve in curveloop)
{
Line line1 = Line.CreateBound(curve.GetEndPoint(0), curve.GetEndPoint(1));
faceLineList.Add(line1);
}
}
bool insideOrNot = SomeMethod.IsInsideOutline(xyz,faceLineList);
TaskDialog.Show("Face", face.ToString());
TaskDialog.Show("1", insideOrNot.ToString());
}
catch (Exception ex)
{
message = ex.Message;
return Result.Failed;
}
return Result.Succeeded;
}
}
当交点数为奇数时,说明点在这个轮廓内。这里有需要注意的地方是,这一条线必须是完全穿过这个轮廓的,而且在revit中得到的线不是一定在同一个平面中,因此我们需要自己封装一个方法来把线放到同一个平面上。如果确定在同一平面上那就可以不用封装这一个方法。