public static Curve Flatten3dCurveOnPlane(Curve c, Plane plane) { XYZ meanPt = null; List <XYZ> orderedEigenvectors; XYZ normal; if (c is HermiteSpline) { var hs = c as HermiteSpline; if (plane == null) { plane = GetPlaneFromCurve(c, false); } var projPoints = new List <XYZ>(); foreach (var pt in hs.ControlPoints) { var proj = pt - (pt - plane.Origin).DotProduct(plane.Normal) * plane.Normal; projPoints.Add(proj); } return(dynRevitSettings.Revit.Application.Create.NewHermiteSpline(projPoints, false)); } if (c is NurbSpline) { var ns = c as NurbSpline; BestFitLine.PrincipalComponentsAnalysis(ns.CtrlPoints.ToList(), out meanPt, out orderedEigenvectors); normal = orderedEigenvectors[0].CrossProduct(orderedEigenvectors[1]).Normalize(); if (plane == null) { plane = dynRevitSettings.Doc.Application.Application.Create.NewPlane(normal, meanPt); } var projPoints = new List <XYZ>(); foreach (var pt in ns.CtrlPoints) { var proj = pt - (pt - plane.Origin).DotProduct(plane.Normal) * plane.Normal; projPoints.Add(proj); } return(dynRevitSettings.Revit.Application.Create.NewNurbSpline(projPoints, ns.Weights, ns.Knots, ns.Degree, ns.isClosed, ns.isRational)); } return(c); }
public static Plane GetPlaneFromCurve(Curve c, bool planarOnly) { //cases to handle //straight line - normal will be inconclusive //find the plane of the curve and generate a sketch plane double period = c.IsBound ? 0.0 : (c.IsCyclic ? c.Period : 1.0); var p0 = c.IsBound ? c.Evaluate(0.0, true) : c.Evaluate(0.0, false); var p1 = c.IsBound ? c.Evaluate(0.5, true) : c.Evaluate(0.25 * period, false); var p2 = c.IsBound ? c.Evaluate(1.0, true) : c.Evaluate(0.5 * period, false); if (c is Line) { var v1 = p1 - p0; var v2 = p2 - p0; XYZ norm = null; //keep old plane computations if (Math.Abs(p0.Z - p2.Z) < 0.0001) { norm = XYZ.BasisZ; } else { var p3 = new XYZ(p2.X, p2.Y, p0.Z); var v3 = p3 - p0; norm = v1.CrossProduct(v3); if (norm.IsZeroLength()) { norm = v2.CrossProduct(XYZ.BasisY); } norm = norm.Normalize(); } return(new Plane(norm, p0)); } CurveLoop cLoop = new CurveLoop(); cLoop.Append(c.Clone()); if (cLoop.HasPlane()) { return(cLoop.GetPlane()); } if (planarOnly) { return(null); } IList <XYZ> points = c.Tessellate(); List <XYZ> xyzs = new List <XYZ>(); for (int iPoint = 0; iPoint < points.Count; iPoint++) { xyzs.Add(points[iPoint]); } //var v1 = p1 - p0; //var v2 = p2 - p0; //var norm = v1.CrossProduct(v2).Normalize(); ////Normal can be zero length in the case of a straight line ////or a curve whose three parameter points as measured above ////happen to lie along the same line. In this case, project ////the last point down to a plane and use the projected vector ////and one of the vectors from above to calculate a normal. //if (norm.IsZeroLength()) //{ // if (p0.Z == p2.Z) // { // norm = XYZ.BasisZ; // } // else // { // var p3 = new XYZ(p2.X, p2.Y, p0.Z); // var v3 = p3 - p0; // norm = v1.CrossProduct(v3); // } //} //var curvePlane = new Plane(norm, p0); XYZ meanPt; List <XYZ> orderedEigenvectors; BestFitLine.PrincipalComponentsAnalysis(xyzs, out meanPt, out orderedEigenvectors); var normal = orderedEigenvectors[0].CrossProduct(orderedEigenvectors[1]); var plane = dynRevitSettings.Doc.Application.Application.Create.NewPlane(normal, meanPt); return(plane); }