private void AppendSurfaceGeometry(StringBuilder sb, NurbsSurface ns) { if (ns == null) { return; } double ulength; double vlength; // reparametrize to real world length to minimize distortion in the map from parameter space to 3D if (ns.GetSurfaceSize(out ulength, out vlength)) { ns.SetDomain(0, new Interval(0, ulength)); ns.SetDomain(1, new Interval(1, vlength)); } // write knot vectors bool first = true; foreach (var ku in ns.KnotsU) { sb.AppendFormat(" SARN S {0:F8}", ku); if (first) { sb.AppendFormat(" DEGS {0}", ns.OrderU - 1); first = false; } sb.AppendLine(); } first = true; foreach (var kv in ns.KnotsV) { sb.AppendFormat(" SARN T {0:F8}", kv); if (first) { sb.AppendFormat(" DEGT {0}", ns.OrderV - 1); first = false; } sb.AppendLine(); } // write control points for (int i = 0; i < ns.Points.CountV; ++i) { for (int j = 0; j < ns.Points.CountU; ++j) { var cpt = ns.Points.GetControlPoint(j, i); double w = cpt.Weight; sb.AppendFormat(" SARP NURB {0} {1}", j + 1, i + 1); sb.AppendFormat(" X {0:F8} {1:F8} {2:F8} {3:F8}", cpt.X / w, cpt.Y / w, cpt.Z / w, w); sb.AppendLine(); } } }