def dirProject():
    if CTK.t == []: return
    if (CTK.__MAINTREE__ <= 0):
        CTK.TXT.insert('START', 'Fail on a temporary tree.\n')
        CTK.TXT.insert('START', 'Error: ', 'Error')
        return
    # surfaces
    name = VARS[0].get()
    names = name.split(';')
    surfaces = []
    for v in names:
        v = v.lstrip()
        v = v.rstrip()
        sname = v.split('/', 1)
        bases = Internal.getNodesFromName1(CTK.t, sname[0])
        if (bases != []):
            nodes = Internal.getNodesFromType1(bases[0], 'Zone_t')
            for z in nodes:
                if (z[0] == sname[1]): surfaces.append(z)
    if (surfaces == []):
        CTK.TXT.insert('START', 'Projection surface is empty.\n')
        CTK.TXT.insert('START', 'Error: ', 'Error')
        return
    nzs = CPlot.getSelectedZones()
    if (nzs == []):
        CTK.TXT.insert('START', 'Selection is empty.\n')
        CTK.TXT.insert('START', 'Error: ', 'Error')
        return

    eye = CPlot.getState('posEye')
    cam = CPlot.getState('posCam')
    dir = (eye[0] - cam[0], eye[1] - cam[1], eye[2] - cam[2])
    CTK.saveTree()
    fail = False
    errors = []
    for nz in nzs:
        nob = CTK.Nb[nz] + 1
        noz = CTK.Nz[nz]
        z = CTK.t[2][nob][2][noz]
        try:
            a = T.projectDir(z, surfaces, dir)
            CTK.replace(CTK.t, nob, noz, a)
        except Exception as e:
            fail = True
            errors += [0, str(e)]

    if (fail == False):
        CTK.TXT.insert('START', 'Zones projected.\n')
    else:
        Panels.displayErrors(errors, header='Error: projectDir')
        CTK.TXT.insert('START', 'Projection fails for at least one zone.\n')
        CTK.TXT.insert('START', 'Warning: ', 'Warning')
    CTK.TKTREE.updateApp()
    CPlot.render()
# - projectDir (pyTree) -
import Geom.PyTree as D
import Converter.PyTree as C
import Generator.PyTree as G
import Transform.PyTree as T

a = D.sphere((0, 0, 0), 1., 20)
b = G.cart((1.1, -0.1, -0.1), (0.1, 0.1, 0.1), (1, 5, 5))
c = T.projectDir(b, a, (1., 0, 0))
c[0] = 'projection'
C.convertPyTree2File([a, b, c], 'out.cgns')
# - projectDir (pyTree) -
import Geom.PyTree as D
import Converter.PyTree as C
import Generator.PyTree as G
import Transform.PyTree as T
import KCore.test as test

# Structure
a = D.sphere((0, 0, 0), 1., 20)
a = C.addBC2Zone(a, 'wall1', 'BCWall', 'imin')
a = C.addBC2Zone(a, 'match1', 'BCMatch', 'jmin', a, 'jmax', [1, 2])
C._addVars(a, 'F')
C._addVars(a, 'centers:G')
b = G.cart((1.1, -0.1, -0.1), (0.1, 0.1, 0.1), (1, 5, 5))
c = T.projectDir(b, a, (1., 0, 0))
c[0] = 'projection'
t = C.newPyTree(['Base', 2, c])
test.testT(t, 1)

# Non structure sur structure
a = D.sphere((0, 0, 0), 1., 20)
a = C.addBC2Zone(a, 'wall1', 'BCWall', 'imin')
a = C.addBC2Zone(a, 'match1', 'BCMatch', 'jmin', a, 'jmax', [1, 2])
C._addVars(a, 'F')
C._addVars(a, 'centers:G')
b = G.cartTetra((1.1, -0.1, -0.1), (0.1, 0.1, 0.1), (1, 5, 5))
c = T.projectDir(b, a, (1., 0, 0))
c[0] = 'projection'
t = C.newPyTree(['Base', 2])
t[2][1][2].append(c)
test.testT(t, 2)