Python Tutorials (back to the list of tutorials)

## Various Curve/Surface Modeling Methods

### Offset Curves

You can offset curve with IG.offset(ICurve,double) method and the first argument is a curve to be offset and the second argument is the offset distance. If you put negative value at the offset distance, the offset direction is flipped.

```add_library('igeo')

size(480, 360, IG.GL)

cpts1 = [ IVec(-60,0,0),IVec(-40,0,0),IVec(-40,20,0),IVec(-60,20,0)]
curve1 = ICurve(cpts1).clr(0)
IG.offset(curve1, 5.0).clr(1.0,0,0)

cpts2 = [ IVec(-20,0,0), IVec(-10,20,0), IVec(-10,0,0) ]
curve2 = ICurve(cpts2, True).clr(0)
IG.offset(curve2, 5).clr(1.0,0,0)

cpts3 = [ IVec(10,0,0),IVec(20,20,0),IVec(20,0,0) ]
curve3 = ICurve(cpts3, 2).clr(0)
IG.offset(curve3, 5).clr(1.,0,0)

cpts4 = [ IVec(40,0,0),IVec(50,20,0),IVec(50,0,0) ]
curve4 = ICurve(cpts4, 2, True).clr(0)
IG.offset(curve4, 5).clr(1.,0,0)

cpts5 = [ IVec(-20,60,0),IVec(10,60,0),IVec(10,60,20) ]
curve5 = ICurve(cpts5, True).clr(0)
IG.offset(curve5, 5).clr(1.,0,0)

cpts6 = [ IVec(80,0,0),IVec(90,0,20),IVec(100,0,20),IVec(100,20,20),IVec(80,20,0) ]
curve6 = ICurve(cpts6, True).clr(0)
IG.offset(curve6, 5).clr(1.,0,0)
```

The offset distance of degree 1 curve can have constant distance between the original curve (polyline) and the offset one, like the curve1 and curve2 in the code above.
However, if the curve's degree is more than 2 and curving, the distance between two curve is not constant, like curve3 and curve4 on the code, because it's simply taking offset vertices of a degree 1 curve as its control points.
If an input curve is not planar curve, offset curve is deformed accordingly and also non-planar, like the curve6 on the code.

### Lofting

You can create a lofted surface by providing array of curves with IG.loft(ICurve[]) for lofting multiple curves, or IG.loft(ICurve,ICurve,) for lofting two curves. Note that all the curves to be lofted need to have the exact same number of control points.

```add_library('igeo')

size(480, 360, IG.GL)

cpts1 = [ IVec(-50,0,0),IVec(-30,0,0),IVec(-30,-20,0),IVec(-50,-20,0) ]
curve1 = ICurve(cpts1).clr(1.,0,1.)

cpts2 = [ IVec(-40,20,30),IVec(-30,20,30),IVec(-30,0,30),IVec(-40,0,30) ]
curve2 = ICurve(cpts2).clr(1.,0,1.)

# loft of two curves
IG.loft(curve1, curve2).clr(0.2)

cpts3 = [ IVec(-20,0,0),IVec(10,0,0),IVec(10,-20,0),IVec(-20,-20,0) ]
curve3 = ICurve(cpts3,3,True).clr(1.,1.,0)

cpts4 = [ IVec(-10,0,20),IVec(0,0,20),IVec(0,-20,20),IVec(-10,-20,20) ]
curve4 = ICurve(cpts4,3,True).clr(1.,1.,0)

cpts5 = [ IVec(-20,20,40),IVec(10,20,40),IVec(10,-20,40),IVec(-20,-20,40) ]
curve5 = ICurve(cpts5,3,True).clr(1.,1.,0)

# loft of multiple curves in an array (degre=1, straight)
IG.loft([ curve3, curve4, curve5 ]).clr(0.2)

curve6 = curve3.dup().mv(40,0,0).clr(0,1.,1)
curve7 = curve4.dup().mv(40,0,0).clr(0,1.,1)
curve8 = curve5.dup().mv(40,0,0).clr(0,1.,1)

# degree 2 curved lofting
IG.loft([ curve6, curve7, curve8 ], 2 ).clr(0.2)
```

### Extruding Point Array

You can extrude an array of points to create a surface with the method IG.extrude() providing a point array as a profile to be extruded.

```add_library('igeo')

size(480, 360, IG.GL)

pts1 = [ IVec(-50,-20,0),IVec(-30,-20,0),IVec(-30,0,0),IVec(-50,0,0) ]

# extrude points to their normal direction
IG.extrude(pts1, 30).clr(0.2)

pts2= [ IVec(-20,0,0),IVec(10,0,0),IVec(10,-20,0),IVec(-20,-20,0) ]

# extrude degree 2 closed profile
IG.extrude(pts2, 2, True, -20).clr(0.2)

pts3= [ IVec(20,0,0),IVec(50,0,0),IVec(50,-20,0),IVec(20,-20,0) ]

# extrude in the direction specified by a vector
IG.extrude(pts3, 1, True, IVec(10,20,30)).clr(0.2)
```

### Extruding Curves

You can extrude a curve in its normal direction or a specified direction to create a surface with IG.extrude() method providing the curve as a profile to be extruded.

```add_library('igeo')

size(480, 360, IG.GL)

pts1 = [ IVec(-50,-20,0),IVec(-30,-20,0),IVec(-30,0,0),IVec(-50,0,0) ]

curve1 = ICurve(pts1).clr(1.,0,1.)

IG.extrude(curve1, 30).clr(0.2)

pts2 = [ IVec(-20,0,0),IVec(10,0,0),IVec(10,-20,0),IVec(-20,-20,0) ]
curve2 = ICurve(pts2, 2, True).clr(1.,1.,0)

IG.extrude(curve2, -20).clr(0.2)

pts3 = [ IVec(20,0,0),IVec(50,0,0),IVec(50,-20,0),IVec(20,-20,0) ]

curve3 = ICurve(pts3, 1, True).clr(0,1.,1.)

IG.extrude(curve3, IVec(10,20,30)).clr(0.2)
```

### Sweeping Point Arrays

You can sweep two set of point array to create a surface with the method IG.sweep(). One set is a profile and another set defines railing line (or curve) to sweep. Note that the size of the profile on the rail whose degree is 2 or more is not accurately same and variable in the exactly same way the offset method creates variable offset distance in degree 2 or more.

```add_library('igeo')

size(480, 360, IG.GL)

profile1 = [ IVec(5,0,0),IVec(5,5,0),IVec(0,5,0) ]
rail1 = [ IVec(-40,0,-20),IVec(-30,0,10),IVec(-50,0,20) ]
# sweeping open profile and open rail
IG.sweep(profile1, rail1).clr(0.2)

profile2 = [ IVec(0,0,0),IVec(10,0,0),IVec(10,10,0),IVec(0,10,0) ]
rail2 = [ IVec(0,20,-20),IVec(0,0,20),IVec(0,-20,-20) ]
# sweeping degree 2 closed profile and degree 2 open rail
IG.sweep(profile2, 3, True, rail2, 2, False).clr(0.5,0,0)

profile3 = [ IVec(-5,0,0),IVec(0,5,0),IVec(0,-5,0) ]
rail3 = [ IVec(40,20,-20),IVec(40,0,20),IVec(40,-20,-20) ]
# sweeping degree 2 closed profile and degree 2 open rail
IG.sweep(profile3, 1, True, rail3, 1, True).clr(0,0,0.5)
```

### Sweeping Curves

You can sweep a profile curve and a railing curve to create a surface by IG.sweep(ICurve,ICurve) method.

```add_library('igeo')

size(480, 360, IG.GL)

profile1 = [ IVec(0,0,0),IVec(10,0,0),IVec(10,10,0),IVec(0,10,0) ]
profileCrv1 = ICurve(profile1,3).clr(0,1.,1.)
rail1 = [ IVec(-50,0,-30),IVec(-30,0,0),IVec(-30,0,30) ]
railCrv1 = ICurve(rail1).clr(1.,1.,0)

# sweeping open profile and open rail
IG.sweep(profileCrv1, railCrv1).clr(0.2)

# ellipse profile
profileCrv2 = ICircle(0,0,0,10,5).clr(0,1.,1.)
rail2 = [ IVec(0,20,-20),IVec(0,0,20),IVec(0,-20,-20) ]
railCrv2 = ICurve(rail2, 2).clr(1.,1.,0)

# sweeping degree 2 closed profile and degree 2 open rail
IG.sweep(profileCrv2, railCrv2).clr(0.5,0,0)

profile3 = [ IVec(-5,0,0),IVec(0,5,0),IVec(0,-5,0) ]
profileCrv3 = ICurve(profile3,True).clr(0,1.,1.)
# circle profile
railCrv3 = ICircle(IVec(40,0,0),IVec(1,0,0),30).clr(1.,1.,0)

# sweeping degree 2 closed profile and degree 2 open rail
IG.sweep(profileCrv3, railCrv3).clr(0,0,0.5)
```

### Circular Pipe Along Curves

You can create circular pipe geometry along a curve with IG.pipe(ICurve,double) method. The first argument is the curve along which the pipe is swept. The second argument is the radius of the pipe. This method has same accuracy issue with sweeping when the degree of the rail curve is 2 or more.

```add_library('igeo')

size(480, 360, IG.GL)

curve1 = ICurve(IVec(-40,0,-20),IVec(-30,20,30))
IG.pipe(curve1, 2).clr(.2)

curve2 = ICurve([ IVec(-10,0,-30),IVec(-10,-10,-10),IVec(-10,10,10),IVec(-10,0,30) ])
IG.pipe(curve2,6).clr(0.5,0,0)

curve3 = ICircle(IVec(20,0,0),IVec(1,0,0),20)
IG.pipe(curve3,4).clr(1.0,0,0.5)

curve4 = ICurve([ IVec(50, -20, 20),IVec(40, 30, 0),IVec(70, 0, 40), \
IVec(50, -10, -10),IVec(60, -40, -10) ], \
2, True)
IG.pipe(curve4, 4).clr(0,0,0.8)
```

### Rectangular Pipe Along Curves

In the same way with creating circular pipes, you can also create rectangular or square pipes with IG.rectPipe(ICurve,double,double) or IG.squarePipe(ICurve,double).

```add_library('igeo')

size(480, 360, IG.GL)

curve1 = ICurve(IVec(-40,0,-20),IVec(-30,20,30))
IG.rectPipe(curve1, 10,2).clr(.2)

curve2 = ICurve([ IVec(-10,0,-30),IVec(-10,-10,-10),IVec(-10,10,10),IVec(-10,0,30) ])
IG.rectPipe(curve2,5,10).clr(0.5,0,0)

curve3 = ICircle(IVec(20,0,0),IVec(1,0,0),20)
IG.squarePipe(curve3,8).clr(1.0,0,0.5)

curve4 = ICurve([ IVec(50, -20, 20),IVec(40, 30, 0),IVec(70, 0, 40), \
IVec(50, -10, -10),IVec(60, -40, -10) ], \
2, True)
IG.squarePipe(curve4,8).clr(0,0,0.8)
```

(back to the list of tutorials)