/// <summary>
/// Поиск пересечения плоскости и кривой (без учета виртуальных продолжений кривой)
/// </summary>
public static Point3dCollection IntersectWith(this Plane plane, Curve curve)
{
Point3dCollection ret = new Point3dCollection();
if (plane == null || curve == null || curve.IsErased) return ret;
Curve projectedCurve = curve.GetProjectedCurve(plane, plane.Normal);
projectedCurve.IntersectWith(curve, Intersect.OnBothOperands, ret, IntPtr.Zero, IntPtr.Zero);
Point3dCollection ret1 = new Point3dCollection();
// Спроецированный сплайн может пройти через точку несколько раз туда-обратно -> надо удалить копии точки
foreach(Point3d p in ret)
{
bool contain = false;
foreach(Point3d old in ret1)
if(old.Approx()==p.Approx())
{ contain = true; break; }
if (!contain) ret1.Add(p);
}
ret.Dispose();
ret = ret1;
if (ret.Count == 0) // не факт, что это правда. Возможно глюк работы со сплайнами. Проверим
{
if (curve.IsPlanar)
{
using (Plane curvePlane = curve.GetPlane())
{
if (curvePlane.IsCoplanarTo(plane) || curvePlane.IsParallelTo(plane)) return ret;
if (!(curve is Line) && projectedCurve is Spline) // SplineIntersectWith в этом случае не работает
if (curvePlane.IsPerpendicularTo(plane)) // проекция вырождается в линию
{
Line aline = projectedCurve.ApproxLine();
// ищем на продолжениях проекции, т.к. проекция может быть длиннее, чем расстояние от начальной до конечной точки
aline.IntersectWith(curve, Intersect.ExtendThis, ret, IntPtr.Zero, IntPtr.Zero);
aline.Dispose();
}
}
}
if (ret.Count == 0)
// с линией не получилось. проверим хотя бы одну точку на плоскости
try // Curve.GetClosestPointTo тоже не работает со сплайнами, поэтому вызываем исключение в GetParameterAtPoint
{
double param = curve.GetParameterAtPoint(plane.PointOnPlane); // Если нет исключения, то точка на кривой
ret.Add(plane.PointOnPlane);
}
catch { }
}
projectedCurve.Dispose();
return ret;
}
public static Line ApproxLine(this Curve spline)
{
if (spline == null || spline.IsErased || !spline.IsPlanar) return null;
Point3d start = spline.StartPoint;
Point3d end = spline.EndPoint;
if (start.Approx() == end.Approx())
end = spline.GetPointAtParameter(spline.StartParam + (spline.EndParam - spline.StartParam) / 2);
return new Line(start, end);
}