⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 testapproximation.cpp

📁 《3D游戏引擎设计》的源码
💻 CPP
字号:
// Magic Software, Inc.
// http://www.magic-software.com
// Copyright (c) 2000, All Rights Reserved
//
// Source code from Magic Software is supplied under the terms of a license
// agreement and may not be copied or disclosed except in accordance with the
// terms of that agreement.  The various license agreements may be found at
// the Magic Software web site.  This file is subject to the license
//
// FREE SOURCE CODE
// http://www.magic-software.com/License.html/free.pdf

#include <MgcCore.pkg>
#include <MgcApproximation.pkg>
#include <MgcNumerics.pkg>

#define DRAND (2.0*rand()/(MgcReal)RAND_MAX-1.0)

//----------------------------------------------------------------------------
void TestLineFit2 ()
{
    const int n = 256;

    MgcVector2* pt = new MgcVector2[n];
    MgcVector2 dir(1.0,2.0);
    MgcVector2 off(0.1,0.1);

    for (int i = 0; i < n; i++) 
    {
        // generate random point on true line
        MgcReal tval = DRAND;
        pt[i].x = off.x + tval * dir.x;
        pt[i].y = off.y + tval * dir.y;

        // generate random perturbation of point
        const MgcReal amp = 0.1;
        pt[i].x += amp*DRAND;
        pt[i].y += amp*DRAND;
    }

    // unitize the true direction
    MgcReal len = sqrt(dir.x*dir.x+dir.y*dir.y);
    if ( len > 0 ) 
    {
        dir.x /= len;
        dir.y /= len;
    }

    // find true line offset which is closest to origin
    MgcReal offDotDir = off.x*dir.x+off.y*dir.y;
    off.x -= offDotDir * dir.x;
    off.y -= offDotDir * dir.y;

    // print the true parameters
    cout << "TRUE:" << endl;
    cout << "offset = (" 
         << off.x << ',' 
         << off.y << ')' << endl;
    cout << "direction = ("
         << dir.x << ','
         << dir.y << ')' << endl;
    cout << endl;

    MgcOrthogonalLineFit(n,pt,off,dir);
    offDotDir = off.x*dir.x+off.y*dir.y;
    off.x -= offDotDir * dir.x;
    off.y -= offDotDir * dir.y;
    cout << "APPROXIMATE:" << endl;
    cout << "offset = (" 
         << off.x << ',' 
         << off.y << ')' << endl;
    cout << "direction = ("
         << dir.x << ','
         << dir.y << ')' << endl;

    delete[] pt;
}
//----------------------------------------------------------------------------
void TestLineFit3 ()
{
    const int n = 256;

    MgcVector3* pt = new MgcVector3[n];
    MgcVector3 dir(1.0,2.0,3.0);
    MgcVector3 off(0.1,0.1,0.1);

    for (int i = 0; i < n; i++) 
    {
        // generate random point on true line
        MgcReal tval = DRAND;
        pt[i].x = off.x + tval * dir.x;
        pt[i].y = off.y + tval * dir.y;
        pt[i].z = off.z + tval * dir.z;

        // generate random perturbation of point
        const MgcReal amp = 0.1;
        pt[i].x += amp*DRAND;
        pt[i].y += amp*DRAND;
        pt[i].z += amp*DRAND;
    }

    // unitize the true direction
    MgcReal len = sqrt(dir.x*dir.x+dir.y*dir.y+dir.z*dir.z);
    if ( len > 0 ) 
    {
        dir.x /= len;
        dir.y /= len;
        dir.z /= len;
    }

    // find true line offset which is closest to origin
    MgcReal offDotDir = off.x*dir.x+off.y*dir.y+off.z*dir.z;
    off.x -= offDotDir * dir.x;
    off.y -= offDotDir * dir.y;
    off.z -= offDotDir * dir.z;

    // print the true parameters
    cout << "TRUE:" << endl;
    cout << "offset = (" 
         << off.x << ',' 
         << off.y << ',' 
         << off.z << ')' << endl;
    cout << "direction = ("
         << dir.x << ','
         << dir.y << ','
         << dir.z << ')' << endl;
    cout << endl;

    MgcOrthogonalLineFit(n,pt,off,dir);
    offDotDir = off.x*dir.x+off.y*dir.y+off.z*dir.z;
    off.x -= offDotDir * dir.x;
    off.y -= offDotDir * dir.y;
    off.z -= offDotDir * dir.z;
    cout << "APPROXIMATE:" << endl;
    cout << "offset = (" 
         << off.x << ',' 
         << off.y << ',' 
         << off.z << ')' << endl;
    cout << "direction = ("
         << dir.x << ','
         << dir.y << ','
         << dir.z << ')' << endl;

    delete[] pt;
}
//----------------------------------------------------------------------------
void TestPlaneFit ()
{
    const int n = 256;

    MgcVector3* pt = new MgcVector3[n];
    MgcVector3 nor( 1.0, 2.0, 3.0 );
    MgcVector3 off( 0.1, 0.1, 0.1 );

    MgcVector3 tan1( -2.0, 1.0, 0.0 );
    MgcVector3 tan2( -3.0, -6.0, 5.0 );
    for (int i = 0; i < n; i++) 
    {
        // generate random point on true line
        MgcReal sval = DRAND, tval = DRAND;
        pt[i].x = off.x + sval * tan1.x + tval * tan2.x;
        pt[i].y = off.y + sval * tan1.y + tval * tan2.y;
        pt[i].z = off.z + sval * tan1.z + tval * tan2.z;

        // generate random perturbation of point
        const MgcReal amp = 0.1;
        pt[i].x += amp*DRAND;
        pt[i].y += amp*DRAND;
        pt[i].z += amp*DRAND;
    }

    // unitize the true normal
    MgcReal len = sqrt(nor.x*nor.x+nor.y*nor.y+nor.z*nor.z);
    if ( len > 0 ) 
    {
        nor.x /= len;
        nor.y /= len;
        nor.z /= len;
    }

    // find true plane offset which is closest to origin
    MgcReal offDotNor = off.x*nor.x+off.y*nor.y+off.z*nor.z;
    off.x = offDotNor * nor.x;
    off.y = offDotNor * nor.y;
    off.z = offDotNor * nor.z;

    // print the true parameters
    cout << "TRUE:" << endl;
    cout << "offset = (" 
         << off.x << ',' 
         << off.y << ',' 
         << off.z << ')' << endl;
    cout << "normal = ("
         << nor.x << ','
         << nor.y << ','
         << nor.z << ')' << endl;
    cout << endl;

    MgcReal minEnergy = MgcOrthogonalPlaneFit(n,pt,off,nor);
    offDotNor = off.x*nor.x+off.y*nor.y+off.z*nor.z;
    off.x = offDotNor * nor.x;
    off.y = offDotNor * nor.y;
    off.z = offDotNor * nor.z;
    cout << "APPROXIMATE:" << endl;
    cout << "offset = (" 
         << off.x << ',' 
         << off.y << ',' 
         << off.z << ')' << endl;
    cout << "normal = ("
         << nor.x << ','
         << nor.y << ','
         << nor.z << ')' << endl;
    cout << "energy = " << minEnergy << endl;

    delete[] pt;
}
//----------------------------------------------------------------------------
void TestCircleFit0()
{
    // points perturbed slightly from a circle

    // exact circle
    MgcVector2 kCenter(1.0,2.0);
    MgcReal fRadius = 1.0;

    // perturbed points
    const int N = 128;
    MgcVector2 point[N];

    for (int i = 0; i < N; i++)
    {
        MgcReal pa = kCenter.x + 0.1*DRAND;
        MgcReal pb = kCenter.y + 0.1*DRAND;
        MgcReal pr = fRadius + 0.1*DRAND;
        MgcReal angle = DRAND*MgcMath::PI;
        point[i].x = pa + pr*MgcMath::Cos(angle);
        point[i].y = pb + pr*MgcMath::Sin(angle);
    }

    bool bSuccess = MgcCircleFit(N,point,kCenter,fRadius);
}
//----------------------------------------------------------------------------
void TestCircleFit1()
{
    // randomly generated points

    const int N = 128;
    MgcVector2 point[N];

    for (int i = 0; i < N; i++)
    {
        point[i].x = DRAND;
        point[i].y = DRAND;
    }

    MgcVector2 kCenter;
    MgcReal fRadius;
    bool bSuccess = MgcCircleFit(N,point,kCenter,fRadius);
}
//----------------------------------------------------------------------------
void TestSphereFit0 ()
{
    // exact sphere
    MgcVector3 kCenter(1.0,2.0,3.0);
    MgcReal fRadius = 1.0;

    // perturbed points
    const int N = 128;
    MgcVector3 point[N];

    for (int i = 0; i < N; i++)
    {
        MgcReal pa = kCenter.x + 0.1*DRAND;
        MgcReal pb = kCenter.y + 0.1*DRAND;
        MgcReal pc = kCenter.z + 0.1*DRAND;
        MgcReal pr = fRadius + 0.1*DRAND;
        MgcReal theta = DRAND*MgcMath::PI;
        MgcReal phi = 0.5*(DRAND+1.0)*MgcMath::PI;
        MgcReal cst = MgcMath::Cos(theta);
        MgcReal snt = MgcMath::Sin(theta);
        MgcReal csp = MgcMath::Cos(phi);
        MgcReal snp = MgcMath::Sin(phi);
        point[i].x = pa + pr*cst*snp;
        point[i].y = pb + pr*snt*snp;
        point[i].z = pc + pr*csp;
    }

    bool bSuccess = MgcSphereFit(N,point,kCenter,fRadius);
}
//----------------------------------------------------------------------------
void TestSphereFit1 ()
{
    const int N = 128;
    MgcVector3 point[N];

    for (int i = 0; i < N; i++)
    {
        point[i].x = DRAND;
        point[i].y = DRAND;
        point[i].z = DRAND;
    }

    MgcVector3 kCenter;
    float fRadius;
    bool bSuccess = MgcSphereFit(N,point,kCenter,fRadius);
}
//----------------------------------------------------------------------------
void TestParaboloidFit ()
{
    // 9 data samples given on a 3x3 grid
    const int n = 9;
    MgcVector3 point[n];
    point[0].x = 0.0;  point[1].x = 0.5;  point[2].x = 1.0;
    point[3].x = 0.0;  point[4].x = 0.5;  point[5].x = 1.0;
    point[6].x = 0.0;  point[7].x = 0.5;  point[8].x = 1.0;

    point[0].y = 0.0;  point[1].y = 0.0;  point[2].y = 0.0;
    point[3].y = 0.5;  point[4].y = 0.5;  point[5].y = 0.5;
    point[6].y = 1.0;  point[7].y = 1.0;  point[8].y = 1.0;

    point[0].z = 1.0;  point[1].z = 1.0;  point[2].z = 1.0;
    point[3].z = 0.5;  point[4].z = 0.0;  point[5].z = 0.7;
    point[6].z = 0.9;  point[7].z = 1.1;  point[8].z = 0.8;

    MgcReal afCoeff[6];
    bool bSuccess = MgcParaboloidFit(n,point,afCoeff);
}
//----------------------------------------------------------------------------
void TestQuadraticFit2 ()
{
    const int n = 256;
    MgcVector2 p[n];

    // generate points on (x/a)^2 + (y/b)^2 - 1 = 0
    MgcReal a = 1.0;
    MgcReal b = 2.0;

    for (int i = 0; i < n; i++)
    {
        MgcReal angle = MgcMath::TWO_PI*MgcMath::UnitRandom();
        p[i].x = a*MgcMath::Cos(angle);
        p[i].y = b*MgcMath::Sin(angle);
    }

    MgcReal coeff[6];
    MgcReal minEnergy = MgcQuadraticFit(n,p,coeff);
}
//----------------------------------------------------------------------------
void TestQuadraticFit3 ()
{
    const int n = 256;
    MgcVector3 p[n];

    // generate points on (x/a)^2 + (y/b)^2 - (z/c)^2 - 1 = 0
    MgcReal a = 1.0;
    MgcReal b = 2.0;
    MgcReal c = 3.0;

    for (int i = 0; i < n; i++)
    {
        p[i].z = MgcMath::UnitRandom();
        MgcReal ratio = p[i].z/c;
        MgcReal r2 = 1.0+ratio*ratio;
        MgcReal r = MgcMath::Sqrt(r2);
        MgcReal angle = MgcMath::TWO_PI*MgcMath::UnitRandom();
        p[i].x = a*r*MgcMath::Cos(angle);
        p[i].y = b*r*MgcMath::Sin(angle);
    }

    MgcReal coeff[10];
    MgcReal minEnergy = MgcQuadraticFit(n,p,coeff);
}
//----------------------------------------------------------------------------
int main ()
{
    //TestLineFit2();
    //TestLineFit3();
    //TestPlaneFit();
    //TestCircleFit0();
    //TestCircleFit1();
    //TestSphereFit0();
    //TestSphereFit1();
    //TestParaboloidFit();
    TestQuadraticFit2();
    TestQuadraticFit3();
    return 0;
}
//----------------------------------------------------------------------------

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -