117 lines
3.2 KiB
C++
117 lines
3.2 KiB
C++
template <class NUMERIC>
|
|
double OrientedBoundingBox<NUMERIC>::area() {
|
|
return sqrt((ul.x - ll.x)*(ul.x - ll.x) + (ul.y - ll.y)*(ul.y - ll.y)) *
|
|
sqrt((ul.x - ur.x)*(ul.x - ur.x) + (ul.y - ur.y)*(ul.y - ur.y)) ;
|
|
}
|
|
|
|
template<class NUMERIC>
|
|
OrientedBoundingBox<NUMERIC>::OrientedBoundingBox(std::vector< point<NUMERIC> > p) {
|
|
|
|
int nOfPoints = (int) p.size();
|
|
|
|
// calculate the center of all points (schwerpunkt)
|
|
// -------------------------------------------------
|
|
double centerx = 0;
|
|
double centery = 0;
|
|
for (int i=0; i < nOfPoints; i++) {
|
|
centerx += p[i].x;
|
|
centery += p[i].y;
|
|
}
|
|
centerx /= (double) nOfPoints;
|
|
centery /= (double) nOfPoints;
|
|
|
|
|
|
|
|
// calcutae the covariance matrix
|
|
// -------------------------------
|
|
// covariance matrix (x1 x2, x3 x4)
|
|
double x1 = 0.0;
|
|
double x2 = 0.0;
|
|
double x3 = 0.0;
|
|
double x4 = 0.0;
|
|
|
|
for (int i=0; i < nOfPoints; i++) {
|
|
double cix = p[i].x - centerx;
|
|
double ciy = p[i].y - centery;
|
|
|
|
x1 += cix*cix;
|
|
x2 += cix*ciy;
|
|
x4 += ciy*ciy;
|
|
}
|
|
x1 /= (double) nOfPoints;
|
|
x2 /= (double) nOfPoints;
|
|
x3 = x2;
|
|
x4 /= (double) nOfPoints;
|
|
// covariance & center done
|
|
|
|
|
|
// calculate the eigenvectors
|
|
// ---------------------------
|
|
// catch 1/0 or sqrt(<0)
|
|
if ((x3 == 0) || (x2 == 0)|| (x4*x4-2*x1*x4+x1*x1+4*x2*x3 < 0 )) {
|
|
fprintf(stderr,"error computing the Eigenvectors (%s, line %d)\nx3=%lf, x2=%lf, term=%lf\n\n",
|
|
__FILE__, __LINE__, x3,x2, (x4*x4-2*x1*x4+x1*x1+4*x2*x3) );
|
|
|
|
ul.x = 0;
|
|
ul.y = 0;
|
|
ur.x = 0;
|
|
ur.y = 0;
|
|
ll.x = 0;
|
|
ll.y = 0;
|
|
lr.x = 0;
|
|
lr.y = 0;
|
|
}
|
|
|
|
// eigenvalues
|
|
double lamda1 = 0.5* (x4 + x1 + sqrt(x4*x4 - 2.0*x1*x4 + x1*x1 + 4.0*x2*x3));
|
|
double lamda2 = 0.5* (x4 + x1 - sqrt(x4*x4 - 2.0*x1*x4 + x1*x1 + 4.0*x2*x3));
|
|
|
|
// eigenvector 1 with (x,y)
|
|
double v1x = - (x4-lamda1) * (x4-lamda1) * (x1-lamda1) / (x2 * x3 * x3);
|
|
double v1y = (x4-lamda1) * (x1-lamda1) / (x2 * x3);
|
|
// eigenvector 2 with (x,y)
|
|
double v2x = - (x4-lamda2) * (x4-lamda2) * (x1-lamda2) / (x2 * x3 * x3);
|
|
double v2y = (x4-lamda2) * (x1-lamda2) / (x2 * x3);
|
|
|
|
// norm the eigenvectors
|
|
double lv1 = sqrt ( (v1x*v1x) + (v1y*v1y) );
|
|
double lv2 = sqrt ( (v2x*v2x) + (v2y*v2y) );
|
|
v1x /= lv1;
|
|
v1y /= lv1;
|
|
v2x /= lv2;
|
|
v2y /= lv2;
|
|
// eigenvectors done
|
|
|
|
// get the points with maximal dot-product
|
|
double x = 0.0;
|
|
double y = 0.0;
|
|
double xmin = 1e20;
|
|
double xmax = -1e20;
|
|
double ymin = 1e20;
|
|
double ymax = -1e20;
|
|
for(int i = 0; i< nOfPoints; i++) {
|
|
// dot-product of relativ coordinates of every point
|
|
x = (p[i].x - centerx) * v1x + (p[i].y - centery) * v1y;
|
|
y = (p[i].x - centerx) * v2x + (p[i].y - centery) * v2y;
|
|
|
|
if( x > xmax) xmax = x;
|
|
if( x < xmin) xmin = x;
|
|
if( y > ymax) ymax = y;
|
|
if( y < ymin) ymin = y;
|
|
}
|
|
|
|
// now we can compute the corners of the bounding box
|
|
ul.x = centerx + xmin * v1x + ymin * v2x;
|
|
ul.y = centery + xmin * v1y + ymin * v2y;
|
|
|
|
ur.x = centerx + xmax * v1x + ymin * v2x;
|
|
ur.y = centery + xmax * v1y + ymin * v2y;
|
|
|
|
ll.x = centerx + xmin * v1x + ymax * v2x;
|
|
ll.y = centery + xmin * v1y + ymax * v2y;
|
|
|
|
lr.x = centerx + xmax * v1x + ymax * v2x;
|
|
lr.y = centery + xmax * v1y + ymax * v2y;
|
|
|
|
}
|