home processing download documents tutorial python tutorial gallery source about
 Python Tutorials (back to the list of tutorials)

Lines on Surface

     Grid Points on Surface

Here we take a NURBS surface from an input file using IG.open() method shown in the previous section. In the following example, iGeo imports geometries from 3dm file or OBJ file and puts the imported surfaces by IG.surfaces() method as shown in this section. You can put any NURBS surface via 3dm file or OBJ. Here is a sample input files used in the example codes below. The code below use a special type of for loop for( ISurface surf : surfs ) and this for loop executes the body for each member of the array (in this case surfs is an array of ISurface) and the each member is put in the new variable (in this case ISurface surf). With this for loop, the operation in the code is applied to all surfaces in the file.

add_library('igeo')

size( 480, 360, IG.GL )

#IG.open("surface1.3dm")  #input geometry from 3dm file
IG.open("surface1.obj") #input geometry from OBJ file

surfs = IG.surfaces()

for surf in surfs : 
    unum = 8
    vnum = 8
    uinc = 1.0/unum
    vinc = 1.0/vnum
    for i in range(unum+1) :
        for j in range(vnum+1) :
            pt = surf.pt( i*uinc, j*vinc )
            IPoint(pt).clr( i*uinc, j*vinc, 0)

The for loop and the way to use surf.pt( i*uinc, j*vinc ) in the code above are a basic way to extract points on the surface to create new geometries on the surface.

When you don't need the input surface anymore, you can delete it by del() method.

add_library('igeo')

size( 480, 360, IG.GL )

#IG.open("surface1.3dm")  #input geometry from 3dm file
IG.open("surface1.obj") #/input geometry from OBJ file

surfs = IG.surfaces()

for surf in surfs : 
    unum = 8
    vnum = 8
    uinc = 1.0/unum
    vinc = 1.0/vnum
    for i in range(unum+1) : 
        for j in range(vnum+1) : 
            pt = surf.pt( i*uinc, j*vinc )
            IPoint(pt).clr( i*uinc, j*vinc, 0)
    surf.del()


     Grid Lines

Here is an example to create lines on a surface in u direction. Please note that the condition of the for loop of index number i uses i < unum not i <= unum.

add_library('igeo')

size( 480, 360, IG.GL )

#IG.open("surface1.3dm")  #input geometry from 3dm file
IG.open("surface1.obj") # input geometry from OBJ file

surfs = IG.surfaces()

for surf in surfs :
    unum = 8
    vnum = 8
    uinc = 1.0/unum
    vinc = 1.0/vnum
    for i in range(unum) :
        for j in range(vnum) :
            pt1 = surf.pt(i*uinc, j*vinc)
            pt2 = surf.pt((i+1)*uinc, j*vinc)
            ICurve(pt1, pt2).clr(0)
    surf.del()

In the similar way, you can draw lines on a surface in v direction, by switching the logic of i and j.

add_library('igeo')

size( 480, 360, IG.GL )

#IG.open("surface1.3dm")  #input geometry from 3dm file
IG.open("surface1.obj")  #input geometry from OBJ file

surfs = IG.surfaces()

for surf in surfs : 
    unum = 8
    vnum = 8
    uinc = 1.0/unum
    vinc = 1.0/vnum
    for i in range(unum+1) : 
        for j in range(vnum) : 
            pt1 = surf.pt(i*uinc, j*vinc)
            pt2 = surf.pt(i*uinc, (j+1)*vinc)
            ICurve(pt1, pt2).clr(1.0)
    surf.del()

To combine both, dealing with the ending number difference in u and v direction, you'd use if condition to skip the logic around the ending number.

add_library('igeo')

size( 480, 360, IG.GL )

#IG.open("surface1.3dm")  # input geometry from 3dm file
IG.open("surface1.obj") # input geometry from OBJ file

surfs = IG.surfaces()

for surf in surfs :
    unum = 8
    vnum = 8
    uinc = 1.0/unum
    vinc = 1.0/vnum
    for i in range(unum+1) : 
        for j in range(vnum+1) : 
            pt1 = surf.pt(i*uinc, j*vinc)
            if i < unum : 
                pt2u = surf.pt((i+1)*uinc, j*vinc)
                ICurve(pt1, pt2u).clr(0)
            if j < vnum : 
                pt2v = surf.pt(i*uinc, (j+1)*vinc)
                ICurve(pt1, pt2v).clr(1.0)
    surf.del()

When you run the for loops with the counter i and j, the behavior of the internal parameter of u and v, calculated by the counter i, j and the interval uinc, vinc on the surface can be diagrammed like the below.

When the iteration of for loop is going through, depending on the state (depending on what number i and j are assigned), the location of the point specified the parameter is relatively changed.

To build geometry relative to the current state of i and j in the for loop, you specify a relative location using the counter i, j and the interval uinc and vinc.


     Diagonal Lines

When you draw diagonal line inside the for loop like above, you'd connect point at pt( i*uinc, j*vinc ) and another at pt( (i+1)*uinc, (j+1)*vinc ).

add_library('igeo')

size( 480, 360, IG.GL )

#IG.open("surface1.3dm")  #input geometry from 3dm file
IG.open("surface1.obj") #input geometry from OBJ file

surfs = IG.surfaces()

for surf in surfs : 
    unum = 8
    vnum = 8
    uinc = 1.0/unum
    vinc = 1.0/vnum
    for i in range(unum) : 
        for j in range(vnum) : 
            pt1 = surf.pt(i*uinc, j*vinc)
            pt2 = surf.pt((i+1)*uinc, (j+1)*vinc)
            ICurve(pt1, pt2).clr(0,1.,1.)
    surf.del()

To flip the direction of diagonals, use pt( i*uinc, (j+1)*vinc ) and pt( (i+1)*uinc, j*vinc ).

add_library('igeo')

size( 480, 360, IG.GL )

#IG.open("surface1.3dm")  #input geometry from 3dm file
IG.open("surface1.obj") #input geometry from OBJ file

surfs = IG.surfaces()

for surf in surfs :
    unum = 8
    vnum = 8
    uinc = 1.0/unum
    vinc = 1.0/vnum
    for i in range(unum) : 
        for j in range(vnum) :
            pt1 = surf.pt(i*uinc, (j+1)*vinc)
            pt2 = surf.pt((i+1)*uinc, j*vinc)
            ICurve(pt1, pt2).clr(0,0,1.)
    surf.del()

The below is an example to combine diagonal lines and orthogonal u lines and v lines.

add_library('igeo')

size( 480, 360, IG.GL )

#IG.open("surface1.3dm")  #input geometry from 3dm file
IG.open("surface1.obj") #input geometry from OBJ file

surfs = IG.surfaces()

for surf in surfs : 
    unum = 8
    vnum = 8
    uinc = 1.0/unum
    vinc = 1.0/vnum
    for i in range(unum+1) : 
        for j in range(vnum) : 
            pt1 = surf.pt(i*uinc, j*vinc)
            if i < unum : 
                pt2u = surf.pt((i+1)*uinc, j*vinc)
                ICurve(pt1, pt2u).clr(0)
            if j < vnum : 
                pt2v = surf.pt(i*uinc, (j+1)*vinc)
                ICurve(pt1, pt2v).clr(1.0)
            if i < unum and j < vnum :
                pt2uv = surf.pt((i+1)*uinc, (j+1)*vinc)
                ICurve(pt1, pt2uv).clr(0,1.,1.)
    surf.del()


     Diagrid Lines

Diagrid lines can be drawn using if condition of if( (i+j)%2 == 0 ) .

add_library('igeo')

size( 480, 360, IG.GL )

#IG.open("surface1.3dm")  #input geometry from 3dm file
IG.open("surface1.obj") #input geometry from OBJ file

surfs = IG.surfaces()

for surf in surfs :
    unum = 8
    vnum = 8
    uinc = 1.0/unum
    vinc = 1.0/vnum
    for i in range(unum) : 
        for j in range(vnum+1) : 
            if (i+j)%2 == 0 :
                pt1 = surf.pt(i*uinc, j*vinc)
                if j > 0 :
                    pt2 = surf.pt((i+1)*uinc, (j-1)*vinc)
                    ICurve(pt1, pt2).clr(0)
                if j < vnum :
                    pt3 = surf.pt((i+1)*uinc, (j+1)*vinc)
                    ICurve(pt1, pt3).clr(0,0,1.)
    surf.del()

The if condition of if( (i+j)%2 == 0 ) picks every other point in the diagonal checker pattern way as shown in the diagram below.

Then on each point, pt1 at i*uinc, j*vinc, pt2 at (i+1)*uinc, (j-1)*vinc and pt3 at (i+1)*uinc, (j+1)*vinc forms two lines in "<" shape.

When this "<" shape is repeated at each diagrid point, it forms diagrid lines.


If you use the if condition of if( (i+j)%2 == 1 ) , instead of if( (i+j)%2 == 0 ) , The corner condition of diagrid lines can be changed.

add_library('igeo')

size( 480, 360, IG.GL )

#IG.open("surface1.3dm")  #input geometry from 3dm file
IG.open("surface1.obj") #input geometry from OBJ file

surfs = IG.surfaces()

for surf in surfs : 
    unum = 8
    vnum = 8
    uinc = 1.0/unum
    vinc = 1.0/vnum
    for i in range(unum) : 
        for j in range(vnum+1) : 
            if (i+j)%2 == 1 :
                pt1 = surf.pt(i*uinc, j*vinc)
                if j > 0 :
                    pt2 = surf.pt((i+1)*uinc, (j-1)*vinc)
                    ICurve(pt1, pt2).clr(0)
                if j < vnum :
                    pt3 = surf.pt((i+1)*uinc, (j+1)*vinc)
                    ICurve(pt1, pt3).clr(0,0,1.)
    surf.del()


     Variable Diagrid Lines

If you change vnum and vinc inside the for loop in u direction with the counter i, you get variable diagrid like the below. Because you are accessing two different row of i and i+1 at the same time, you need to have vinc for the row of i and vinc2 for the row of i+1 separately.

add_library('igeo')

size( 480, 360, IG.GL )

#IG.open("surface1.3dm")  #input geometry from 3dm file
IG.open("surface1.obj") #input geometry from OBJ file

surfs = IG.surfaces()

for surf in surfs :
    unum = 8
    vnum = 4
    uinc = 1.0/unum
    vinc = 1.0/vnum
    for i in range(unum) : 
        vnum+=1
        vinc = 1.0/vnum
        for j in range(vnum+1) : 
            vinc2 = 1.0/(vnum+1)
            pt1 = surf.pt(i*uinc, j*vinc)
            pt2 = surf.pt((i+1)*uinc, j*vinc2)
            pt3 = surf.pt((i+1)*uinc, (j+1)*vinc2)
            ICurve(pt1, pt2).clr(1.,0,0)
            ICurve(pt1, pt3).clr(.5,0,1)
    surf.del()


     Hexagonal Grid Lines

By modifying the diagrid line algorithm, you can get hexagonal grid lines. The parameter r defines the angle of diagonal lines. If r = 0.0, it's same with diagrid, if 0 < r < 0.5, it's hexagonal, if r = 0.5, it's orthogonal, and if r > 0.5, it generates ribbon shape grid lines.

add_library('igeo')

size( 480, 360, IG.GL )

#IG.open("surface1.3dm")  #input geometry from 3dm file
IG.open("surface1.obj") # input geometry from OBJ file

surfs = IG.surfaces()

for surf in surfs :
    unum = 20
    vnum = 8
    uinc = 1.0/unum
    vinc = 1.0/vnum
    r = 0.3
    for i in range(unum+1) : 
        for j in range(vnum+1) : 
            if (i+j)%2 == 0 : 
                pt1 = surf.pt(i*uinc, (j-r)*vinc)
                pt2 = surf.pt(i*uinc, (j+r)*vinc)
                ICurve(pt1, pt2).clr(1.,0,1.)
                if i < unum : 
                    if j > 0 :
                        pt3 = surf.pt((i+1)*uinc, (j-1+r)*vinc)
                        ICurve(pt1, pt3).clr(0)
                    if j < vnum :
                        pt4 = surf.pt((i+1)*uinc, (j+1-r)*vinc)
                        ICurve(pt2, pt4).clr(0,0,1.)
    surf.del()


     Hexagonal Grid Lines2

You can also create different type of hexagonal grid lines with two orthogonal lines and one diagonal line.

add_library('igeo')

size( 480, 360, IG.GL )

#IG.open("surface1.3dm")  #input geometry from 3dm file
IG.open("surface1.obj") #input geometry from OBJ file

surfs = IG.surfaces()

for surf in surfs :
    unum = 12
    vnum = 12
    uinc = 1.0/unum
    vinc = 1.0/vnum
    for i in range(unum+1) : 
        for j in range(vnum+1) : 
            pt1 = surf.pt(i*uinc, j*vinc)
            if (i+j)%3 == 0 :
                if i < unum :
                    pt2 = surf.pt((i+1)*uinc, j*vinc)
                    ICurve(pt1, pt2).clr(0) # orthogonal line
                if j < vnum :
                    pt3 = surf.pt(i*uinc, (j+1)*vinc)
                    ICurve(pt1, pt3).clr(0.5) # orthogonal line
            if (i+j)%3 == 1 :
                if i < unum and j < vnum :
                    pt4 = surf.pt((i+1)*uinc, (j+1)*vinc)
                    ICurve(pt1, pt4).clr(1.,0,0) # diagonal line
    surf.del()


     Putting Cylinder around Line

You can create a cylinder around a line with ICylinder class by putting two end points and a radius. The code below is replaceing ICurve with ICylinder in the diagrid code.

add_library('igeo')

size( 480, 360, IG.GL )

#IG.open("surface1.3dm")  #input geometry from 3dm file
IG.open("surface1.obj") #input geometry from OBJ file

surfs = IG.surfaces()

for surf in surfs: 
    unum = 8
    vnum = 8
    uinc = 1.0/unum
    vinc = 1.0/vnum
    for i in range(unum) : 
        for j in range(vnum+1) :
            if (i+j)%2 == 0 : 
                pt1 = surf.pt(i*uinc, j*vinc)
                if j > 0 : 
                    pt2 = surf.pt((i+1)*uinc, (j-1)*vinc)
                    ICylinder(pt1, pt2, 0.5)
                if j < vnum :
                    pt3 = surf.pt((i+1)*uinc, (j+1)*vinc)
                    ICylinder(pt1, pt3, 0.5)
    surf.del()


     Putting Fin Surface on Line

You can put fin surface along lines by creating rectangles with ISurface with offset points on the surface.

add_library('igeo')

size( 480, 360, IG.GL )

#IG.open("surface1.3dm")  #input geometry from 3dm file
IG.open("surface1.obj") #input geometry from OBJ file

surfs = IG.surfaces()

for surf in surfs : 
    unum = 12
    vnum = 12
    uinc = 1.0/unum
    vinc = 1.0/vnum
    depth = 3.0
    for i in range(unum+1) : 
        for j in range(vnum+1) : 
            pt1 = surf.pt(i*uinc, j*vinc)
            pt1d = surf.pt(i*uinc, j*vinc, depth)
            if (i+j)%3 == 0 :
                if i < unum :
                    pt2 = surf.pt((i+1)*uinc, j*vinc)
                    pt2d = surf.pt((i+1)*uinc, j*vinc, depth)
                    ISurface(pt1, pt2, pt2d, pt1d).clr(0)
                if j < vnum :
                    pt3 = surf.pt(i*uinc, (j+1)*vinc)
                    pt3d = surf.pt(i*uinc, (j+1)*vinc, depth)
                    ISurface(pt1, pt3, pt3d, pt1d).clr(0.5)
            if (i+j)%3 == 1 : 
                if i < unum and j < vnum : 
                    pt4 = surf.pt((i+1)*uinc, (j+1)*vinc)
                    pt4d = surf.pt((i+1)*uinc, (j+1)*vinc, depth)
                    ISurface(pt1, pt4, pt4d, pt1d).clr(1.,0,0)
    surf.del()


(back to the list of tutorials)

HOME
FOR PROCESSING
DOWNLOAD
DOCUMENTS
TUTORIALS (Java / Python)
GALLERY
SOURCE CODE(GitHub)
ABOUT