Acad::ErrorStatus
AsdkSmiley::transformBy(const AcGeMatrix3d& xform)
{
    assertWriteEnabled();

    // Transform the center point and get the translation vector
    AcGePoint3d oldCenter( center() ),
                newCenter( center() );
    newCenter.transformBy( xform );
    AcGeVector3d transVec = newCenter - center();

    // Get the equivalent transformation
    AcGeMatrix3d newXform;
    newXform.setToTranslation( transVec );

    // Only translate the face and mouth - do not transform!
    mfacecircle.transformBy( newXform );
    mmoutharc.transformBy( newXform );

    // Get the point at a quadrant, transform it..
    AcGePoint3d oldXquad = center() + AcGeVector3d( radius(), 0, 0 ),
                newXquad( oldXquad );
    newXquad.transformBy( xform );

    // ... then scale the Smiley accordingly
    if ( Adesk::kFalse == xform.isEqualTo( AcGeMatrix3d::kIdentity ))
        scaleRadius( radius() * newCenter.distanceTo( newXquad ) / oldCenter.distanceTo( oldXquad ));

    return Acad::eOk;
}
std::list<KDPoint> randomPointsInSphereGaussianDistribution(int numPoints, double radius, double width)
{
	CGAL::Random_points_in_sphere_3<KDPoint, Pt_creator> sphereRnd(1.0);
	std::list<KDPoint> innerRandomPoints;
	CGAL::copy_n(sphereRnd, numPoints, std::back_inserter(innerRandomPoints));

	std::list<KDPoint> randomPoints;
	std::list<KDPoint>::iterator pointsIter;
	for(pointsIter = innerRandomPoints.begin(); pointsIter != innerRandomPoints.end(); ++pointsIter)
	{
		KDPoint point = *pointsIter;
		KDVector vPointR = KDVector(point.x(), point.y(), point.z());
		double r =  CGAL::sqrt(vPointR.squared_length());
		KDVector unitVector = vPointR / r;
		double gaussRadius = std::exp(-(width*r*r));
		KDTransformation scaleGauss(CGAL::SCALING, gaussRadius);
		KDTransformation scaleRadius(CGAL::SCALING, radius);
		KDPoint scaledPoint = scaleGauss(KDPoint(unitVector.x(), unitVector.y(), unitVector.z()));
		scaledPoint = scaleRadius(scaledPoint);
		randomPoints.push_back(scaledPoint);
	}
	return randomPoints;
}
Acad::ErrorStatus
AsdkSmiley::moveGripPointsAt(
    const AcDbIntArray& indices,
    const AcGeVector3d& offset)
{
    assertWriteEnabled();

    AcGePoint3dArray eyearray;
    AcGePoint3d oldquad, newquad, newmouthcenter, newmouthbottom,
                smilecen, startpt, endpt, midpt, newpt;
    AcGeVector3d vecstart(0,0,0), vecend(0,0,0), newvec(0,0,0);

    eyes( eyearray );
    for( int i = 0; i < indices.length(); i++ ) {
        int idx = indices[i];
        switch( idx ) {

        // Stretch smiley center
        //
        case 0:
            setCenter( center() + offset );
            continue;

        // Stretch smiley radius
        //
        case 1:
            oldquad = center() + AcGeVector3d( radius(), 0, 0 );
            break;
        case 2:
            oldquad = center() + AcGeVector3d( 0, radius(), 0 );
            break;
        case 3:
            oldquad = center() - AcGeVector3d( radius(), 0, 0 );
            break;
        case 4:
            oldquad = center() - AcGeVector3d( 0, radius(), 0 );
            break;

        // Stretch smiley mouth
        //
        case 5:
            // Left hand edge of mouth
            //
            setMouthLeft( mouthLeft() + offset );
            ensureRadius();

            continue;

        case 6:
            // Right hand edge of mouth
            //
            setMouthRight( mouthRight() + offset );
            ensureRadius();

            continue;

        case 7:
            // Middle mouth chord
            //
            setMouth( mouthLeft() + offset, mouthBottom() + offset, mouthRight() + offset );
            ensureRadius();

            continue;

        case 8:
            // Bottom of mouth arc
            //
            setMouthBottom( mouthBottom() + offset );
            ensureRadius();

            continue;

        // Stretch smiley eyes
        //
        default:
            if(( eyearray.length() * 5 ) + 9 > idx ){
                
                // Get eye number, extracting it from the array
                //
                int eyepos = (int)(( idx - 9 ) / 5 );
                AcGePoint3d eyecen = eyearray.at( eyepos );
                
                // Handle the grip for the eye
                //
                int subidx = idx - 9;
                while ( subidx >= 5 ){ subidx -= 5; }
                switch( subidx ){

                // Stretch eye center
                //
                case 0:
                    // Keep the minimum eye height at zero
                    //
                    if( meyesheight+offset[Y] < 0 )
                        setEyesHeight( 0 );
                    else
                        setEyesHeight( meyesheight + offset[Y] );

                    // Keep the eyes from overlapping
                    //
                    if( eyecen[X] < center()[X] ){    // left eye
                        if( meyesapart - ( offset[X] * 2 ) < meyesize * 2 )
                            setEyesApart( meyesize * 2 );
                        else
                            setEyesApart( meyesapart - ( offset[X] * 2 ));
                    }
                    else {                          // right eye
                        if( meyesapart + ( offset[X] * 2 ) < meyesize * 2 )
                            setEyesApart( meyesize * 2 );
                        else
                            setEyesApart( meyesapart + ( offset[X] * 2));
                    }
                    ensureRadius();
                    continue;

                // Stretch eye radius
                //
                case 1:
                    oldquad = eyecen + AcGeVector3d( meyesize, 0, 0 );
                    break;
                case 2:
                    oldquad = eyecen + AcGeVector3d( 0, meyesize, 0 );
                    break;
                case 3:
                    oldquad = eyecen - AcGeVector3d( meyesize, 0, 0 );
                    break;
                case 4:
                    oldquad = eyecen - AcGeVector3d( 0, meyesize, 0 );
                    break;
                }
                newquad = oldquad + offset;
                
                // Keep eyes from touching
                //
                if( newquad.distanceTo( eyecen ) > meyesapart / 2 )
                    setEyeSize( meyesapart / 2 );
                else
                    setEyeSize( newquad.distanceTo( eyecen ));
                ensureRadius();
            }
            continue;
        }
        newquad = oldquad + offset;
        scaleRadius( newquad.distanceTo( center() ));
    }

    return Acad::eOk;
}