static internal IEnumerable <Autodesk.Revit.DB.Curve> ToHost(this Rhino.Geometry.Curve curve, double curveTolerance = double.PositiveInfinity) { curveTolerance = Math.Min(Revit.ShortCurveTolerance, Math.Abs(curveTolerance)); Debug.Assert(!curve.IsShort(curveTolerance)); var simplifiedCurve = curve.Simplify(CurveSimplifyOptions.SplitAtFullyMultipleKnots, curveTolerance, Revit.AngleTolerance); if (simplifiedCurve != null) { curve = simplifiedCurve; } switch (curve) { case Rhino.Geometry.LineCurve line: yield return(Autodesk.Revit.DB.Line.CreateBound(line.PointAtStart.ToHost(), line.PointAtEnd.ToHost())); break; case Rhino.Geometry.PolylineCurve polyline: for (int p = 1; p < polyline.PointCount; ++p) { yield return(Autodesk.Revit.DB.Line.CreateBound(polyline.Point(p - 1).ToHost(), polyline.Point(p).ToHost())); } break; case Rhino.Geometry.ArcCurve arc: if (arc.IsClosed) { yield return(Autodesk.Revit.DB.Arc.Create(arc.Arc.Plane.ToHost(), arc.Arc.Radius, 0.0, (2.0 * Math.PI) - 2e-8)); } else { yield return(Autodesk.Revit.DB.Arc.Create(arc.Arc.StartPoint.ToHost(), arc.Arc.EndPoint.ToHost(), arc.Arc.MidPoint.ToHost())); } break; case Rhino.Geometry.PolyCurve polyCurve: polyCurve.RemoveNesting(); polyCurve.RemoveShortSegments(curveTolerance); for (int s = 0; s < polyCurve.SegmentCount; ++s) { foreach (var segment in polyCurve.SegmentCurve(s).ToHost()) { yield return(segment); } } break; case Rhino.Geometry.NurbsCurve nurbsCurve: if (nurbsCurve.IsLinear(Revit.VertexTolerance)) { yield return(Autodesk.Revit.DB.Line.CreateBound(nurbsCurve.PointAtStart.ToHost(), nurbsCurve.PointAtEnd.ToHost())); yield break; } if (nurbsCurve.TryGetPolyline(out var polylineSegment)) { polylineSegment.ReduceSegments(curveTolerance); foreach (var segment in polylineSegment.GetSegments()) { yield return(Autodesk.Revit.DB.Line.CreateBound(segment.From.ToHost(), segment.To.ToHost())); } yield break; } if (nurbsCurve.TryGetArc(out var arcSegment, Revit.VertexTolerance)) { yield return(Autodesk.Revit.DB.Arc.Create(arcSegment.StartPoint.ToHost(), arcSegment.EndPoint.ToHost(), arcSegment.MidPoint.ToHost())); yield break; } if (nurbsCurve.IsClosed) { if (nurbsCurve.TryGetCircle(out var circle, Revit.VertexTolerance)) { yield return(Autodesk.Revit.DB.Arc.Create(circle.Plane.ToHost(), circle.Radius, 0.0, 2.0 * (2.0 * Math.PI) - 2e-8)); yield break; } if (nurbsCurve.TryGetEllipse(out var ellipse, Revit.VertexTolerance)) { yield return(Autodesk.Revit.DB.Ellipse.CreateCurve(ellipse.Plane.Origin.ToHost(), ellipse.Radius1, ellipse.Radius2, ellipse.Plane.XAxis.ToHost(), ellipse.Plane.YAxis.ToHost(), 0.0, (2.0 * Math.PI) - 2e-8)); yield break; } foreach (var segment in nurbsCurve.Split(nurbsCurve.Domain.Mid)) { foreach (var c in segment.ToHost()) { yield return(c); } } } else { nurbsCurve.Knots.RemoveMultipleKnots(1, nurbsCurve.Degree, Revit.VertexTolerance); var degree = nurbsCurve.Degree; var knots = nurbsCurve.Knots.ToHost(); var controlPoints = nurbsCurve.Points.ToHost(); Debug.Assert(degree >= 1); Debug.Assert(controlPoints.Count > nurbsCurve.Degree); Debug.Assert(knots.Count == nurbsCurve.Degree + controlPoints.Count + 1); Autodesk.Revit.DB.Curve nurbSpline = null; try { if (nurbsCurve.IsRational) { var weights = new List <double>(controlPoints.Count); foreach (var p in nurbsCurve.Points) { Debug.Assert(p.Weight > 0.0); weights.Add(p.Weight); } Debug.Assert(weights.Count == controlPoints.Count); nurbSpline = NurbSpline.CreateCurve(nurbsCurve.Degree, knots, controlPoints, weights); } else { nurbSpline = NurbSpline.CreateCurve(nurbsCurve.Degree, knots, controlPoints); } } catch (Autodesk.Revit.Exceptions.ApplicationException e) { Debug.Fail(e.Source, e.Message); } yield return(nurbSpline); } break; default: foreach (var c in curve.ToNurbsCurve().ToHost()) { yield return(c); } break; } }