/***************************************************************
* Function: updateGridUnits()
***************************************************************/
void CAVEGroupEditGeodeWireframe::updateGridUnits(const float &gridUnitLegnth, 
			const float &gridUnitAngle, const float &gridUnitScale)
{
    /* update 'Move' matrix transform wireframes */
    unsigned int numMoveChildren = mMoveSwitch->getNumChildren();
    if (numMoveChildren > 1)
    {
	Vec3 gridOffsetVect = Vec3(0, 0, 0);
	if (mMoveSVect.x() > 0) gridOffsetVect = Vec3(gridUnitLegnth, 0, 0);
	else if (mMoveSVect.x() < 0) gridOffsetVect = Vec3(-gridUnitLegnth, 0, 0);
	else if (mMoveSVect.y() > 0) gridOffsetVect = Vec3(0,  gridUnitLegnth, 0);
	else if (mMoveSVect.y() < 0) gridOffsetVect = Vec3(0, -gridUnitLegnth, 0);
	else if (mMoveSVect.z() > 0) gridOffsetVect = Vec3(0, 0,  gridUnitLegnth);
	else if (mMoveSVect.z() < 0) gridOffsetVect = Vec3(0, 0, -gridUnitLegnth);

	for (int i = 0; i < numMoveChildren; i++)
	{
	    Matrixd transMat;
	    transMat.makeTranslate(gridOffsetVect * i);
	    mMoveMatTransVector[i]->setMatrix(mBoundBoxScaleMat * mAccRootMat * transMat);
	}
	return;
    }

    /* update 'Rotate' matrix transform wireframes */
    unsigned int numRotateChildren = mRotateSwitch->getNumChildren();
    if (numRotateChildren > 1)
    {
	Vec3 gridRotationAxis = Vec3(0, 0, 1);
	if (mRotateSVect.x() > 0) gridRotationAxis = Vec3(1, 0, 0);
	else if (mRotateSVect.x() < 0) gridRotationAxis = Vec3(-1, 0, 0);
	else if (mRotateSVect.y() > 0) gridRotationAxis = Vec3(0, 1, 0);
	else if (mRotateSVect.y() < 0) gridRotationAxis = Vec3(0, -1, 0);
	else if (mRotateSVect.z() > 0) gridRotationAxis = Vec3(0, 0, 1);
	else if (mRotateSVect.z() < 0) gridRotationAxis = Vec3(0, 0, -1);

	for (int i = 0; i < numRotateChildren; i++)
	{
	    Matrixd rotMat;
	    rotMat.makeRotate(gridUnitAngle * i, gridRotationAxis);
	    mRotateMatTransVector[i]->setMatrix(mBoundSphereScaleMat * rotMat);
	}
	return;
    }

    /* update 'Scale' matrix transform wireframes */
    unsigned int numScaleChildren = mManipulateSwitch->getNumChildren();
    if (numScaleChildren > 1)
    {
	/* rewrite scaling vector */
	mScaleUnitVect.x() = mScaleUnitVect.x() > 0 ? 1:0;
	mScaleUnitVect.y() = mScaleUnitVect.y() > 0 ? 1:0;
	mScaleUnitVect.z() = mScaleUnitVect.z() > 0 ? 1:0;
	mScaleUnitVect *= gridUnitScale;

	for (int i = 0; i < numScaleChildren; i++)
	{
	    /* generate scaling vector with non-negative values */
	    Vec3 scaleVect = Vec3(1, 1, 1);
	    if (mScaleNumSegs > 0) scaleVect += mScaleUnitVect * i;
	    else scaleVect -= mScaleUnitVect * i;
	    scaleVect.x() = scaleVect.x() > 0 ? scaleVect.x() : 0;
	    scaleVect.y() = scaleVect.y() > 0 ? scaleVect.y() : 0;
	    scaleVect.z() = scaleVect.z() > 0 ? scaleVect.z() : 0;

	    Matrixd scaleMat;
	    scaleMat.makeScale(scaleVect);
	    mManipulateMatTransVector[i]->setMatrix(mBoundBoxScaleMat * mAccRootMat * scaleMat);
	}
	return;
    }
}
/***************************************************************
* Function: applyScaling()
*
* 'gridUnitScaleVect' is guranteed to be non-negative vector
*
***************************************************************/
void CAVEGroupEditGeodeWireframe::applyScaling( const short &nOffsetSegs, const Vec3 &gridUnitScaleVect, 
						const std::string &gridUnitScaleInfo)
{
    mManipulateSwitch->setAllChildrenOn();

    /* scale to other direction: clear all children of 'mManipulateSwitch' except child[0], rebuild offset tree */
    if (mScaleNumSegs * nOffsetSegs <= 0)
    {
	unsigned int numChildren = mManipulateSwitch->getNumChildren();
	if (numChildren > 1)
	{
	    mManipulateSwitch->removeChildren(1, numChildren - 1);
	    MatrixTransVector::iterator itrMatTrans = mManipulateMatTransVector.begin();
	    mManipulateMatTransVector.erase(itrMatTrans + 1, itrMatTrans + numChildren);
	}
	mScaleNumSegs = 0;
    }

    /* decide unit offset vector and start/end index of children under 'mManipulateSwitch' */
    short idxStart = 0, idxEnd = 0;
    if (nOffsetSegs != 0)
    {
	idxStart = mScaleNumSegs;
	idxEnd = nOffsetSegs;
    }
    idxStart = idxStart > 0 ? idxStart: -idxStart;
    idxEnd = idxEnd > 0 ? idxEnd : -idxEnd;

    /* update the first wireframe with global translation and rotation */
    if (idxStart == 0) mManipulateMatTransVector[0]->setMatrix(mBoundBoxScaleMat * mAccRootMat);

    /* create or remove a sequence of extra children under 'mMoveSwitch' */
    if (idxStart < idxEnd)
    {
	for (short i = idxStart + 1; i <= idxEnd; i++)
	{
	    /* generate scaling vector with non-negative values */
	    Vec3 scaleVect = Vec3(1, 1, 1);
	    if (nOffsetSegs > 0) scaleVect += gridUnitScaleVect * i;
	    else scaleVect -= gridUnitScaleVect * i;
	    scaleVect.x() = scaleVect.x() > 0 ? scaleVect.x() : 0;
	    scaleVect.y() = scaleVect.y() > 0 ? scaleVect.y() : 0;
	    scaleVect.z() = scaleVect.z() > 0 ? scaleVect.z() : 0;

	    Matrixd scaleMat;
	    scaleMat.makeScale(scaleVect);
	    MatrixTransform *scaleTrans = new MatrixTransform;
	    CAVEGeodeEditWireframeManipulate *manipulateGeode = new CAVEGeodeEditWireframeManipulate;
	    mManipulateSwitch->addChild(scaleTrans);
	    mManipulateMatTransVector.push_back(scaleTrans);
	    scaleTrans->addChild(manipulateGeode);
	    scaleTrans->setMatrix(mBoundBoxScaleMat * mAccRootMat * scaleMat);
	}
    }
    else if (idxStart > idxEnd)
    {
	mManipulateSwitch->removeChildren(idxEnd + 1, idxStart - idxEnd);
	MatrixTransVector::iterator itrMatTrans = mManipulateMatTransVector.begin();
	itrMatTrans += idxEnd + 1;
	mManipulateMatTransVector.erase(itrMatTrans, itrMatTrans + (idxStart - idxEnd));
    }

    mScaleNumSegs = nOffsetSegs;
    mScaleUnitVect = gridUnitScaleVect;

    if (!mPrimaryFlag) return;

    /* update info text if 'this' wireframe is primary */
    mEditInfoTextSwitch->setAllChildrenOn();

    float scaleUnit = gridUnitScaleVect.x() > 0 ? gridUnitScaleVect.x() : gridUnitScaleVect.y();
    scaleUnit = scaleUnit > 0 ? scaleUnit : gridUnitScaleVect.z();

    char info[128];
    float scaleval = scaleUnit * nOffsetSegs + 1.0f;
    scaleval = scaleval > 0 ? scaleval:0;
    sprintf(info, "Scale = %3.2f \nSnapping = ", scaleval);
    mEditInfoText->setText(info + gridUnitScaleInfo);
}