Dennis
Dennis

Reputation: 341

Morph circle to oval in openscad

I am trying to create a fan duct in openscad, flattening the duct from circular to oval. Is there a way to do this in openscad? If not, is there any other programmatic way to generate this type of 3d model?

Thanks Dennis

Upvotes: 5

Views: 7526

Answers (4)

Gabriel Robinson
Gabriel Robinson

Reputation: 21

I like Chris Wallace answer but there was a bug in the Minkwoski, it should be h=Delta.

module tube(height, radius, eccentricity=1, thickness) {
    difference() {
      minkowski() {
        connector(height,radius,eccentricity);
        cylinder(h=Delta,r=thickness);
      }
    translate([0,0,-(Delta+thickness)]) 
        connector(height + 2* (Delta +thickness) ,radius, eccentricity);
    }
  }

tube(20,8,0.6,2);

Upvotes: 2

a_manthey_67
a_manthey_67

Reputation: 4306

There is another way by using the „scale“-parameter of linear_extrude(). It „scales the 2D shape by this value over the height of the extrusion. Scale can be a scalar or a vector“ (Documentation). Using a vector with x- and y-scalefactor, you get the modification, you wanted:

d = 2;        // height of ellipsoid, diameter of bottom circle
t = 0.25;     // wall thickness
w = 4;        // width of ellipsoid
l = 10;       // length of extrusion

module ellipsoid(diameter, width, height) {
    linear_extrude(height = height, scale = [width/diameter,1]) circle(d = diameter); 
  }

difference() {
    ellipsoid(d,w,l);
    ellipsoid(d-2*t,w-2*t,l);
  }

Upvotes: 5

Chris Wallace
Chris Wallace

Reputation: 515

Assuming by 'oval' you mean elipse, then the following creates a solid tapering from a circle to an ellipse:

    Delta=0.01;

    module connector (height,radius,eccentricity) {
        hull() {
          linear_extrude(height=Delta)
             circle(r=radius);
          translate([0,0,height - Delta])   
             linear_extrude(height=Delta) 
                scale([1,eccentricity]) 
                   circle(r=radius);
        }
      }

      connector(20,6,0.6);

You could make the tube by subtracting a smaller version:

module tube(height, radius, eccentricity=1, thickness) {
     difference() {
       connector(height,radius,eccentricity);
       translate([0,0,-(Delta+thickness)]) 
         connector(height + 2* (Delta +thickness) ,radius-thickness, eccentricity);
     }
   }
   tube(20,8,0.6,2);

but the wall thickness will not be uniform. To make a uniform wall, use minkowski to add the wall:

module tube(height, radius, eccentricity=1, thickness) {
    difference() {
      minkowski() {
        connector(height,radius,eccentricity);
        cylinder(height=height,r=thickness);
      }
    translate([0,0,-(Delta+thickness)]) 
        connector(height + 2* (Delta +thickness) ,radius, eccentricity);
    }
  }

tube(20,8,0.6,2);

Upvotes: 10

jwygralak67
jwygralak67

Reputation: 934

I don't know of a way to do it directly, but I can imagine approximating it with a series of stacked slices.

Start with a circle, and have a loop that changes the scale factor smoothly from circle to oval as you add slices to the stack. This will give you a stepped surface. If this is for a 3D printing application, if you make your slice thickness the same as your layer height, you might not even notice.

Upvotes: 0

Related Questions