// -*- Mode: c++ -*- /*************************************************************************** file : geometry.h created : Mon Nov 22 0:10:00 CET 2004 copyright : (C) 2004 by Christos Dimitrakakis email : dimitrak@idiap.ch version : $Id: geometry.cpp,v 1.9 2006/01/06 15:22:29 olethros Exp $ ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "geometry.h" #include #include #include #include #include #ifdef WIN32 #include #define isnan _isnan #endif Vector::Vector(int N_, enum BoundsCheckingStatus check) { n = N_; maxN = n; if (n==0) { x = NULL; } else { x = (float*) malloc(sizeof(float)*n); for (int i=0; i=n)) { throw std::out_of_range("index out of range"); } } return x[index]; } const float& Vector::operator[] (int index) const { if (checking_bounds) { if ((index<0) || (index>=n)) { throw std::out_of_range("index out of range"); } } return x[index]; } void Vector::Resize(int N_) { n = N_; if (n>maxN) { if (n==0) { x = (float*) malloc (sizeof(float)*n); } else { x = (float*) realloc(x, sizeof(float)*n); } maxN = n; } } float DotProd(Vector* A, Vector* B) { int n = A->n; float sum = 0.0; for (int i=0; ix[i]*B->x[i]; } return sum; } void Sub (Vector* A, Vector* B, Vector* R) { for (int i=0; in; i++) { R->x[i] = A->x[i] - B->x[i]; } } ParametricLine::ParametricLine (Vector* A, Vector* B) { int N = A->n; R = new Vector(N); Q = new Vector(N); for (int i=0; ix[i] = A->x[i]; Q->x[i] = B->x[i] - R->x[i]; } } ParametricLine::~ParametricLine() { delete Q; delete R; } void ParametricLine::PointCoords (float t, Vector* X) { for (int i=0; in; i++) { X->x[i] = Q->x[i] + t*R->x[i]; } } Vector* GetNormalToLine(Vector* R) { int N = R->Size(); Vector* Q = new Vector(N); int i; int index = 0; for (i=0; iR->n; Vector b(N); Sub (B->R, A->R, &b); Vector* a = A->Q; //Vector* b = D; Vector* c = B->Q; for (int i=0; in; Vector D(N); Sub (line->R, C, &D); float a = DotProd (line->Q, line->Q); float b = 2.0*DotProd (line->Q, &D); float c = DotProd(&D, &D) - r*r; Vector* t = new Vector(0); if (a==0) { t->Resize(1); t->x[0] = -c/b; } else { float q = b*b - 4*a*c; if (q==0) { t->Resize(1); t->x[0] = -b/(2*a); } else if (q>0) { t->Resize(2); t->x[0] = (sqrt(q)-b)/(2*a); t->x[1] = (-sqrt(q)-b)/(2*a); //printf ("%f %f\n", t->x[0], t->x[1]); } else { //fprintf (stderr, "no solutions: q=%f\n", q); } } return t; } float CalculateRadiusPoints (std::vector P) { int K = P.size(); if (K!=3) { printf ("K=%d\n", K); throw std::invalid_argument ("P has size !=3"); } int N = P[0].Size(); ParametricLine W(&P[0], &P[1]); Vector* A = GetNormalToLine (W.Q); delete W.Q; W.Q = A; ParametricLine Z = ParametricLine(&P[1], &P[2]); Vector* B = GetNormalToLine (Z.Q); delete Z.Q; Z.Q = B; int i; for (i=0; in; this->C = new Vector(N); for (int i=0; iC->x[i] = C->x[i]; } this->r = r; } ParametricSphere::ParametricSphere(int N) { C = new Vector(N); r = 0; } ParametricSphere::~ParametricSphere() { delete C; } /** Estimate an optimally fitting sphere. * */ void EstimateSphere (std::vector P, ParametricSphere* sphere) { int N=P.size(); if (N<=0) { throw std::invalid_argument ("P has size <=0 "); } int d=P[0].n; int iter = 1000; float a = 0.001f; float delta_prev = 100; float converge = 1.0; Vector mean(d); float** Q = new float* [N]; float* Q_buffer = new float[N*d]; int i, j; for (j=0; j scale) { scale = fabs(Q[j][i]); } } } for (i=0; ir / scale; for (i=0; iC))[i] - mean[i]) / scale; } for (int n=0; nC))[i] - mean[i]) / scale; } r = 1.0; a = a*.1; } //printf ("%f\n", r); } float aconv=0.5; converge = aconv*converge + (1-aconv) * fabs(delta_total-delta_prev)/a; delta_prev = delta_total; if (converge < 0.0001f) { break; } } sphere->r = r * scale; for (i=0; iC))[i] = center[i]*scale + mean[i]; } delete [] Q_buffer; delete [] Q; }