25
$\begingroup$

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.

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

1 Answer 1

26
$\begingroup$

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, ∞]], _Polygon, ∞]]

polygons for the B-spline surface, adaptive sampling

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_] /; ArrayQ[vl, 3] := 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]]]]

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, ∞]]

polygons for the B-spline surface, uniform sampling

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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.