# Convert Graphics3D containing BSpline to polygon primitives for export to 3DS?

Graphics3D[] objects created with BSpline functions will not export to 3DS format, which only supports the more basic primitives. Is there any straightforward way to get at an underlying polygon representation of the BSplineSurface[] graphics "primitive" (in quotes because its not very primitive)?

An example is the final 'pipe' example in the documentation ref/BSplineSurface. If you try Export["Pipe.3ds", %], you get an error.

In my particular case I'm creating arbitrary 'surface of revolution' objects as per the "Potter's Wheel" demonstration, where the cross section is determined by a BSpline with dynamic control points. That works fine, but then I need export the resulting objects to another program.

-
Welcome to Mathematica SE! Please include a sample code snippet -- you will get faster/better answers that way. – Ajasja Aug 9 '12 at 14:02
Welcome to Mathematica.SE! Good question. Would you mind providing an example of a surface you try to export? That would make playing around that much easier. – Yves Klett Aug 9 '12 at 14:02
Under most definitions of straightforward, I don't believe there is. You may have to write a program that converts it into graphics primitives. – Searke Aug 9 '12 at 14:02

I don't know what you'll count as "straightforward", but...

(* data for B-spline surface, from example in docs *)
pts = {{{0.5, 0, -0.5}, {0, 0, -0.5}, {0, 1, -0.5}, {0.5, 1, -0.5}, {1, 1, -0.5},
{1, 0, -0.5}, {0.5, 0, -0.5}},
{{0.5, 0, 0.7}, {0, 0, 0.7}, {0, 1, 0.7}, {0.5, 1, 0.7}, {1, 1, 0.7},
{1, 0, 0.7}, {0.5, 0, 0.7}},
{{0.5, 0, 0.9}, {0, 0, 0.9}, {0, 1, 1.5}, {0.5, 1, 1.5}, {1, 1, 1.5},
{1, 0, 0.9}, {0.5, 0, 0.9}},
{{0.5, -0.1, 1}, {0, -0.1, 1}, {0, 0.5, 2}, {0.5, 0.5, 2}, {1, 0.5, 2},
{1, -0.1, 1}, {0.5, -0.1, 1}},
{{0.5, -0.3, 1}, {0, -0.3, 1}, {0, -0.3, 2}, {0.5, -0.3, 2},
{1, -0.3, 2}, {1, -0.3, 1}, {0.5, -0.3, 1}},
{{0.5, -1.5, 1}, {0, -1.5, 1}, {0, -1.5, 2}, {0.5, -1.5, 2},
{1, -1.5, 2}, {1, -1.5, 1}, {0.5, -1.5, 1}}};
w = {{1, .5, .5, 1, .5, .5, 1}, {1, .5, .5, 1, .5, .5, 1},
{1, .5, .5, 1, .5, .5, 1}, {1, .5, .5, 1, .5, .5, 1},
{1, .5, .5, 1, .5, .5, 1}, {1, .5, .5, 1, .5, .5, 1}};
uk = {0, 0, 0, 1/4, 1/2, 3/4, 1, 1, 1};
vk = {0, 0, 0, 1/4, 1/2, 1/2, 3/4, 1, 1, 1};

Graphics3D[
BSplineSurface[pts, SplineKnots -> {uk, vk}, SplineDegree -> 2,
SplineWeights -> w, SplineClosed -> {False, True}]] /.
bs : BSplineSurface[pts_?ArrayQ, opts___] :>
Module[{bsf = BSplineFunction[pts, opts]},
Cases[Normal[
Cases[ParametricPlot3D[bsf[u, v], {u, 0, 1}, {v, 0, 1}], _GraphicsComplex, Infinity]
], _Polygon, Infinity]]


You can check that the output is composed entirely of Polygon[] objects. If need be, you can tweak the options within ParametricPlot3D[].

From the comments, it was asked how one might do a version where the sampling is uniform and the polygons are quadrilaterals. The old version of ParametricPlot3D[] did something like that. Here's how I'd emulate it:

MakePolygons[vl_] := Module[{dims = Most[Dimensions[vl]]},
GraphicsComplex[Apply[Join, vl], Polygon[Flatten[Apply[Join[#1, Reverse[#2]] &,
Partition[Partition[Range[Times @@ dims], Last[dims]], {2, 2}, {1, 1}],
{2}], 1]]]] /; ArrayQ[vl, 3]

Graphics3D[
BSplineSurface[pts, SplineKnots -> {uk, vk}, SplineDegree -> 2,
SplineWeights -> w, SplineClosed -> {False, True}]] /.
bs : BSplineSurface[pts_?ArrayQ, opts___] :>
Module[{bsf = BSplineFunction[pts, opts], upts = 30, vpts = 18},
Cases[Normal[MakePolygons[
Table[bsf[u, v], {u, 0, 1, 1/(upts - 1)}, {v, 0, 1, 1/(vpts - 1)}]
]], _Polygon, Infinity]]


-
Wicked! How´d you arrive at that one? – Yves Klett Aug 9 '12 at 14:44
Well, I know that BSplineSurface[] and BSplineCurve[] are always convertible in terms of BSplineFunction[]... then, it was a matter of extracting polygons from ParametricPlot3D[]. – J. M. Aug 9 '12 at 14:48
My impression is the the whole BSpline surface stuff is still a bit standalone (not to say orphaned). – Yves Klett Aug 9 '12 at 15:08
Maybe we should ask Yu-Sung about that... – J. M. Aug 9 '12 at 15:09
Definitely...he did show rather more advanced stuff some time ago which allegedly did not make the release... – Yves Klett Aug 9 '12 at 15:18