I came across this code but not sure how I can write it in 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;
}
I mainly don’t understand the const char line. Is it trying to get the first item of values array?
The purpose of casting
pointstosourceis to get a constant byte array (effectively) version of thefloatarray thatI assume that
vstrideis a value of 12 or more.vstrideis being used to skip an arbitrary number of bytes for the current point in order to calculate the weighted value. As there are at least 3floatpoints per position, that is how I came up with at least 12 (3 times 4). It could be more if there is other data in the array along with the point, between the z coordinate and the start of the next point.The reason that it is necessary to use the
sourcepointer is because pointer arithmetic works based on thesizeofthe pointed data. Thus(points + 12)is different from(source + 12), and clearlyvstrideis associated with the number of bytes to skip (sort of implying that thepointsreference may actually be astructure that is being used asfloatarray out of convenience, which is not unusual in C/C++).In C#, you would not be writing something like this. You are going to pass in an array/collection of Points, which is going to be an object that has an X, Y, and Z
floating point coordinate. Similarly, there will be an optional (can benull, as noted byif (wsource)) array/collection of Weights, which contains a singlefloatvalue in it representing the weight for the current coordinate. It may make sense to combine them together. The points and weights have the same number of elements, ifweightsis defined.You will not need the
vcount,vstride, orwstridevariables in C#. You can loop through thePointsarray/collection and apply the weight if any Weights are supplied.