# OSG Plane specific test procedures.
#
# Cnstr-Plane       Plane constructors.        Plane as result.
# Plane-Scalar      Plane as input.            Scalar as result.
# Plane-Plane       Plane as input.            Plane as result.
# PlanePlane-Scalar Plane and Plane as input.  Scalar as result.
# Plane-Vec         Plane as input.            Vector as result.
# PlaneMisc         Miscellaneous Plane tests: set, get, ...

package require tcl3d

source testUtil.tcl

# Test procedure for the different types of Plane constructors.
proc Cnstr-Plane { planeType } {
    P "\nCnstr-Plane: $planeType Functionality: set Plane \[$planeType\]"

    set plane1 [osg::Plane]
    PN "Cnstr():" ; PP $plane1

    set plane2 [osg::Plane a 1 2 3 4]
    PN "Cnstr(a b c d):" ; PP $plane2

    set plane3 [osg::Plane a $plane2]
    PN "Cnstr(Plane):" ; PP $plane3

    set plane4 [osg::Plane a [CreateVec1 osg::Vec4f 4]]
    PN "Cnstr(Vec4f):" ; PP $plane4

    set plane5 [osg::Plane a [CreateVec1 osg::Vec4d 4]]
    PN "Cnstr(Vec4d):" ; PP $plane5

    set plane6 [osg::Plane a [CreateVec1 osg::Vec3d 3] 4]
    PN "Cnstr(Vec3d,sc):" ; PP $plane6

    set plane7 [osg::Plane a [CreateUnitVec osg::Vec3d 3 0] \
                             [CreateUnitVec osg::Vec3d 3 1] \
                             [CreateUnitVec osg::Vec3d 3 2]]
    PN "Cnstr(Vec3d,Vec3d,Vec3d):" ; PP $plane7

    set plane8 [osg::Plane a [CreateUnitVec osg::Vec3d 3 0] \
                             [CreateUnitVec osg::Vec3d 3 1]]
    PN "Cnstr(Vec3d,Vec3d):" ; PP $plane8
}

# Test procedure for methods returning scalar information about a Plane
# without the need to supply parameters.
proc Plane-Scalar { planeType plane } {
    P "\nPlane-Scalar: $planeType Functionality: set Scalar \[\$In method\]"
    PN "In $planeType" ; PP $plane
    set size [$plane size]
    for { set i 0 } { $i < $size } { incr i } {
        set retVal [catch {eval $plane get $i} result]
        PN "Method get $i"
        if { $retVal == 0 } {
            P $result
        } else {
            P "Not supported"
        }
    }
    foreach m { size valid isNaN } {
        set retVal [catch {eval $plane $m} result]
        PN "Method $m"
        if { $retVal == 0 } {
            P $result
        } else {
            P "Not supported"
        }
    }

    foreach m { ptr } {
        set retVal [catch {eval $plane $m} result]
        PN "Method $m"
        if { $retVal == 0 } {
            P [GetPointerType $result]
        } else {
            P "Not supported"
        }
    }
}

# Test procedure for methods returning a Plane generated
# by supplying a Plane.
proc Plane-Plane { planeType plane } {
    P "\nPlane-Plane: $planeType Functionality: set Plane \[\$In method\]"
    PN "In $planeType" ; PP $plane
    foreach m { copy } {
        set retVal [catch {eval $plane $m} result]
        PN "Method $m"
        if { $retVal == 0 } {
            PP "$result"
        } else {
            P "Not supported"
        }
    }
    return $result
}

# Test procedure for methods returning a scalar generated
# by supplying two Planes.
proc PlanePlane-Scalar { planeType plane1 plane2 } {
    P "\nPlanePlane-Scalar: $planeType Functionality: set Scalar \[\$In1 method \$In2\]"
    PN "In1 $planeType" ; PP $plane1
    PN "In2 $planeType" ; PP $plane2
    foreach m { eq ne less } {
        set retVal [catch {eval $plane1 $m $plane2} result]
        PN "Method $m"
        if { $retVal == 0 } {
            P $result
        } else {
            P "Not supported"
        }
    }
    return $result
}

# Test procedure for methods returning a scalar generated
# by supplying a Plane and a Vector.
proc PlaneVec-Scalar { planeType plane vecType vec } {
    P "\nPlaneVec-Scalar: $planeType Functionality: set Scalar \[\$In1 method \$In2\]"
    PN "In1 $planeType" ; PP $plane
    PN "In2 $vecType"   ; PV $vec
    foreach m { distance dotProductNormal } {
        set retVal [catch {eval $plane $m $vec} result]
        PN "Method $m"
        if { $retVal == 0 } {
            P $result
        } else {
            P "Not supported"
        }
    }
    return $result
}

# Test procedure for methods returning a vector casted from
# a supplied Plane.
proc Plane-Vec { planeType plane } {
    P "\nPlane-Vec: $planeType Functionality: set Vector \[\$In cast\]"
    PN "In $planeType" ; PP $plane
    foreach m { asVec4 getNormal } {
        set retVal [catch {eval $plane $m} result]
        PN "Method $m"
        if { $retVal == 0 } {
            PN "[GetPointerType [$result ptr]]"
            PV "$result"
        } else {
            P "Not supported"
        }
    }
    return $result
}

# Test procedure for methods not fitting into one of the above categories.
proc PlaneMisc { planeType } {
    P "\nPlaneMisc: $planeType Functionality: Miscellaneous"

    set plane1 [osg::Plane]
    $plane1 set 1 2 3 4
    PN "Method set xyzw" ; PP $plane1

    $plane1 set [CreateUnitVec osg::Vec4f 4 0]
    PN "Method set Vec4f" ; PP $plane1

    $plane1 set [CreateUnitVec osg::Vec4d 4 1]
    PN "Method set Vec4d" ; PP $plane1

    $plane1 set [CreateVec1 osg::Vec3d 3] 1.5
    PN "Method set Vec3d,sc" ; PP $plane1

    $plane1 set [CreateUnitVec osg::Vec3d 3 0] \
                [CreateUnitVec osg::Vec3d 3 1] \
                [CreateUnitVec osg::Vec3d 3 2]
    PN "Method set Vec3d,Vec3d,Vec3d" ; PP $plane1

    $plane1 set [CreateVec1 osg::Vec3d 3] [CreateUnitVec osg::Vec3d 3 1]
    PN "Method set Vec3d,Vec3d" ; PP $plane1

    $plane1 flip
    PN "Method flip" ; PP $plane1

    $plane1 makeUnitLength
    PN "Method makeUnitLength" ; PP $plane1

    $plane1 calculateUpperLowerBBCorners
    PN "Method calculateUpperLowerBBCorners" ; PP $plane1

    # ToDo Missing: intersect with std::vector<Vec3>
    set stdVec [osg::StdVec3f]
    $stdVec push [osg::Vec3f a1 1 2 3]
    $stdVec push [osg::Vec3f a2 4 5 6] 
    set result [$plane1 intersect $stdVec]
    PN "Method intersect StdVec3f" ; P $result

    lappend stdVecList [osg::Vec3f a1 1 2 3]
    lappend stdVecList [osg::Vec3f a2 4 5 6] 
    set result [$plane1 intersect $stdVecList]
    PN "Method intersect StdVec3fList" ; P $result

    set stdVecd [osg::StdVec3d]
    $stdVecd push [osg::Vec3d a1 1 2 3]
    $stdVecd push [osg::Vec3d a2 4 5 6] 
    set result [$plane1 intersectd $stdVecd]
    PN "Method intersectd StdVec3d" ; P $result

    lappend stdVecdList [osg::Vec3d a1 1 2 3]
    lappend stdVecdList [osg::Vec3d a2 4 5 6] 
    set result [$plane1 intersectd $stdVecdList]
    PN "Method intersectd StdVec3dList" ; P $result

    set result [$plane1 intersect [CreateBSphere1]]
    PN "Method intersect BSphere" ; P $result

    set result [$plane1 intersect [CreateBBox1]]
    PN "Method intersect BBox" ; P $result

    set plane2 [$plane1 copy]
    osg::Matrix mat
    mat makeRotate 30 [osg::Vec3f vf1 1 0 0] \
                   30 [osg::Vec3f vf2 0 1 0] \
                   30 [osg::Vec3f vf3 0 0 1]

    $plane1 transform mat
    PN "Method transform Matrix" ; PP $plane1

    osg::Matrix invMat
    invMat invert mat
    $plane2 transformProvidingInverse invMat
    PN "Method transformProvidingInverse Matrix" ; PP $plane2
}

P ">>> Test cases for osg::Plane class <<<\n"

set planeType osg::Plane
set idPlane [osg::Plane]
set plane1  [CreatePlane1 $planeType]
Cnstr-Plane      $planeType
Plane-Scalar     $planeType $plane1
Plane-Plane       $planeType $plane1
PlanePlane-Scalar $planeType $idPlane $plane1
PlaneVec-Scalar   $planeType $plane1 osg::Vec3f [CreateVec1 osg::Vec3f 3] 
PlaneVec-Scalar   $planeType $plane1 osg::Vec3d [CreateVec1 osg::Vec3d 3] 
Plane-Vec        $planeType $plane1
PlaneMisc        $planeType
$idPlane -delete
$plane1  -delete

exit
