2012-03-20 2 views
1

я наткнулся на этот код, но не знаю, как я могу написать это в C#:C++ код справки для C#

bool getBestFitPlane(unsigned int vcount, 
        const float *points, 
        unsigned int vstride, 
        const float *weights, 
        unsigned int wstride, 
        float *plane) 
{ 
    bool ret = false; 

    SinglePrecision::Vec3 kOrigin(0,0,0); 

    float wtotal = 0; 

    if (1) 
    { 
    const char *source = (const char *) points; 
    const char *wsource = (const char *) weights; 

    for (unsigned int i=0; i<vcount; i++) 
    { 

     const float *p = (const float *) source; 

     float w = 1; 

     if (wsource) 
     { 
     const float *ws = (const float *) wsource; 
     w = *ws; // 
     wsource+=wstride; 
     } 

     kOrigin.x+=p[0]*w; 
     kOrigin.y+=p[1]*w; 
     kOrigin.z+=p[2]*w; 

     wtotal+=w; 

     source+=vstride; 
    } 
    } 

    float recip = 1.0f/wtotal; // reciprocol of total weighting 

    kOrigin.x*=recip; 
    kOrigin.y*=recip; 
    kOrigin.z*=recip; 


    float fSumXX=0; 
    float fSumXY=0; 
    float fSumXZ=0; 

    float fSumYY=0; 
    float fSumYZ=0; 
    float fSumZZ=0; 


    if (1) 
    { 
    const char *source = (const char *) points; 
    const char *wsource = (const char *) weights; 

    for (unsigned int i=0; i<vcount; i++) 
    { 

     const float *p = (const float *) source; 

     float w = 1; 

     if (wsource) 
     { 
     const float *ws = (const float *) wsource; 
     w = *ws; // 
     wsource+=wstride; 
     } 

     SinglePrecision::Vec3 kDiff; 

     kDiff.x = w*(p[0] - kOrigin.x); // apply vertex weighting! 
     kDiff.y = w*(p[1] - kOrigin.y); 
     kDiff.z = w*(p[2] - kOrigin.z); 

     fSumXX+= kDiff.x * kDiff.x; // sume of the squares of the differences. 
     fSumXY+= kDiff.x * kDiff.y; // sume of the squares of the differences. 
     fSumXZ+= kDiff.x * kDiff.z; // sume of the squares of the differences. 

     fSumYY+= kDiff.y * kDiff.y; 
     fSumYZ+= kDiff.y * kDiff.z; 
     fSumZZ+= kDiff.z * kDiff.z; 


     source+=vstride; 
    } 
    } 

    fSumXX *= recip; 
    fSumXY *= recip; 
    fSumXZ *= recip; 
    fSumYY *= recip; 
    fSumYZ *= recip; 
    fSumZZ *= recip; 

    // setup the eigensolver 
    SinglePrecision::Eigen kES; 

    kES.mElement[0][0] = fSumXX; 
    kES.mElement[0][1] = fSumXY; 
    kES.mElement[0][2] = fSumXZ; 

    kES.mElement[1][0] = fSumXY; 
    kES.mElement[1][1] = fSumYY; 
    kES.mElement[1][2] = fSumYZ; 

    kES.mElement[2][0] = fSumXZ; 
    kES.mElement[2][1] = fSumYZ; 
    kES.mElement[2][2] = fSumZZ; 

    // compute eigenstuff, smallest eigenvalue is in last position 
    kES.DecrSortEigenStuff(); 

    SinglePrecision::Vec3 kNormal; 

    kNormal.x = kES.mElement[0][2]; 
    kNormal.y = kES.mElement[1][2]; 
    kNormal.z = kES.mElement[2][2]; 

    // the minimum energy 
    plane[0] = kNormal.x; 
    plane[1] = kNormal.y; 
    plane[2] = kNormal.z; 

    plane[3] = 0 - kNormal.dot(kOrigin); 

    return ret; 
} 

я в основном не понимают константный обугленного линию. Он пытается получить первый элемент массива значений?

+2

Это похоже на код C. В настоящее время он ничего не делает, поскольку значение p никогда не используется. – Lucina

+5

Я не знаю, почему вы хотели бы сделать это на C#. Узнайте, что это за намерение, и напишите в чистом современном стиле. –

+1

Поскольку эта вещь бессмысленна даже в C, вы должны либо предоставить больше контекста, либо объяснить, в чем смысл этого кода. –

ответ

2

В основном я не понимаю строку const char. Он пытается получить первый элемент массива значений?

Цель отливки points к source, чтобы получить версию постоянной массив байтов (эффективно) из массива float, что

// use points as a byte array 
const char *source = (const char *) points; 

for (unsigned int i=0; i<vcount; i++) 
{ 
    // get a reference to the current position in the source array 
    const float *p = (const float *) source; 

    ... 

    // iterate to the next series of points 
    source+=vstride; 
} 

Я полагаю, что vstride является значение 12 или более. vstride используется для пропуски произвольного количества байтов для текущей точки, чтобы вычислить взвешенное значение. Поскольку есть как минимум 3 float очков за позицию, вот как я придумал не менее 12 (3 раза 4). Это может быть больше, если в массиве есть другие данные вместе с точкой, между координатой z и началом следующей точки.

Причина, по которой необходимо использовать указатель source, заключается в том, что арифметика указателя работает на основе sizeof заостренных данных. Таким образом (points + 12) отличается от (source + 12), и ясно vstride связано с числом байтов, чтобы пропустить (то подразумевается, что points ссылка может быть на самом деле struct Юр, который используется в качестве float массива из удобства, что не является необычным в C/C++).

В C# вы бы не писали нечто подобное. Вы собираетесь передать массив/набор точек, который будет объектом, который имеет координату точки X, Y и Z . Точно так же будет необязательный (может быть , как указано if (wsource)) массив/набор весов, который содержит одно значение float, представляющее вес для текущей координаты. Может быть разумно объединить их. Точки и веса имеют одинаковое количество элементов, если определено weights.

Вам не нужны vcount, vstride или wstride переменные в C#. Вы можете прокручивать массив/коллекцию Points и применять вес, если поставляются грузы.

float weight = 1.0f; 

for (int i = 0; i < points.Length; ++i) 
{ 
    if (weights != null) 
    { 
     weight = weights[i].Weight; 
    } 

    x += points[i].X * weight; 
    y += points[i].Y * weight; 
    z += points[i].Z * weight; 

    wtotal += weight; 
} 
+0

Спасибо, очень хороший ответ, именно то, что я делал на C#. –

3

По существу, да - хотя здесь происходит какое-то странное литье, которое кажется ненужным, по крайней мере, учитывая фрагмент кода, который вы опубликовали.

Линия объявляет постоянный (то есть неизменяемый) указатель (*) символу (подписанный байт) с именем «источник» и присваивает ему адрес начала «значений». Это странно, потому что, как вы можете видеть из списка аргументов, значения представляют собой const float * type.

Типы указателей часто используются для обработки массивов в старых программах на C/C++, поскольку они несколько взаимозаменяемы.

Для C# вместо этого вы должны использовать встроенный тип массива.

[EDIT] Теперь, когда вы разместили больше источников, ясно, что это было сделано для того, чтобы они могли использовать переменную «source», чтобы указывать на блок поплавков и увеличивать ее на величину «шага» байты (символы), когда необходимо, чтобы перейти к поплавку, подлежащему обработке. Вы можете, конечно, разработать код C# для обработки этого макета памяти, если это необходимо (System.IntPtr может быть вам полезна.)

+0

Так что, по сути, источник - это индекс, не так ли? (что он увеличивает) –

+0

Спасибо, но почему бы просто не перечеркнуть «значения», используя простой цикл? –

+0

Да - кажется, что поплавки разделены некоторой величиной «vstride», указанной в байтах, поэтому выполняется нечетное кастинг. Если вам нужно работать с одним и тем же макетом данных, я бы предложил получить фрагмент C, работающий в тестовой программе, с некоторыми примерами данных (которые вы затем можете использовать для подтверждения своей реализации C#) – holtavolt

Смежные вопросы