Справка по коду C ++ для C # - PullRequest
1 голос
/ 20 марта 2012

Я сталкивался с этим кодом, но не уверен, как написать его на 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;
}

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

Ответы [ 2 ]

3 голосов
/ 20 марта 2012

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

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

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

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

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

2 голосов
/ 20 марта 2012

Я в основном не понимаю строку 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 ure, которая используется как float массив из удобства, что не является чем-то необычным в C / C ++).

В C # вы бы не писали что-то подобное.Вы собираетесь передать массив / набор точек, который будет объектом с координатами точки X, Y и Z float.Точно так же будет необязательный (может быть null, как отмечено 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;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...