Exemplo n.º 1
0
static libmv::Marker ProjectMarker(const libmv::EuclideanPoint &point, const libmv::EuclideanCamera &camera,
			const libmv::CameraIntrinsics &intrinsics) {
	libmv::Vec3 projected = camera.R * point.X + camera.t;
	projected /= projected(2);

	libmv::Marker reprojected_marker;
	intrinsics.ApplyIntrinsics(projected(0), projected(1), &reprojected_marker.x, &reprojected_marker.y);

	reprojected_marker.image = camera.image;
	reprojected_marker.track = point.track;

	return reprojected_marker;
}
void extract_convex(pcl_cloud::Ptr cloud_in,
                    pcl::PointIndices::Ptr inliers,
                    pcl::ModelCoefficients::Ptr coefficients,
                    pcl_cloud::Ptr cloud_hull,
                    pcl_cloud::Ptr cloud_cave)

{
    pcl_cloud::Ptr projected(new pcl_cloud());

    pcl::ProjectInliers<Point> proj;
    proj.setModelType (pcl::SACMODEL_PLANE);
    proj.setIndices (inliers);
    proj.setInputCloud (cloud_in);
    proj.setModelCoefficients (coefficients);
    proj.filter (*projected);

    pcl::ConvexHull<Point> chull;
    chull.setInputCloud (projected);
    chull.reconstruct (*cloud_hull);

    pcl::ConcaveHull<Point> cavehull;
    cavehull.setAlpha(0.1);
    cavehull.setInputCloud (projected);
    cavehull.reconstruct (*cloud_cave);
}
void PointAnnotationImpl::updateLayer(const CanonicalTileID& tileID, AnnotationTileLayer& layer) const {
    std::unordered_map<std::string, std::string> featureProperties;
    featureProperties.emplace("sprite", point.icon.empty() ? std::string("default_marker") : point.icon);

    // Clamp to the latitude limits of Web Mercator.
    const double constrainedLatitude = util::clamp(point.position.latitude, -util::LATITUDE_MAX, util::LATITUDE_MAX);

    // Project a coordinate into unit space in a square map.
    const double sine = std::sin(constrainedLatitude * util::DEG2RAD);
    const double x = point.position.longitude / util::DEGREES_MAX + 0.5;
    const double y = 0.5 - 0.25 * std::log((1.0 + sine) / (1.0 - sine)) / M_PI;

    Point<double> projected(x, y);
    projected *= std::pow(2, tileID.z);
    projected.x = std::fmod(projected.x, 1);
    projected.y = std::fmod(projected.y, 1);
    projected *= double(util::EXTENT);

    layer.features.emplace_back(
        std::make_shared<const AnnotationTileFeature>(FeatureType::Point,
                                                      GeometryCollection {{ {{ convertPoint<int16_t>(projected) }} }},
                                                      featureProperties));
}
void	AnalyzerTest::testResiduals() {
	debug(LOG_DEBUG, DEBUG_LOG, 0, "testResiduals() begin");
	// read the chart image
	FITSinfile<float>	chart("testimages/deneb-chart.fits");
	Image<float>	*image1 = chart.read();
	TypeReductionAdapter<double, float>	base(*image1);

	// read the projected image
	FITSinfile<double>	projected("testimages/deneb-projected.fits");
	Image<double>	*image2 = projected.read();

	// compute the residuals
	Analyzer	analyzer(base);
	std::vector<Residual>	residuals = analyzer(*image2);

	debug(LOG_DEBUG, DEBUG_LOG, 0, "%d residuals", residuals.size());
	std::vector<Residual>::const_iterator	r;
	for (r = residuals.begin(); r != residuals.end(); r++) {
		// std::cout << r->first << " -> " << r->second << std::endl;
	}

	debug(LOG_DEBUG, DEBUG_LOG, 0, "testResiduals() end");
}
Exemplo n.º 5
0
Line SegmentStitching::extractLineFromMeasurements(pcl::PointCloud<pcl::PointXYZ>::Ptr measurements,
                                                   float ransacThreshold,
                                                   std::vector<int>* inliers){
    // Create the sample consensus object for the received cloud
    pcl::SampleConsensusModelLine<pcl::PointXYZ>::Ptr
        modelLine(new pcl::SampleConsensusModelLine<pcl::PointXYZ>(measurements));
            
    pcl::RandomSampleConsensus<pcl::PointXYZ> ransac(modelLine);
    ransac.setDistanceThreshold(ransacThreshold);
    ransac.computeModel();
    ransac.getInliers(*inliers);

    // Vector of 6 points
    // see http://docs.pointclouds.org/trunk/classpcl_1_1_sample_consensus_model_line.html
    Eigen::VectorXf coeff;
    ransac.getModelCoefficients(coeff);
    
    for (int i = 0; i < coeff.size(); i++){
        ROS_INFO("Coeff %d: %f", i, coeff[i]);
    }
    ROS_INFO("#Inliers: %d", (int)inliers->size());

    // Project inliers onto the line so that we end up with a cloud where
    // min+max can be found in order to define a line segment
    pcl::PointCloud<pcl::PointXYZ>::Ptr projected(new pcl::PointCloud<pcl::PointXYZ>);
    // project the inliers onto the model, without copying non-inliers over
    modelLine->projectPoints(*inliers, coeff, *projected, false);
    ROS_INFO("Projected size: %d", (int)projected->size());
    pcl::PointCloud<pcl::PointXYZ>::iterator it = projected->begin();

    // Segments have start and end points. A point is at the start or end of the
    // line if one of its coordinates corresponds to the minimum or maximum
    // value of either of the coordinate axes
    int xmaxInd = -1;
    int xminInd = -1;
    int ymaxInd = -1;
    int yminInd = -1;
    
    float xmax = -std::numeric_limits<float>::max();
    float ymax = -std::numeric_limits<float>::max();
    float xmin = std::numeric_limits<float>::max();
    float ymin = std::numeric_limits<float>::max();
    for (; it != projected->end(); it++) {
        // ROS_INFO_STREAM("Point " <<  (int)(it - projected->begin()) << ": " << *it);
        // std::cout << "x: " << it->x << ", max: " << xmax << " x bigger? " << (it->x > xmax) << std::endl;
        if (it->x > xmax){
            xmax = it->x;
            // index of this point is 
            xmaxInd = it - projected->begin();
            //ROS_INFO("X max ind: %d with val %f", xmaxInd, xmax);
        }
        if (it->y > ymax){
            ymax = it->y;
            // index of this point is 
            ymaxInd = it - projected->begin();
            //ROS_INFO("Y max ind: %d with val %f", ymaxInd, ymax);
        }
        if (it->x < xmin){
            xmin = it->x;
            // index of this point is 
            xminInd = it - projected->begin();
            //ROS_INFO("X min ind: %d with val %f", xminInd, xmin);
        }
        if (it->y < ymin){
            ymin = it->y;
            // index of this point is 
            yminInd = it - projected->begin();
            //ROS_INFO("Y min ind: %d with val %f", yminInd, ymin);
        }
    }
    ROS_INFO("xmin ind %d, xmax ind %d, ymin ind %d, ymax ind %d", 
             xminInd, xmaxInd, yminInd, ymaxInd);
    ROS_INFO("xmin %f, xmax %f, ymin %f, ymax %f", 
             xmin, xmax, ymin, ymax);

    // If the x or y coordinates are identical, then you have a vertical or
    // horizontal line - define start and end points of the line with the value
    // of xmin or max, and then assign values for the other coordinate to the
    // start and end point arbitrarily. You should be able to do this min/max
    // comparison based on the indices of xmin and xmax - they should be the same
    // if lines are horizontal or vertical
    if (xminInd == xmaxInd){
        return Line(pcl::PointXYZ(xmin, ymin, 0), pcl::PointXYZ(xmin, ymax, 0));
    } else if (yminInd == ymaxInd){
        return Line(pcl::PointXYZ(xmin, ymin, 0), pcl::PointXYZ(xmax, ymin, 0));
    } else {
        // TODO: Make sure this works correctly
        // This is a line which is not horizontal or vertical - the indices of
        // xmin,ymin or xmax, ymax should match. 
        if (xminInd == yminInd && xmaxInd == ymaxInd){
            return Line(pcl::PointXYZ(xmin, ymin, 0), pcl::PointXYZ(xmax, ymax, 0));
        } else if (xmaxInd == yminInd && xminInd == ymaxInd){
            return Line(pcl::PointXYZ(xmax, ymin, 0), pcl::PointXYZ(xmin, ymax, 0));
        }
    }
    ROS_ERROR("Reached end of extract line without getting anything!");
}
Exemplo n.º 6
0
void MeshViewerWindow::fileDrop(int pathCount, const char** paths)
{
	bool meshLoadedThisDrop = false;

	for (int pathIndex = 0; pathIndex < pathCount; ++pathIndex)
	{
		if (gtf::StaticMeshLoader::isMeshFile(paths[pathIndex]))
		{
			if (!meshLoadedThisDrop && m_meshLoader.loadFromFile(paths[pathIndex], m_mesh))
			{
				m_texturedShapes.clear();
	
				//reset camera
				m_frame.scale = 1.0f;
				m_frame.position = glm::vec3(0.0f);
				m_frame.viewPosition = glm::vec3(0.0f, 0.0f, -150.0f);
				m_frame.rotation = glm::vec3(0.0f);
				m_frame.scaleFactor = 1.0f;

				m_projectionMatrix = glm::perspective(220.0f, (float)m_windowWidth / glm::max(1.0f, (float)m_windowHeight), 1.0f, 1000.0f);
				m_modelMatrix = glm::mat4(1.0);
				m_viewMatrix = glm::translate(glm::mat4(1.0), m_frame.viewPosition);

				glm::vec2 topLeft(0, 0), bottomRight(0, 0);
				float midZ = 0.0f;
				glm::vec4 viewport(0, 0, m_windowWidth, m_windowHeight);
				glm::mat4 vpMatrix = m_projectionMatrix * m_viewMatrix;
				glm::mat4 ivpMatrix = glm::inverse(vpMatrix);

				
				int shapeCount = m_mesh.getShapeCount();


				for (int s = 0; s < shapeCount; ++s)
				{
					gtf::StaticMesh::Shape const * shape = m_mesh.getShape(s);
					std::shared_ptr<gtf::RHIVAO> newVAO(gtf::GRHI->createVertexBufferObject());
					newVAO->setup(m_attrList, shape->data, shape->vertexCount);
					
					//m_vaos.push_back(newVAO);
					TexturedShape texturedShape;
					texturedShape.name = shape->name;
					texturedShape.vao = newVAO;
					m_texturedShapes.push_back(texturedShape);
					
					//trying to calculate a default transformation to fid the viewport
					for (size_t vc = 0; vc < shape->vertexCount; vc++)
					{
						glm::vec4 projected(shape->data[vc].posX, shape->data[vc].posY, shape->data[vc].posZ, 1.0f);
						projected = vpMatrix * projected;
						projected /= projected.w;

						if (vc == 0)
						{
							topLeft.x = projected.x;
							topLeft.y = projected.y;
							bottomRight.x = projected.x;
							bottomRight.y = projected.y;
						}
						else
						{
							if (projected.x < topLeft.x)
								topLeft.x = projected.x;
							if (projected.x > bottomRight.x)
								bottomRight.x = projected.x;
							if (projected.y > topLeft.y)
								topLeft.y = projected.y;
							if (projected.y < bottomRight.y)
								bottomRight.y = projected.y;
						}

						midZ += projected.z;
					}

					midZ /= float(shape->vertexCount);
				}

				std::cout << "topLeft = (" << topLeft.x << ", " << topLeft.y << ")" << std::endl;
				std::cout << "bottomRight = (" << bottomRight.x << ", " << bottomRight.y << ")" << std::endl;

				float fixX = (bottomRight.x + topLeft.x) * 0.5f;
				float fixY = (bottomRight.y + topLeft.y) * 0.5f;

				glm::vec4 fixTranslate(fixX, -fixY, midZ, 1.0f);
				std::cout << "fixTranslate preProj = (" << fixTranslate.x << ", " << fixTranslate.y << ")" << std::endl;
				fixTranslate = ivpMatrix * fixTranslate;
				fixTranslate /= fixTranslate.w;
				fixTranslate.z = 0;
				std::cout << "fixTranslate = (" << fixTranslate.x << ", " << fixTranslate.y << ")" << std::endl;

				topLeft += glm::vec2(fixX, -fixY);
				bottomRight += glm::vec2(fixX, -fixY);

				float fixScale = 1.0f;
				if (glm::abs(topLeft.x) > glm::abs(bottomRight.x))
				{
					if (glm::abs(topLeft.x) > glm::abs(topLeft.y))
					{
						fixScale = 0.75f / glm::abs(topLeft.x);
					}
					else
					{
						fixScale = 0.75f / glm::abs(topLeft.y);
					}
				}
				else
				{
					if (glm::abs(bottomRight.x) > glm::abs(bottomRight.y))
					{
						fixScale = 0.75f / glm::abs(bottomRight.x);
					}
					else
					{
						fixScale = 0.75f / glm::abs(bottomRight.y);
					}
				}

				std::cout << "fixScale = " << fixScale << std::endl;
				m_frame.scale = fixScale;
				m_frame.scaleFactor = fixScale;
				m_frame.position = glm::vec3(fixTranslate);
			}
		}
	}
}
Exemplo n.º 7
0
	bool Box::testHit(Brick* brick) const
	{
		ofVec3f projected(brick->getHitPolygon().getPlane().project(getCenter()));
		bool result = brick->getHitPolygon().isInPolygon(projected);
		return result;
	}
Exemplo n.º 8
0
SOrientedBoundingBox *
SOrientedBoundingBox::buildOBB(std::vector<SPoint3> &vertices)
{
#if defined(HAVE_MESH)

  int num_vertices = vertices.size();
  // First organize the data

  std::set<SPoint3> unique;
  unique.insert(vertices.begin(), vertices.end());

  num_vertices = unique.size();
  fullMatrix<double> data(3, num_vertices);

  fullVector<double> mean(3);
  fullVector<double> vmins(3);
  fullVector<double> vmaxs(3);

  mean.setAll(0);
  vmins.setAll(DBL_MAX);
  vmaxs.setAll(-DBL_MAX);

  size_t idx = 0;
  for(std::set<SPoint3>::iterator uIter = unique.begin(); uIter != unique.end();
      ++uIter) {
    const SPoint3 &pp = *uIter;
    for(int d = 0; d < 3; d++) {
      data(d, idx) = pp[d];
      vmins(d) = std::min(vmins(d), pp[d]);
      vmaxs(d) = std::max(vmaxs(d), pp[d]);
      mean(d) += pp[d];
    }
    idx++;
  }

  for(int i = 0; i < 3; i++) { mean(i) /= num_vertices; }

  // Get the deviation from the mean
  fullMatrix<double> B(3, num_vertices);
  for(int i = 0; i < 3; i++) {
    for(int j = 0; j < num_vertices; j++) { B(i, j) = data(i, j) - mean(i); }
  }

  // Compute the covariance matrix
  fullMatrix<double> covariance(3, 3);
  B.mult(B.transpose(), covariance);
  covariance.scale(1. / (num_vertices - 1));
  /*
  Msg::Debug("Covariance matrix");
  Msg::Debug("%f %f %f", covariance(0,0),covariance(0,1),covariance(0,2) );
  Msg::Debug("%f %f %f", covariance(1,0),covariance(1,1),covariance(1,2) );
  Msg::Debug("%f %f %f", covariance(2,0),covariance(2,1),covariance(2,2) );
  */
  for(int i = 0; i < 3; i++) {
    for(int j = 0; j < 3; j++) {
      if(std::abs(covariance(i, j)) < 10e-16) covariance(i, j) = 0;
    }
  }

  fullMatrix<double> left_eigv(3, 3);
  fullMatrix<double> right_eigv(3, 3);
  fullVector<double> real_eig(3);
  fullVector<double> img_eig(3);
  covariance.eig(real_eig, img_eig, left_eigv, right_eigv, true);

  // Now, project the data in the new basis.
  fullMatrix<double> projected(3, num_vertices);
  left_eigv.transpose().mult(data, projected);
  // Get the size of the box in the new direction
  fullVector<double> mins(3);
  fullVector<double> maxs(3);
  for(int i = 0; i < 3; i++) {
    mins(i) = DBL_MAX;
    maxs(i) = -DBL_MAX;
    for(int j = 0; j < num_vertices; j++) {
      maxs(i) = std::max(maxs(i), projected(i, j));
      mins(i) = std::min(mins(i), projected(i, j));
    }
  }

  // double means[3];
  double sizes[3];

  // Note:  the size is computed in the box's coordinates!
  for(int i = 0; i < 3; i++) {
    sizes[i] = maxs(i) - mins(i);
    // means[i] = (maxs(i) - mins(i)) / 2.;
  }

  if(sizes[0] == 0 && sizes[1] == 0) {
    // Entity is a straight line...
    SVector3 center;
    SVector3 Axis1;
    SVector3 Axis2;
    SVector3 Axis3;

    Axis1[0] = left_eigv(0, 0);
    Axis1[1] = left_eigv(1, 0);
    Axis1[2] = left_eigv(2, 0);
    Axis2[0] = left_eigv(0, 1);
    Axis2[1] = left_eigv(1, 1);
    Axis2[2] = left_eigv(2, 1);
    Axis3[0] = left_eigv(0, 2);
    Axis3[1] = left_eigv(1, 2);
    Axis3[2] = left_eigv(2, 2);

    center[0] = (vmaxs(0) + vmins(0)) / 2.0;
    center[1] = (vmaxs(1) + vmins(1)) / 2.0;
    center[2] = (vmaxs(2) + vmins(2)) / 2.0;

    return new SOrientedBoundingBox(center, sizes[0], sizes[1], sizes[2], Axis1,
                                    Axis2, Axis3);
  }

  // We take the smallest component, then project the data on the plane defined
  // by the other twos

  int smallest_comp = 0;
  if(sizes[0] <= sizes[1] && sizes[0] <= sizes[2])
    smallest_comp = 0;
  else if(sizes[1] <= sizes[0] && sizes[1] <= sizes[2])
    smallest_comp = 1;
  else if(sizes[2] <= sizes[0] && sizes[2] <= sizes[1])
    smallest_comp = 2;

  // The projection has been done circa line 161.
  // We just ignore the coordinate corresponding to smallest_comp.
  std::vector<SPoint2 *> points;
  for(int i = 0; i < num_vertices; i++) {
    SPoint2 *p = new SPoint2(projected(smallest_comp == 0 ? 1 : 0, i),
                             projected(smallest_comp == 2 ? 1 : 2, i));
    bool keep = true;
    for(std::vector<SPoint2 *>::iterator point = points.begin();
        point != points.end(); point++) {
      if(std::abs((*p)[0] - (**point)[0]) < 10e-10 &&
         std::abs((*p)[1] - (**point)[1]) < 10e-10) {
        keep = false;
        break;
      }
    }
    if(keep) { points.push_back(p); }
    else {
      delete p;
    }
  }

  // Find the convex hull from a delaunay triangulation of the points
  DocRecord record(points.size());
  record.numPoints = points.size();
  srand((unsigned)time(0));
  for(std::size_t i = 0; i < points.size(); i++) {
    record.points[i].where.h =
      points[i]->x() + (10e-6) * sizes[smallest_comp == 0 ? 1 : 0] *
                         (-0.5 + ((double)rand()) / RAND_MAX);
    record.points[i].where.v =
      points[i]->y() + (10e-6) * sizes[smallest_comp == 2 ? 1 : 0] *
                         (-0.5 + ((double)rand()) / RAND_MAX);
    record.points[i].adjacent = NULL;
  }

  try {
    record.MakeMeshWithPoints();
  } catch(const char *err) {
    Msg::Error("%s", err);
  }

  std::vector<Segment> convex_hull;
  for(int i = 0; i < record.numTriangles; i++) {
    Segment segs[3];
    segs[0].from = record.triangles[i].a;
    segs[0].to = record.triangles[i].b;
    segs[1].from = record.triangles[i].b;
    segs[1].to = record.triangles[i].c;
    segs[2].from = record.triangles[i].c;
    segs[2].to = record.triangles[i].a;

    for(int j = 0; j < 3; j++) {
      bool okay = true;
      for(std::vector<Segment>::iterator seg = convex_hull.begin();
          seg != convex_hull.end(); seg++) {
        if(((*seg).from == segs[j].from && (*seg).from == segs[j].to)
           // FIXME:
           // || ((*seg).from == segs[j].to && (*seg).from == segs[j].from)
        ) {
          convex_hull.erase(seg);
          okay = false;
          break;
        }
      }
      if(okay) { convex_hull.push_back(segs[j]); }
    }
  }

  // Now, examinate all the directions given by the edges of the convex hull
  // to find the one that lets us build the least-area bounding rectangle for
  // then points.
  fullVector<double> axis(2);
  axis(0) = 1;
  axis(1) = 0;
  fullVector<double> axis2(2);
  axis2(0) = 0;
  axis2(1) = 1;
  SOrientedBoundingRectangle least_rectangle;
  least_rectangle.center[0] = 0.0;
  least_rectangle.center[1] = 0.0;
  least_rectangle.size[0] = -1.0;
  least_rectangle.size[1] = 1.0;

  fullVector<double> segment(2);
  fullMatrix<double> rotation(2, 2);

  for(std::vector<Segment>::iterator seg = convex_hull.begin();
      seg != convex_hull.end(); seg++) {
    // segment(0) = record.points[(*seg).from].where.h -
    // record.points[(*seg).to].where.h;  segment(1) =
    // record.points[(*seg).from].where.v - record.points[(*seg).to].where.v;
    segment(0) = points[(*seg).from]->x() - points[(*seg).to]->x();
    segment(1) = points[(*seg).from]->y() - points[(*seg).to]->y();
    segment.scale(1.0 / segment.norm());

    double cosine = axis(0) * segment(0) + segment(1) * axis(1);
    double sine = axis(1) * segment(0) - segment(1) * axis(0);
    // double sine = axis(0)*segment(1) - segment(0)*axis(1);

    rotation(0, 0) = cosine;
    rotation(0, 1) = sine;
    rotation(1, 0) = -sine;
    rotation(1, 1) = cosine;

    // TODO C++11 std::numeric_limits<double>
    double max_x = -DBL_MAX;
    double min_x = DBL_MAX;
    double max_y = -DBL_MAX;
    double min_y = DBL_MAX;

    for(int i = 0; i < record.numPoints; i++) {
      fullVector<double> pnt(2);
      // pnt(0) = record.points[i].where.h;
      // pnt(1) = record.points[i].where.v;
      pnt(0) = points[i]->x();
      pnt(1) = points[i]->y();

      fullVector<double> rot_pnt(2);
      rotation.mult(pnt, rot_pnt);

      if(rot_pnt(0) < min_x) min_x = rot_pnt(0);
      if(rot_pnt(0) > max_x) max_x = rot_pnt(0);
      if(rot_pnt(1) < min_y) min_y = rot_pnt(1);
      if(rot_pnt(1) > max_y) max_y = rot_pnt(1);
    }

    /**/
    fullVector<double> center_rot(2);
    fullVector<double> center_before_rot(2);
    center_before_rot(0) = (max_x + min_x) / 2.0;
    center_before_rot(1) = (max_y + min_y) / 2.0;
    fullMatrix<double> rotation_inv(2, 2);

    rotation_inv(0, 0) = cosine;
    rotation_inv(0, 1) = -sine;
    rotation_inv(1, 0) = sine;
    rotation_inv(1, 1) = cosine;

    rotation_inv.mult(center_before_rot, center_rot);

    fullVector<double> axis_rot1(2);
    fullVector<double> axis_rot2(2);

    rotation_inv.mult(axis, axis_rot1);
    rotation_inv.mult(axis2, axis_rot2);

    if((least_rectangle.area() == -1) ||
       (max_x - min_x) * (max_y - min_y) < least_rectangle.area()) {
      least_rectangle.size[0] = max_x - min_x;
      least_rectangle.size[1] = max_y - min_y;
      least_rectangle.center[0] = (max_x + min_x) / 2.0;
      least_rectangle.center[1] = (max_y + min_y) / 2.0;
      least_rectangle.center[0] = center_rot(0);
      least_rectangle.center[1] = center_rot(1);
      least_rectangle.axisX[0] = axis_rot1(0);
      least_rectangle.axisX[1] = axis_rot1(1);
      //      least_rectangle.axisX[0] = segment(0);
      //      least_rectangle.axisX[1] = segment(1);
      least_rectangle.axisY[0] = axis_rot2(0);
      least_rectangle.axisY[1] = axis_rot2(1);
    }
  }
  // TODO C++11 std::numeric_limits<double>::min() / max()
  double min_pca = DBL_MAX;
  double max_pca = -DBL_MAX;
  for(int i = 0; i < num_vertices; i++) {
    min_pca = std::min(min_pca, projected(smallest_comp, i));
    max_pca = std::max(max_pca, projected(smallest_comp, i));
  }
  double center_pca = (max_pca + min_pca) / 2.0;
  double size_pca = (max_pca - min_pca);

  double raw_data[3][5];
  raw_data[0][0] = size_pca;
  raw_data[1][0] = least_rectangle.size[0];
  raw_data[2][0] = least_rectangle.size[1];

  raw_data[0][1] = center_pca;
  raw_data[1][1] = least_rectangle.center[0];
  raw_data[2][1] = least_rectangle.center[1];

  for(int i = 0; i < 3; i++) {
    raw_data[0][2 + i] = left_eigv(i, smallest_comp);
    raw_data[1][2 + i] =
      least_rectangle.axisX[0] * left_eigv(i, smallest_comp == 0 ? 1 : 0) +
      least_rectangle.axisX[1] * left_eigv(i, smallest_comp == 2 ? 1 : 2);
    raw_data[2][2 + i] =
      least_rectangle.axisY[0] * left_eigv(i, smallest_comp == 0 ? 1 : 0) +
      least_rectangle.axisY[1] * left_eigv(i, smallest_comp == 2 ? 1 : 2);
  }
  // Msg::Info("Test 1 : %f
  // %f",least_rectangle.center[0],least_rectangle.center[1]);
  // Msg::Info("Test 2 : %f
  // %f",least_rectangle.axisY[0],least_rectangle.axisY[1]);

  int tri[3];

  if(size_pca > least_rectangle.size[0]) {
    // P > R0
    if(size_pca > least_rectangle.size[1]) {
      // P > R1
      tri[0] = 0;
      if(least_rectangle.size[0] > least_rectangle.size[1]) {
        // R0 > R1
        tri[1] = 1;
        tri[2] = 2;
      }
      else {
        // R1 > R0
        tri[1] = 2;
        tri[2] = 1;
      }
    }
    else {
      // P < R1
      tri[0] = 2;
      tri[1] = 0;
      tri[2] = 1;
    }
  }
  else { // P < R0
    if(size_pca < least_rectangle.size[1]) {
      // P < R1
      tri[2] = 0;
      if(least_rectangle.size[0] > least_rectangle.size[1]) {
        tri[0] = 1;
        tri[1] = 2;
      }
      else {
        tri[0] = 2;
        tri[1] = 1;
      }
    }
    else {
      tri[0] = 1;
      tri[1] = 0;
      tri[2] = 2;
    }
  }

  SVector3 size;
  SVector3 center;
  SVector3 Axis1;
  SVector3 Axis2;
  SVector3 Axis3;

  for(int i = 0; i < 3; i++) {
    size[i] = raw_data[tri[i]][0];
    center[i] = raw_data[tri[i]][1];
    Axis1[i] = raw_data[tri[0]][2 + i];
    Axis2[i] = raw_data[tri[1]][2 + i];
    Axis3[i] = raw_data[tri[2]][2 + i];
  }

  SVector3 aux1;
  SVector3 aux2;
  SVector3 aux3;
  for(int i = 0; i < 3; i++) {
    aux1(i) = left_eigv(i, smallest_comp);
    aux2(i) = left_eigv(i, smallest_comp == 0 ? 1 : 0);
    aux3(i) = left_eigv(i, smallest_comp == 2 ? 1 : 2);
  }
  center = aux1 * center_pca + aux2 * least_rectangle.center[0] +
           aux3 * least_rectangle.center[1];
  // center[1] = -center[1];

  /*
  Msg::Info("Box center : %f %f %f",center[0],center[1],center[2]);
  Msg::Info("Box size : %f %f %f",size[0],size[1],size[2]);
  Msg::Info("Box axis 1 : %f %f %f",Axis1[0],Axis1[1],Axis1[2]);
  Msg::Info("Box axis 2 : %f %f %f",Axis2[0],Axis2[1],Axis2[2]);
  Msg::Info("Box axis 3 : %f %f %f",Axis3[0],Axis3[1],Axis3[2]);

  Msg::Info("Volume : %f", size[0]*size[1]*size[2]);
  */

  return new SOrientedBoundingBox(center, size[0], size[1], size[2], Axis1,
                                  Axis2, Axis3);
#else
  Msg::Error("SOrientedBoundingBox requires mesh module");
  return 0;
#endif
}