Exemple #1
0
SbMatrix tgf::MatrixFromTransform( const Transform& transform )
{
	Ptr<Matrix4x4> transformMatrix = transform.GetMatrix()->Transpose();
	float m00 = float ( transformMatrix->m[0][0] );
	float m01 = float ( transformMatrix->m[0][1] );
	float m02 = float ( transformMatrix->m[0][2] );
	float m03 = float ( transformMatrix->m[0][3] );
	float m10 = float ( transformMatrix->m[1][0] );
	float m11 = float ( transformMatrix->m[1][1] );
	float m12 = float ( transformMatrix->m[1][2] );
	float m13 = float ( transformMatrix->m[1][3] );
	float m20 = float ( transformMatrix->m[2][0] );
	float m21 = float ( transformMatrix->m[2][1] );
	float m22 = float ( transformMatrix->m[2][2] );
	float m23 = float ( transformMatrix->m[2][3] );
	float m30 = float ( transformMatrix->m[3][0] );
	float m31 = float ( transformMatrix->m[3][1] );
	float m32 = float ( transformMatrix->m[3][2] );
	float m33 = float ( transformMatrix->m[3][3] );

	SbVec3f axis1( m00, m10, m20 );
	SbVec3f axis2( m01, m11, m21 );
	//axis2.normalize();

	SbVec3f axis3( m02, m12, m22 );
	//axis3.normalize();

	return SbMatrix( axis1[0], axis2[0], axis3[0], m03,
			axis1[1], axis2[1], axis3[1], m13,
			axis1[2], axis2[2], axis3[2], m23,
			m30, m31, m32, m33 );

}
bool IfcGeom::convert(const Ifc2x3::IfcCartesianTransformationOperator3DnonUniform::ptr l, gp_GTrsf& gtrsf) {
	IN_CACHE(IfcCartesianTransformationOperator3DnonUniform,l,gp_GTrsf,gtrsf)
	gp_Trsf trsf;
	gp_Pnt origin;
	IfcGeom::convert(l->LocalOrigin(),origin);
	gp_Dir axis1 (1.,0.,0.);
	gp_Dir axis2 (0.,1.,0.);
	gp_Dir axis3;
	if ( l->hasAxis1() ) IfcGeom::convert(l->Axis1(),axis1);
	if ( l->hasAxis2() ) IfcGeom::convert(l->Axis2(),axis2);
	if ( l->hasAxis3() ) IfcGeom::convert(l->Axis3(),axis3);
	else axis3 = axis1.Crossed(axis2);
	gp_Ax3 ax3 (origin,axis3,axis1);
	if ( axis2.Dot(ax3.YDirection()) < 0 ) ax3.YReverse();
	trsf.SetTransformation(ax3);
	trsf.Invert();
	const double scale1 = l->hasScale() ? l->Scale() : 1.0f;
	const double scale2 = l->hasScale2() ? l->Scale2() : scale1;
	const double scale3 = l->hasScale3() ? l->Scale3() : scale1;
	gtrsf = gp_GTrsf();
	gtrsf.SetValue(1,1,scale1);
	gtrsf.SetValue(2,2,scale2);
	gtrsf.SetValue(3,3,scale3);
	gtrsf.PreMultiply(trsf);
	CACHE(IfcCartesianTransformationOperator3DnonUniform,l,gtrsf)
	return true;
}
// Called when the user moves the mouse in the main window
// while a button is held down
void Cmesh_mesh_collisionsApp::scroll(CPoint p, int left_button) {

    // If the user hasn't clicked on any objects, we don't
    // have to move or rotate anyone
    if (selected_object == 0) return;

    cGenericObject* object_to_move = selected_object;

    // If the left button is being held down, rotate the
    // selected object
    if (left_button) {

        cVector3d axis1(-1,0,0);
        object_to_move->rotate(axis1,-1.0*(float)p.y / 50.0);

        cVector3d axis2(0,1,0);
        object_to_move->rotate(axis2,(float)p.x / 50.0);

    }

    // If the left button is being held down, move the
    // selected object
    else {

        object_to_move->translate((float)p.x / 100.0, 0, 0);
        object_to_move->translate(0, -1.0*(float)p.y / 100.0, 0);

    }

    // Let the object re-compute his global position data
    object->computeGlobalPositions();
    object->computeBoundaryBox(true);

}
Exemple #4
0
ImplicitFuncCSG::ImplicitFuncCSG(const BBox<scalar,3>& bb,OP_TYPE op):_alpha(0.8f),_op(op)
{
    BBox<scalar,2> bb2(bb._minC.block(0,0,2,1),bb._maxC.block(0,0,2,1));
    boost::shared_ptr<ImplicitFuncCSG> axis01(new ImplicitFuncCSG(bb2,op));
    boost::shared_ptr<ImplicitFuncCSG> axis2(new ImplicitFuncCSG(op));
    if(op == INTERSECT) {
        axis2->_a.reset(new ImplicitFuncPlane(Vec3(0.0f,0.0f,bb._minC.z()),Vec3(0.0f,0.0f,-1.0f)));
        axis2->_b.reset(new ImplicitFuncPlane(Vec3(0.0f,0.0f,bb._maxC.z()),Vec3(0.0f,0.0f, 1.0f)));
    } else {
        axis2->_a.reset(new ImplicitFuncPlane(Vec3(0.0f,0.0f,bb._minC.z()),Vec3(0.0f,0.0f, 1.0f)));
        axis2->_b.reset(new ImplicitFuncPlane(Vec3(0.0f,0.0f,bb._maxC.z()),Vec3(0.0f,0.0f,-1.0f)));
    }
    _a=axis01;
    _b=axis2;
}
Exemple #5
0
// Called when the user moves the mouse in the main window
// while a button is held down
void Crecord_playerApp::scroll(CPoint p, int left_button) {

  // For now, we're going to disable mouse interaction in
  // this example to simplify the interaction between
  // the haptic device and the record player...
  return;

  // If the user hasn't clicked on any objects, we don't
  // have to move or rotate anyone
  //if (selected_object == 0) return;

  cGenericObject* object_to_move = selected_object;

  // If the left button is being held down, rotate the
  // selected object
  if (left_button) {

        m_recordMesh->translate(cMul(-0.04, m_recordMesh->getRot().getCol2()));
    cVector3d axis1(-1,0,0);
    object->rotate(axis1,-1.0*(float)p.y / 50.0);
        m_recordMesh->rotate(axis1,-1.0*(float)p.y / 50.0);
  
    cVector3d axis2(0,1,0);
    object->rotate(axis2,(float)p.x / 50.0);
        m_recordMesh->rotate(axis2,(float)p.x / 50.0);
        m_recordMesh->translate(cMul(0.04, m_recordMesh->getRot().getCol2()));
  }

  // If the left button is being held down, move the
  // selected object
  else {

    object->translate(0, 0, -1.0*(float)p.y / 100.0);
        m_recordMesh->translate(0, 0, -1.0*(float)p.y / 100.0);
    object->translate(0, 1.0*(float)p.x / 100.0, 0);
        m_recordMesh->translate(0, 1.0*(float)p.x / 100.0, 0);

  }

  // Let the object re-compute his global position data
  object->computeGlobalPositions();
    m_recordMesh->computeGlobalPositions();
  object->computeBoundaryBox(true);  
  
}
Exemple #6
0
void mouseMove(int x, int y)
{
    if (buttonDown == -1) return;

    int dx = x - lastX;
    int dy = y - lastY;

    lastX = x;
    lastY = y;
   
    if (buttonDown == GLUT_LEFT_BUTTON)
    {
        // rotate the model

        // These vectors come from the (unusual) definition of the CHAI
        // camera's rotation matrix:
        //
        // column 0: look
        // column 2: up
        // column 1: look x up

        // Rotation around the horizontal camera axis
        cVector3d axis1(0,1,0);
        camera->getRot().mul(axis1);
        object->rotate(axis1,1.0*(float)dy / 50.0);

        // Rotation around the vertical camera axis
        cVector3d axis2(0,0,1);
        camera->getRot().mul(axis2);
        object->rotate(axis2,(float)dx / 50.0);

        object->computeGlobalPositions(true);
    }
    else
    {
        // move the model
        cVector3d translation_vector = 
          (-1.0*(float)dy / 100.0) * camera->getUpVector() +
          ( 1.0*(float)dx / 100.0) * camera->getRightVector();
        object->translate(translation_vector);

        object->computeGlobalPositions(true);
    }
}
bool IfcGeom::convert(const Ifc2x3::IfcCartesianTransformationOperator3D::ptr l, gp_Trsf& trsf) {
	IN_CACHE(IfcCartesianTransformationOperator3D,l,gp_Trsf,trsf)
	gp_Pnt origin;
	IfcGeom::convert(l->LocalOrigin(),origin);
	gp_Dir axis1 (1.,0.,0.);
	gp_Dir axis2 (0.,1.,0.);
	gp_Dir axis3;
	if ( l->hasAxis1() ) IfcGeom::convert(l->Axis1(),axis1);
	if ( l->hasAxis2() ) IfcGeom::convert(l->Axis2(),axis2);
	if ( l->hasAxis3() ) IfcGeom::convert(l->Axis3(),axis3);
	else axis3 = axis1.Crossed(axis2);
	gp_Ax3 ax3 (origin,axis3,axis1);
	if ( axis2.Dot(ax3.YDirection()) < 0 ) ax3.YReverse();
	trsf.SetTransformation(ax3);
	trsf.Invert();
	if ( l->hasScale() ) trsf.SetScaleFactor(l->Scale());
	CACHE(IfcCartesianTransformationOperator3D,l,trsf)
	return true;
}
  shared_ptr<coil::RenderObj>
  LOscillatingPlate::getCoilRenderObj() const
  {
    const double lengthRescale = 1 / Sim->primaryCellSize.maxElement();

    if (!_renderObj)
      {
	Vector axis3 = nhat / nhat.nrm();
	Vector axis2(0,0,1);
      
	for (size_t i(0); i < NDIM; ++i)
	  {
	    Vector tryaxis = Vector(0,0,0);
	    tryaxis[i] = 1;
	    Vector tryaxis2 = axis3 ^ tryaxis;
	  
	    if (tryaxis2.nrm() != 0) { axis2 = tryaxis2 / tryaxis2.nrm(); break; }
	  }

	Vector axis1 = axis2 ^ axis3;

	std::ostringstream os;
	os << axis3[0] << ", "
	   << axis3[1] << ", "
	   << axis3[2] << ", 0";

	axis1 *= Sim->primaryCellSize[1] * lengthRescale / axis1.nrm();
	axis2 *= Sim->primaryCellSize[2] * lengthRescale / axis2.nrm();

	_renderObj.reset(new coil::RFunction(10, 
					     rw0 - 0.5 * (axis1 + axis2), 
					     axis1, axis2, axis3,
					     0, 0, 1, 1, true, false,
					     "Oscillating wall",
					     "f = A;",
					     "normal = -(float4)(" + os.str() + ");"
					     ));
      }
  
    return std::tr1::static_pointer_cast<coil::RenderObj>(_renderObj);
  }
Exemple #9
0
	void Transformable::setTransformOrientation(Vector3D axis,float angle)
	{
		axis.normalize();
		float c = std::cos(angle);
		float s = std::sin(angle);
		float a = 1 - c;
		Vector3D axis2(axis.x * axis.x,axis.y * axis.y,axis.z * axis.z);

		local[0] = axis2.x + (1 - axis2.x) * c;
		local[1] = axis.x * axis.y * a + axis.z * s;
		local[2] = axis.x * axis.z * a - axis.y * s;
		local[4] = axis.x * axis.y * a - axis.z * s;
		local[5] = axis2.y + (1 - axis2.y) * c;
		local[6] = axis.y * axis.z * a + axis.x * s;
		local[8] = axis.x * axis.z * a + axis.y * s;
		local[9] = axis.y * axis.z * a - axis.x * s;
		local[10] = axis2.z + (1 - axis2.z) * c;

		localIdentity = false;
		notifyForUpdate();
	}
//----------------------------------------------------------------------------
void RoughPlaneSolidBox::MoveBox ()
{
    float x = (float)mModule.GetX();
    float w = (float)mModule.GetW();
    float xExt = (float)mModule.XLocExt;
    float yExt = (float)mModule.YLocExt;
    float zExt = (float)mModule.ZLocExt;
    float sinPhi = (float)mModule.SinAngle;
    float cosPhi = (float)mModule.CosAngle;
    float theta = (float)mModule.GetTheta();
    float sinTheta = Mathf::Sin(theta);
    float cosTheta = Mathf::Cos(theta);

    // Compute the box center.
    APoint center(x, w*cosPhi - zExt*sinPhi, w*sinPhi + zExt*cosPhi);

    // Compute the box orientation.
    AVector axis0(cosTheta, -sinTheta*cosPhi, -sinTheta*sinPhi);
    AVector axis1(sinTheta, +cosTheta*cosPhi, +cosTheta*sinPhi);
    AVector axis2(0.0f, -sinPhi, cosPhi);

    // Keep the box from sliding below the ground.
    float zRadius =
        xExt*Mathf::FAbs(axis0.Z()) +
        yExt*Mathf::FAbs(axis1.Z()) +
        zExt*Mathf::FAbs(axis2.Z());

    if (center.Z() >= zRadius)
    {
        // Update the box.
        mBox->LocalTransform.SetTranslate(center);
        mBox->LocalTransform.SetRotate(HMatrix(axis0, axis1, axis2,
            APoint::ORIGIN, true));
        mBox->Update();
    }
    else
    {
        mDoUpdate = false;
    }
}
Exemple #11
0
/**
 * Load a single entry into a workspace
 * @param root :: The opened root node
 * @param entry_name :: The entry name
 * @param progressStart :: The percentage value to start the progress reporting for this entry
 * @param progressRange :: The percentage range that the progress reporting should cover
 * @returns A 2D workspace containing the loaded data
 */
API::Workspace_sptr LoadNexusProcessed::loadEntry(NXRoot & root, const std::string & entry_name,
    const double& progressStart, const double& progressRange)
{
  progress(progressStart,"Opening entry " + entry_name + "...");

  NXEntry mtd_entry = root.openEntry(entry_name);

  if (mtd_entry.containsGroup("table_workspace"))
  {
    return loadTableEntry(mtd_entry);
  }  

  bool isEvent = false;
  std::string group_name = "workspace";
  if (mtd_entry.containsGroup("event_workspace"))
  {
    isEvent = true;
    group_name = "event_workspace";
  }

  // Get workspace characteristics
  NXData wksp_cls = mtd_entry.openNXData(group_name);

  // Axis information
  // "X" axis
  NXDouble xbins = wksp_cls.openNXDouble("axis1");
  xbins.load();
  std::string unit1 = xbins.attributes("units");
  // Non-uniform x bins get saved as a 2D 'axis1' dataset
  int xlength(-1);
  if( xbins.rank() == 2 )
  {
    xlength = xbins.dim1();
    m_shared_bins = false;
  }
  else if( xbins.rank() == 1 )
  {
    xlength = xbins.dim0();
    m_shared_bins = true;
    xbins.load();
    m_xbins.access().assign(xbins(), xbins() + xlength);
  }
  else
  {
    throw std::runtime_error("Unknown axis1 dimension encountered.");
  }

  // MatrixWorkspace axis 1
  NXDouble axis2 = wksp_cls.openNXDouble("axis2");
  std::string unit2 = axis2.attributes("units");

  // The workspace being worked on
  API::MatrixWorkspace_sptr local_workspace;
  size_t nspectra;
  int64_t nchannels;

  // -------- Process as event ? --------------------
  if (isEvent)
  {
    local_workspace = loadEventEntry(wksp_cls, xbins, progressStart, progressRange);
    nspectra = local_workspace->getNumberHistograms();
    nchannels = local_workspace->blocksize();
  }
  else
  {
    NXDataSetTyped<double> data = wksp_cls.openDoubleData();
    nspectra = data.dim0();
    nchannels = data.dim1();
    //// validate the optional spectrum parameters, if set
    checkOptionalProperties(nspectra);
    // Actual number of spectra in output workspace (if only a range was going to be loaded)
    int total_specs=calculateWorkspacesize(nspectra);

    //// Create the 2D workspace for the output
    local_workspace = boost::dynamic_pointer_cast<API::MatrixWorkspace>
    (WorkspaceFactory::Instance().create("Workspace2D", total_specs, xlength, nchannels));
    try
    {
      local_workspace->setTitle(mtd_entry.getString("title"));
    }
    catch (std::runtime_error&)
    {
      g_log.debug() << "No title was found in the input file, " << getPropertyValue("Filename") << std::endl;
    }

    // Set the YUnit label
    local_workspace->setYUnit(data.attributes("units"));
    std::string unitLabel = data.attributes("unit_label");
    if (unitLabel.empty()) unitLabel = data.attributes("units");
    local_workspace->setYUnitLabel(unitLabel);
    
    readBinMasking(wksp_cls, local_workspace);
    NXDataSetTyped<double> errors = wksp_cls.openNXDouble("errors");

    int64_t blocksize(8);
    //const int fullblocks = nspectra / blocksize;
    //size of the workspace
    int64_t fullblocks = total_specs / blocksize;
    int64_t read_stop = (fullblocks * blocksize);
    const double progressBegin = progressStart+0.25*progressRange;
    const double progressScaler = 0.75*progressRange;
    int64_t hist_index = 0;
    int64_t wsIndex=0;
    if( m_shared_bins )
    {
      //if spectrum min,max,list properties are set
      if(m_interval||m_list)
      {
        //if spectrum max,min properties are set read the data as a block(multiple of 8) and
        //then read the remaining data as finalblock
        if(m_interval)
        {
          //specs at the min-max interval
          int interval_specs=static_cast<int>(m_spec_max-m_spec_min);
          fullblocks=(interval_specs)/blocksize;
          read_stop = (fullblocks * blocksize)+m_spec_min-1;

          if(interval_specs<blocksize)
          {
            blocksize=total_specs;
            read_stop=m_spec_max-1;
          }
          hist_index=m_spec_min-1;

          for( ; hist_index < read_stop; )
          {
            progress(progressBegin+progressScaler*static_cast<double>(hist_index)/static_cast<double>(read_stop),"Reading workspace data...");
            loadBlock(data, errors, blocksize, nchannels, hist_index,wsIndex, local_workspace);
          }
          int64_t finalblock = m_spec_max-1 - read_stop;
          if( finalblock > 0 )
          {
            loadBlock(data, errors, finalblock, nchannels, hist_index,wsIndex,local_workspace);
          }
        }
        // if spectrum list property is set read each spectrum separately by setting blocksize=1
        if(m_list)
        {
          std::vector<int64_t>::iterator itr=m_spec_list.begin();
          for(;itr!=m_spec_list.end();++itr)
          {
            int64_t specIndex=(*itr)-1;
            progress(progressBegin+progressScaler*static_cast<double>(specIndex)/static_cast<double>(m_spec_list.size()),"Reading workspace data...");
            loadBlock(data, errors, static_cast<int64_t>(1), nchannels, specIndex,wsIndex, local_workspace);
          }

        }
      }
      else
      {
        for( ; hist_index < read_stop; )
        {
          progress(progressBegin+progressScaler*static_cast<double>(hist_index)/static_cast<double>(read_stop),"Reading workspace data...");
          loadBlock(data, errors, blocksize, nchannels, hist_index,wsIndex, local_workspace);
        }
        int64_t finalblock = total_specs - read_stop;
        if( finalblock > 0 )
        {
          loadBlock(data, errors, finalblock, nchannels, hist_index,wsIndex,local_workspace);
        }
      }

    }
    else
    {
      if(m_interval||m_list)
      {
        if(m_interval)
        {
          int64_t interval_specs=m_spec_max-m_spec_min;
          fullblocks=(interval_specs)/blocksize;
          read_stop = (fullblocks * blocksize)+m_spec_min-1;

          if(interval_specs<blocksize)
          {
            blocksize=interval_specs;
            read_stop=m_spec_max-1;
          }
          hist_index=m_spec_min-1;

          for( ; hist_index < read_stop; )
          {
            progress(progressBegin+progressScaler*static_cast<double>(hist_index)/static_cast<double>(read_stop),"Reading workspace data...");
            loadBlock(data, errors, xbins, blocksize, nchannels, hist_index,wsIndex,local_workspace);
          }
          int64_t finalblock = m_spec_max-1 - read_stop;
          if( finalblock > 0 )
          {
            loadBlock(data, errors, xbins, finalblock, nchannels, hist_index,wsIndex, local_workspace);
          }
        }
        //
        if(m_list)
        {
          std::vector<int64_t>::iterator itr=m_spec_list.begin();
          for(;itr!=m_spec_list.end();++itr)
          {
            int64_t specIndex=(*itr)-1;
            progress(progressBegin+progressScaler*static_cast<double>(specIndex)/static_cast<double>(read_stop),"Reading workspace data...");
            loadBlock(data, errors, xbins, 1, nchannels, specIndex,wsIndex,local_workspace);
          }

        }
      }
      else
      {
        for( ; hist_index < read_stop; )
        {
          progress(progressBegin+progressScaler*static_cast<double>(hist_index)/static_cast<double>(read_stop),"Reading workspace data...");
          loadBlock(data, errors, xbins, blocksize, nchannels, hist_index,wsIndex,local_workspace);
        }
        int64_t finalblock = total_specs - read_stop;
        if( finalblock > 0 )
        {
          loadBlock(data, errors, xbins, finalblock, nchannels, hist_index,wsIndex, local_workspace);
        }
      }
    }
  } //end of NOT an event -------------------------------



  //Units
  try
  {
    local_workspace->getAxis(0)->unit() = UnitFactory::Instance().create(unit1);
    //If this doesn't throw then it is a numeric access so grab the data so we can set it later
    axis2.load();
    m_axis1vals = MantidVec(axis2(), axis2() + axis2.dim0());
  }
  catch( std::runtime_error & )
  {
    g_log.information() << "Axis 0 set to unitless quantity \"" << unit1 << "\"\n";
  }

  // Setting a unit onto a SpectraAxis makes no sense.
  if ( unit2 == "TextAxis" )
  {
    Mantid::API::TextAxis* newAxis = new Mantid::API::TextAxis(nspectra);
    local_workspace->replaceAxis(1, newAxis);
  }
  else if ( unit2 != "spectraNumber" )
  {
    try
    {
      Mantid::API::NumericAxis* newAxis = new Mantid::API::NumericAxis(nspectra);
      local_workspace->replaceAxis(1, newAxis);
      newAxis->unit() = UnitFactory::Instance().create(unit2);
    }
    catch( std::runtime_error & )
    {
      g_log.information() << "Axis 1 set to unitless quantity \"" << unit2 << "\"\n";
    }
  }


  //Are we a distribution
  std::string dist = xbins.attributes("distribution");
  if( dist == "1" )
  {
    local_workspace->isDistribution(true);
  }
  else
  {
    local_workspace->isDistribution(false);
  }

  //Get information from all but data group
  std::string parameterStr;

  progress(progressStart+0.05*progressRange,"Reading the sample details...");

  // Hop to the right point
  cppFile->openPath(mtd_entry.path());
  try
  {
    // This loads logs, sample, and instrument.
    local_workspace->loadExperimentInfoNexus(cppFile, parameterStr);
  }
  catch (std::exception & e)
  {
    g_log.information("Error loading Instrument section of nxs file");
    g_log.information(e.what());
  }

  // Now assign the spectra-detector map
  readInstrumentGroup(mtd_entry, local_workspace);

  // Parameter map parsing
  progress(progressStart+0.11*progressRange,"Reading the parameter maps...");
  local_workspace->readParameterMap(parameterStr);


  if ( ! local_workspace->getAxis(1)->isSpectra() )
  { // If not a spectra axis, load the axis data into the workspace. (MW 25/11/10)
    loadNonSpectraAxis(local_workspace, wksp_cls);
  }

  progress(progressStart+0.15*progressRange,"Reading the workspace history...");
  try
  {
    readAlgorithmHistory(mtd_entry, local_workspace);
  }
  catch (std::out_of_range&)
  {
    g_log.warning() << "Error in the workspaces algorithm list, its processing history is incomplete\n";
  }

  progress(progressStart+0.2*progressRange,"Reading the workspace history...");

  return boost::static_pointer_cast<API::Workspace>(local_workspace);
}
Exemple #12
0
 static void __DecomposeMatrices(float *matrices, size_t count,
                                 std::vector< shared_ptr <GLTFBufferView> > &TRSBufferViews) {
     
     size_t translationBufferSize = sizeof(float) * 3 * count;
     size_t rotationBufferSize = sizeof(float) * 4 * count;
     size_t scaleBufferSize = sizeof(float) * 3 * count;
     
     float *translationData = (float*)malloc(translationBufferSize);
     float *rotationData = (float*)malloc(rotationBufferSize);
     float *scaleData = (float*)malloc(scaleBufferSize);
     
     shared_ptr <GLTF::GLTFBufferView> translationBufferView = createBufferViewWithAllocatedBuffer(translationData, 0, translationBufferSize, true);
     shared_ptr <GLTF::GLTFBufferView> rotationBufferView = createBufferViewWithAllocatedBuffer(rotationData, 0, rotationBufferSize, true);
     shared_ptr <GLTF::GLTFBufferView> scaleBufferView = createBufferViewWithAllocatedBuffer(scaleData, 0, scaleBufferSize, true);
     
     float *previousRotation = 0;
     
     for (size_t i = 0 ; i < count ; i++) {
         
         float *m = matrices;
         COLLADABU::Math::Matrix4 mat;
         mat.setAllElements(m[0], m[1], m[2], m[3],
                            m[4], m[5], m[6], m[7],
                            m[8], m[9], m[10], m[11],
                            m[12], m[13], m[14], m[15] );
         
         decomposeMatrix(mat, translationData, rotationData, scaleData);
         
         //make sure we export the short path from orientations
         if (0 != previousRotation) {
             COLLADABU::Math::Vector3 axis1(previousRotation[0], previousRotation[1], previousRotation[2]);
             COLLADABU::Math::Vector3 axis2(rotationData[0], rotationData[1], rotationData[2]);
             
             COLLADABU::Math::Quaternion key1;
             COLLADABU::Math::Quaternion key2;
             
             key1.fromAngleAxis(previousRotation[3], axis1);
             key2.fromAngleAxis(rotationData[3], axis2);
             
             COLLADABU::Math::Real cosHalfTheta = key1.dot(key2);
             if (cosHalfTheta < 0) {
                 key2.x = -key2.x;
                 key2.y = -key2.y;
                 key2.z = -key2.z;
                 key2.w = -key2.w;
                 
                 COLLADABU::Math::Real angle;
                 key2.toAngleAxis(angle, axis2);
                 rotationData[3] = (float)angle;
                 rotationData[0] = (float)axis2.x;
                 rotationData[1] = (float)axis2.y;
                 rotationData[2] = (float)axis2.z;
                 
                 key2.fromAngleAxis(rotationData[3], axis2);
                 
                 //FIXME: this needs to be refined, we ensure continuity here, but assume in clockwise order
                 cosHalfTheta = key1.dot(key2);
                 if (cosHalfTheta < 0) {
                     rotationData[3] += (float)(2. * 3.14159265359);
                     key2.fromAngleAxis(rotationData[3], axis2);
                 }
             }
             
         }
         
         previousRotation = rotationData;
         translationData += 3;
         rotationData += 4;
         scaleData += 3;
         matrices += 16;
     }
     /*
      rotationData = (float*)rotationBufferView->getBufferDataByApplyingOffset();
      for (size_t i = 0 ; i < count ; i++) {
      printf("rotation at:%d %f %f %f %f\n",  i,
      rotationData[0],rotationData[1],rotationData[2],rotationData[3]);
      
      rotationData += 4;
      }
      */
     TRSBufferViews.push_back(translationBufferView);
     TRSBufferViews.push_back(rotationBufferView);
     TRSBufferViews.push_back(scaleBufferView);
 }
Exemple #13
0
// ################################################
double NeuralNetwork::LearnGivenData(int MiniBatchSize, int epochs, int TrainingsSize, bool TestOnTrainingsData, bool TestOnTestingData, std::string SavePath){

  TCanvas c1("Accuracy", "Accuracy", 600, 500);
  TCanvas c2("Cost", "Cost", 600, 500);
  TCanvas c3("summary", "summary", 1200, 500);
  c3.SetGrid();
  c3.Divide(2);
  c1.cd();
  TH1F axis("axis", "Accuracy of Neural Network;epochs", epochs, 0.5, epochs+0.5);
  TH1F acc_test ("acc_test" , "Classification accuracy", epochs, 0.5, epochs+0.5);
  TH1F acc_train("acc_train", "Classification accuracy", epochs, 0.5, epochs+0.5);
  TH1F axis2("axis2", "Cost Function of Neural Network;epochs", epochs, 0.5, epochs+0.5);
  TH1F cost_test ("cost_test" , "Cost Function", epochs, 0.5, epochs+0.5);
  TH1F cost_train("cost_train", "Cost Function", epochs, 0.5, epochs+0.5);
  if (TrainingsSize == -1) TrainingsSize = fTrainingsSize;

  for (int k = 0; k < epochs; ++k){
    // if (k % 5 == 0) std::cout << "Epoch nr. " << k << " started!" << std::endl;
    for (int i = 0; i < TrainingsSize / MiniBatchSize; ++i){
      for (int j = 0; j < MiniBatchSize; ++j){
        SetInputVectorInMiniBatch(fTrainingsdata[i*10 + j], fTrainingslabel[i*10 + j]);
      }
      LearnMiniBatches();
    }
    if (TestOnTestingData){
      double correct = 0;
      double cost = 0;
      for (int i = 0; i < fTestingSize; ++i){
        if (Evaluate(fTestingdata[i], fTestinglabel[i]) == true) correct++;
        cost += EvaluateCost(fTestingdata[i], fTestinglabel[i]);
      }
      // std::cout << "Accuracy of test data: " << correct / fTestingSize << " %"<< std::endl;
      acc_test.SetBinContent(k+1, correct / fTestingSize);
      cost_test.SetBinContent(k+1, cost / fTestingSize);
    }
    if (TestOnTrainingsData){
      double correct = 0;
      double cost = 0;
      for (int i = 0; i < TrainingsSize; ++i){
        if (Evaluate(fTrainingsdata[i], fTrainingslabel[i]) == true) correct++;
        cost += EvaluateCost(fTrainingsdata[i], fTrainingslabel[i]);
      }
      // std::cout << "Accuracy of trainings data: " << correct / TrainingsSize << " %" << std::endl;
      acc_train.SetBinContent(k+1, correct / TrainingsSize);
      cost_train.SetBinContent(k+1, cost / fTrainingsSize);
    }
  }
  axis.SetStats(false);
  axis.GetYaxis()->SetNdivisions(524);
  axis.SetAxisRange(0.5, 1.1, "Y");
  axis.Draw("");

  double markersize = 1;
  if (epochs > 100) {
    markersize = 0.5;
    c1.SetLogx();
  }

  acc_test.SetStats(false);
  acc_test.SetMarkerStyle(20);
  acc_test.SetMarkerColor(kOrange-3);
  acc_test.SetMarkerSize(1.);
  acc_test.Draw("p same");
  acc_train.SetStats(false);
  acc_train.SetMarkerStyle(20);
  acc_train.SetMarkerColor(kAzure-2);
  acc_train.SetMarkerSize(1.);
  acc_train.Draw("p same");
  // c1.SetLogx();
  c1.SetGrid();

  // Calculate maxima
  double max_trainingsdata = acc_train.GetMaximum();
  double max_testdata      = acc_test.GetMaximum();

  TLegend leg(0.4,0.1,0.9,0.3);
  leg.SetHeader("Accuracy of");
  leg.AddEntry(&acc_test,  Form("Test data (Maximum: %4.3f)", max_testdata), "p");
  leg.AddEntry(&acc_train, Form("Trainings data (Maximum: %4.3f)", max_trainingsdata), "p");
  leg.Draw("same");

  c1.SaveAs(Form("%saccuracy.pdf", SavePath.c_str()));



  c2.cd();
  axis2.SetStats(false);
  axis2.GetYaxis()->SetNdivisions(524);
  axis2.SetAxisRange(cost_train.GetMinimum()*0.9, cost_test.GetMaximum()*1.1, "Y");
  axis2.Draw("");

  if (epochs > 100) {
    markersize = 0.5;
    c2.SetLogx();
  }

  cost_train.SetStats(false);
  cost_train.SetMarkerStyle(20);
  cost_train.SetMarkerColor(kAzure-2);
  cost_train.SetMarkerSize(1.);
  cost_train.Draw("p same");
  cost_test.SetStats(false);
  cost_test.SetMarkerStyle(20);
  cost_test.SetMarkerColor(kOrange-3);
  cost_test.SetMarkerSize(1.);
  cost_test.Draw("p same");
  // c1.SetLogx();
  c2.SetGrid();

  // Calculate maxima
  double min_trainingsdata = cost_train.GetMinimum();
  double min_testdata      = cost_test.GetMinimum();

  TLegend leg2(0.4,0.7,0.9,0.9);
  leg2.SetHeader("Cost Function");
  leg2.AddEntry(&acc_test,  Form("Test data (Minimum: %4.3f)", min_testdata), "p");
  leg2.AddEntry(&acc_train, Form("Trainings data (Minimum: %4.3f)", min_trainingsdata), "p");
  leg2.Draw("same");

  c2.SaveAs(Form("%scost.pdf", SavePath.c_str()));

  c3.cd(1);
  axis.Draw("");
  acc_test.Draw("p same");
  acc_train.Draw("p same");
  leg.Draw("same");
  c3.cd(2);
  axis2.Draw("");
  cost_test.Draw("p same");
  cost_train.Draw("p same");
  leg2.Draw("same");
  c3.SaveAs(Form("%ssummary.pdf", SavePath.c_str()));



  // std::cout << "Learning completed" << std::endl;
  return max_testdata;
}
Exemple #14
0
//---------------------------------------------------------
void Poly3D::SortPoints(const DVec& cent)
//---------------------------------------------------------
{
  // Sort the points by angle from cent which is
  // a point in the plane of the polygon.  This
  // is done in a counter-clockwise direction.

  // If less than 2 points, no need to sort
  if (m_N < 2) {
    return;
  }
  
  // create local cartesian axis
  DVec ref1,ref2,nor,axis1,axis2,vI,vJ,tmp;

  // wrap DM with DMat for utility routines
  int Nr=m_xyz.num_rows(), Nc=m_xyz.num_cols();
  DMat t_xyz; t_xyz.borrow(Nr, Nc, m_xyz.data());
  
  t_xyz.get_col(1) - cent;   ref1 /= ref1.norm(); 


  // get two lines in the plane
  ref1 = t_xyz.get_col(1) - cent;   ref1 /= ref1.norm(); 
  ref2 = t_xyz.get_col(2) - cent;   ref2 /= ref2.norm();

  // normal to the plane (norm = ref1 X ref2)
  nor(1) = ref1(2)*ref2(3) - ref1(3)*ref2(2);
  nor(2) = ref1(3)*ref2(1) - ref1(1)*ref2(3);
  nor(3) = ref1(1)*ref2(2) - ref1(2)*ref2(1);

  nor /= nor.norm();

  // axis definition
  axis1 = ref1;

  // axis2 = norm x axis1
  axis2(1) = nor(2)*axis1(3) - nor(3)*axis1(2);
  axis2(2) = nor(3)*axis1(1) - nor(1)*axis1(3);
  axis2(3) = nor(1)*axis1(2) - nor(2)*axis1(1);

  double costhetaI,sinthetaI, costhetaJ,sinthetaJ, thetaI,thetaJ;

  for (int i=1; i<=m_N; ++i) {
    for (int j=(i+1); j<=m_N; ++j) {
      vI = t_xyz.get_col(i) - cent;
      vJ = t_xyz.get_col(j) - cent;

      costhetaI = vI.inner(axis1);
      sinthetaI = vI.inner(axis2);

      costhetaJ = vJ.inner(axis1);
      sinthetaJ = vJ.inner(axis2);

      thetaI = atan2(sinthetaI, costhetaI);
      thetaJ = atan2(sinthetaJ, costhetaJ);
      
      // sort  minimum angle difference first
      if (thetaJ < thetaI) 
      {
        // swap I and J
      //t_xyz(All, [i j]) = t_xyz(All, [j i]);

        tmp = t_xyz.get_col(i);               // copy column i
        t_xyz.set_col(i, t_xyz.get_col(j));   // overwrite col i
        t_xyz.set_col(j, tmp);                // overwrite col j
      }
    }
  } 
}
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
}
bool ChunkyBoneGeometry::CreateJoint(ChunkyPhysics* structure, PhysicsManager* physics, unsigned physics_fps) {
	bool ok = false;
	if (body_data_.parent_) {
		if (GetBoneType() == kBonePosition) {
			// Need not do jack. It's not a physical object.
			ok = true;
		} else if (body_data_.joint_type_ == kJointExclude) {
			ok = physics->Attach(GetBodyId(), body_data_.parent_->GetBodyId());
		} else if (body_data_.joint_type_ == kJointFixed) {
			ok = physics->Attach(GetBodyId(), body_data_.parent_->GetBodyId());
		} else if (body_data_.joint_type_ == kJointSuspendHinge || body_data_.joint_type_ == kJointHinge2) {
			// Calculate axis from given euler angles.
			vec3 suspension_axis(-1, 0, 0);
			vec3 hinge_axis(0, 0, 1);
			quat rotator;
			rotator.SetEulerAngles(body_data_.parameter_[kParamEulerTheta], 0, body_data_.parameter_[kParamEulerPhi]);
			suspension_axis = rotator*suspension_axis;
			hinge_axis = rotator*hinge_axis;

			joint_id_ = physics->CreateHinge2Joint(body_data_.parent_->GetBodyId(),
				GetBodyId(), structure->GetTransformation(this).GetPosition(),
				suspension_axis, hinge_axis);
			physics->SetJointParams(joint_id_, body_data_.parameter_[kParamLowStop], body_data_.parameter_[kParamHighStop], 0);
			physics->SetSuspension(joint_id_, 1/(float)physics_fps, body_data_.parameter_[kParamSpringConstant],
				body_data_.parameter_[kParamSpringDamping]);
			physics->SetAngularMotorRoll(joint_id_, 0, 0);
			physics->SetAngularMotorTurn(joint_id_, 0, 0);
			ok = true;
		} else if (body_data_.joint_type_ == kJointHinge) {
			// Calculate axis from given euler angles.
			vec3 hinge_axis(0, 0, 1);
			quat hinge_rotator;
			hinge_rotator.SetEulerAngles(body_data_.parameter_[kParamEulerTheta], 0, body_data_.parameter_[kParamEulerPhi]);
			hinge_axis = hinge_rotator*hinge_axis;

			const xform& body_transform = structure->GetTransformation(this);
			const vec3 anchor = body_transform.GetPosition() + GetOriginalOffset();
			joint_id_ = physics->CreateHingeJoint(body_data_.parent_->GetBodyId(),
				GetBodyId(), anchor, hinge_axis);
			physics->SetJointParams(joint_id_, body_data_.parameter_[kParamLowStop], body_data_.parameter_[kParamHighStop], body_data_.bounce_);
			physics->SetAngularMotorTurn(joint_id_, 0, 0);
			//physics->GetAxis1(joint_id_, hinge_axis);
			ok = true;
		} else if (body_data_.joint_type_ == kJointSlider) {
			// Calculate axis from given euler angles.
			vec3 axis(0, 0, 1);
			quat rotator;
			rotator.SetEulerAngles(body_data_.parameter_[kParamEulerTheta], 0, body_data_.parameter_[kParamEulerPhi]);
			axis = rotator*axis;

			joint_id_ = physics->CreateSliderJoint(body_data_.parent_->GetBodyId(),
				GetBodyId(), axis);
			physics->SetJointParams(joint_id_, body_data_.parameter_[kParamLowStop], body_data_.parameter_[kParamHighStop], body_data_.bounce_);
			physics->SetMotorTarget(joint_id_, 0, 0);
			ok = true;
		} else if (body_data_.joint_type_ == kJointUniversal) {
			// Calculate axis from given euler angles.
			vec3 axis1(0, 0, 1);
			vec3 axis2(0, 1, 0);
			quat rotator;
			rotator.SetEulerAngles(body_data_.parameter_[kParamEulerTheta], 0, body_data_.parameter_[kParamEulerPhi]);
			axis1 = rotator*axis1;
			axis2 = rotator*axis2;

			const xform& body_transform = structure->GetTransformation(this);
			const vec3 anchor = body_transform.GetPosition() +
				vec3(body_data_.parameter_[kParamOffsetX], body_data_.parameter_[kParamOffsetY], body_data_.parameter_[kParamOffsetZ]);
			joint_id_ = physics->CreateUniversalJoint(body_data_.parent_->GetBodyId(),
				GetBodyId(), anchor, axis1, axis2);
			physics->SetJointParams(joint_id_, body_data_.parameter_[kParamLowStop], body_data_.parameter_[kParamHighStop], 0);
			/*physics->SetJointParams(joint_id_, body_data_.parameter_[kParamLowStop], body_data_.parameter_[kParamHighStop], 0);
			physics->SetSuspension(joint_id_, 1/(float)physics_fps, body_data_.parameter_[0],
				body_data_.parameter_[1]);
			physics->SetAngularMotorRoll(joint_id_, 0, 0);
			physics->SetAngularMotorTurn(joint_id_, 0, 0);*/
			ok = true;
		} else if (body_data_.joint_type_ == kJointBall) {
			const xform& body_transform = structure->GetTransformation(this);
			const vec3 anchor = body_transform.GetPosition() +
				vec3(body_data_.parameter_[kParamOffsetX], body_data_.parameter_[kParamOffsetY], body_data_.parameter_[kParamOffsetZ]);
			joint_id_ = physics->CreateBallJoint(body_data_.parent_->GetBodyId(),
				GetBodyId(), anchor);
			/*physics->SetJointParams(joint_id_, body_data_.parameter_[kParamLowStop], body_data_.parameter_[kParamHighStop], 0);
			physics->SetJointParams(joint_id_, body_data_.parameter_[kParamLowStop], body_data_.parameter_[kParamHighStop], 0);
			physics->SetSuspension(joint_id_, 1/(float)physics_fps, body_data_.parameter_[0],
				body_data_.parameter_[1]);
			physics->SetAngularMotorRoll(joint_id_, 0, 0);
			physics->SetAngularMotorTurn(joint_id_, 0, 0);*/
			ok = true;
		} else {
			deb_assert(false);
		}
	} else {
		deb_assert(body_data_.joint_type_ == kJointExclude);
		ok = true;
	}
	deb_assert(ok);
	return (ok);
}