示例#1
0
/*!
* \return	Product of the two given quaternions.
* \ingroup	HGU_GL
* \brief	Calculates and returns the product of the two given
* 		quaternions.
* \param	given1			First quaternion.
* \param	given2			Second quaternion.
*/
HGUglQuaternion	HGUglQuatProduct(HGUglQuaternion given1,
				 HGUglQuaternion given2)
{
  HGUglQuaternion prod;
  WlzDVertex3	tVtx0,
  		tVtx1,
		tVtx2;
 
  prod.qW = (given1.qW * given2.qW) - WLZ_VTX_3_DOT(given1.qV, given2.qV);
  WLZ_VTX_3_SCALE(tVtx0, given2.qV, given1.qW);
  WLZ_VTX_3_SCALE(tVtx1, given1.qV, given2.qW);
  WLZ_VTX_3_CROSS(tVtx2, given1.qV, given2.qV);
  WLZ_VTX_3_ADD3(prod.qV, tVtx0, tVtx1, tVtx2);
  return(prod);
}
示例#2
0
/*!
* \return	Coordinates of centre of mass.
* \ingroup	WlzFeatures
* \brief	Computes the centre of mass of a vector of 3D vertices.
* \param	nVtx			Number of vertices.
* \param	vtx			The vertices.
*/
WlzDVertex3	WlzCentreOfMassVtx3D(int nVtx, WlzDVertex3 *vtx)
{
  WlzDVertex3	cen;

  WLZ_VTX_3_ZERO(cen);
  if(nVtx > 0)
  {
    int		idx;

    for(idx = 0; idx < nVtx; ++idx)
    {
      WLZ_VTX_3_ADD(cen, cen, vtx[idx]);
    }
    WLZ_VTX_3_SCALE(cen, cen, 1.0 / nVtx);
  }
  return(cen);
}
示例#3
0
/*!
* \return	Calculated quaternion.
* \ingroup	HGU_GL
* \brief	Calculates a rotation quaternion (which lies on the unit
* 		sphere) using the given axis and rotation about that axis.
* \param	axis			Axis defined by vector throgh
* 					(0, 0, 0) and this vertex.
* \param	phi			Rotation about the given axis.
*/
HGUglQuaternion	HGUglQuatFromAxis(WlzDVertex3 axis, double phi)
{
  double	halfPhi,
  		axisLen,
		tD1;
  HGUglQuaternion quat;

  halfPhi = phi / 2.0;
  axisLen = WLZ_VTX_3_LENGTH(axis);
  if(axisLen > DBL_EPSILON)
  {
    quat.qW = cos(halfPhi);
    tD1 = sin(halfPhi) / axisLen;
    WLZ_VTX_3_SCALE(quat.qV, axis, tD1);
  }
  else
  {
    HGUgl_QUAT_SET4(quat, 1.0, 0.0, 0.0, 0.0);
    
  }
  return(quat);
}
示例#4
0
/*!
* \return	Woolz error code.
* \ingroup	WlzTransform
* \brief	Fits a plane to the given vertices using singular value
* 		decomposition. The best fit plane is returned (provided
* 		there is no error) as a unit normal \f$n\f$ and the
* 		centroid of the given vertices ( \f$r_0\f$ ) which in a
* 		point in the plane, with the plane equation
* 		\f[
		\vec{n}\cdot(\vec{r} - \vec{r_0}) = \vec{0}
 		\f]
* \param	vtxType			Given vertex type.
* \param	nVtx			Number of given vertices.
* \param	vtx			Given vertices.
* \param	dstPinP			Destination pointer for the return
* 					of the median point (\f$r_0\f$) in
* 					the plane.
* \param	dstNrm			Destination pointer for the unit
*   					normal to the plane (\f$n\f$).
*/
WlzErrorNum WlzFitPlaneSVD(WlzVertexType vtxType, int nVtx, WlzVertexP vtx,
			   WlzDVertex3 *dstPinP, WlzDVertex3 *dstNrm)
{
  AlgMatrix     aMat,
  		vMat;
  WlzDVertex3	centroid,
                normal;
  double	*sVec = NULL;
  AlgError	algErr = ALG_ERR_NONE;
  WlzErrorNum	errNum = WLZ_ERR_NONE;

  aMat.core = NULL;
  vMat.core = NULL;
  if(nVtx < 0)
  {
    errNum = WLZ_ERR_PARAM_DATA;
  }
  else if(vtx.v == NULL)
  {
    errNum = WLZ_ERR_PARAM_NULL;
  }
  if(errNum == WLZ_ERR_NONE)
  {
    if(((sVec = (double *)AlcCalloc(sizeof(double), 3)) == NULL) ||
       ((aMat.rect = AlgMatrixRectNew(nVtx, 3, NULL)) == NULL) ||
       ((vMat.rect = AlgMatrixRectNew(3, 3, NULL)) == NULL))
    {
      errNum = WLZ_ERR_MEM_ALLOC;
    }
  }
  /* Compute a Nx3 matrix from the given vertices then subtract their
   * centroid. */
  if(errNum == WLZ_ERR_NONE)
  {
    int		i;
    double	*row;
    
    WLZ_VTX_3_ZERO(centroid);
    switch(vtxType)
    {
      case WLZ_VERTEX_I3:
	for(i = 0; i < nVtx; ++i)
	{
	  WlzIVertex3 *v;

	  v = vtx.i3 + i;
          row = aMat.rect->array[i];
	  centroid.vtX += row[0] = v->vtX;
	  centroid.vtY += row[1] = v->vtY;
	  centroid.vtZ += row[2] = v->vtZ;
	}
	break;
      case WLZ_VERTEX_F3:
	for(i = 0; i < nVtx; ++i)
	{
	  WlzFVertex3 *v;

	  v = vtx.f3 + i;
          row = aMat.rect->array[i];
	  centroid.vtX += row[0] = v->vtX;
	  centroid.vtY += row[1] = v->vtY;
	  centroid.vtZ += row[2] = v->vtZ;
	}
	break;
      case WLZ_VERTEX_D3:
	for(i = 0; i < nVtx; ++i)
	{
	  WlzDVertex3 *v;

	  v = vtx.d3 + i;
          row = aMat.rect->array[i];
	  centroid.vtX += row[0] = v->vtX;
	  centroid.vtY += row[1] = v->vtY;
	  centroid.vtZ += row[2] = v->vtZ;
	}
	break;
      default:
	errNum = WLZ_ERR_PARAM_TYPE;
        break;
    }
    if(errNum == WLZ_ERR_NONE)
    {
      WLZ_VTX_3_SCALE(centroid, centroid, (1.0 / nVtx));
      for(i = 0; i < nVtx; ++i)
      {
	row = aMat.rect->array[i];
	row[0] -= centroid.vtX;
	row[1] -= centroid.vtY;
	row[2] -= centroid.vtZ;
      }
    }
  }
  /* Compute SVD. */
  if(errNum == WLZ_ERR_NONE)
  {
    algErr = AlgMatrixSVDecomp(aMat, sVec, vMat);
    errNum = WlzErrorFromAlg(algErr);
  }
  /* Find the vector corresponding to the least singular value. */
  if(errNum == WLZ_ERR_NONE)
  {
    int		i,
    		m;
    double	len;
    double	**ary;
    const double eps = 1.0e-06;

    m  = 0;
    for(i = 1; i < 3; ++i)
    {
      if(sVec[i] < sVec[m])
      {
        m = i;
      }
    }
    ary = vMat.rect->array;
#ifdef WLZ_FITPLANESVD_DEBUG
    (void )fprintf(stderr,
                   "WlzFitPlaneSVD() singular values = {%lg, %lg, %lg}\n",
		   sVec[0], sVec[1], sVec[2]);
    (void )fprintf(stderr,
                   "WlzFitPlaneSVD() index of min singular value = %d\n",
		   m);
    (void )fprintf(stderr,
                   "WlzFitPlaneSVD() singular vectors = \n"
		   "{\n");
    for(i = 0; i < 3; ++i)
    {
      (void )fprintf(stderr,
                     " {%lg, %lg, %lg}\n",
		     ary[i][0], ary[i][1], ary[i][2]);
    }
    (void )fprintf(stderr,
		   "}\n");
#endif /* WLZ_FITPLANESVD_DEBUG */
    normal.vtX = ary[0][m];
    normal.vtY = ary[1][m];
    normal.vtZ = ary[2][m];
    len = WLZ_VTX_3_LENGTH(normal);
    if(len < eps)
    {
      errNum = WLZ_ERR_ALG_SINGULAR;
    }
    else
    {
      WLZ_VTX_3_SCALE(normal, normal, (1.0 / len));
    }
  }
  AlgMatrixRectFree(aMat.rect);
  AlgMatrixRectFree(vMat.rect);
  AlcFree(sVec);
  if(errNum == WLZ_ERR_NONE)
  {
    if(dstNrm)
    {
      *dstNrm = normal;
    }
    if(dstPinP)
    {
      *dstPinP = centroid;
    }
  }
  return(errNum);
}
/*! input is the voxsel sip and the unit vector nStraghtline, indicating direction
    in OPT space.
    output is the *sip1p in view space!
*/
static WlzErrorNum WlzGetCorssPoint( WlzVertex sip,
                                WlzVertex nStraghtline,
                                WlzVertex *sip1p,
                                WlzThreeDViewStruct  *wlzViewStri  
				)
{
   WlzVertex    vtemp, vtemp0, vo, vso, vtx1;
   WlzVertex    vs1, nI;
   double       dtemp, dtemp1, dtemp2;
   WlzErrorNum	errNum = WLZ_ERR_NONE;
  

   /* output for test */
   /*
   printf("Yaw:      %f\n",  wlzViewStri->theta*180.0/3.14); 
   printf("Pitch:    %f\n",  wlzViewStri->phi*180.0/3.14 );
   printf("Roll:     %f\n",  wlzViewStri->zeta*180.0/3.14 );
   printf("distance: %f\n",  wlzViewStri->dist );
   printf("scaling:  %f\n",  wlzViewStri->scale );
   printf("%f  %f  %f\n",  wlzViewStri->fixed.vtX, wlzViewStri->fixed.vtY ,wlzViewStri->fixed.vtZ  );
   */

   vtx1.d3.vtX = 0.0;
   vtx1.d3.vtY = 0.0;
   vtx1.d3.vtZ = 1.0;
   /* get the normal n_i = nI.d3   of this plan i -plane do not need !!! */
   errNum = Wlz3DSectionTransformInvVtxR(wlzViewStri, vtx1.d3, &nI.d3 );

   /* in OPT space */

   /* check  the n_{i} *  nStraghtline != 0  other wise throw an erro  */
   dtemp =  WLZ_VTX_3_DOT(nStraghtline.d3, nI.d3);
   /* dtemp = abs(dtemp); */
   if( ( dtemp <  0.000001 ) && ( dtemp >  -0.000001 ) )
   {
      printf("%lg\n",dtemp);
      printf(" the  n_{i} is verticl to n_straght line in OPT space,\n");
      printf(" there is no crossed point. Please chose different straight\n");
      printf("line and  try again\n ");
      printf("%lg  %lg  %lg\n", nI.d3.vtX, nI.d3.vtY, nI.d3.vtZ);
      printf("%lg  %lg  %lg\n", nStraghtline.d3.vtX, nStraghtline.d3.vtY, nStraghtline.d3.vtZ);
      exit( 1 );
   }
   else
   {
     /* not parallel to z-direction  */
     /*  s_{i} = x_{i} + n_straight_line * s
                 = x_{i} + n_straight_line * 
		     <  [ O_{i} - x_{i}  ] dot n_{i}  /   ( n_straightline dot n_{i} ) >

     */
    
     	/*  dtemp =  ( n_straightlien dot n_{i} )  aleady got */

     	/* get the  o_i+1 
   		vo.d3.vtX   = wlzViewStr1->fixed.vtX + wlzViewStr->dist * nI.d3.vtX;
   		vo.d3.vtY   = wlzViewStr1->fixed.vtY + wlzViewStr->dist * nI.d3.vtY;
   		vo.d3.vtY   = wlzViewStr1->fixed.vtZ + wlzViewStr->dist * nI.d3.vtZ;
    	*/
    		WLZ_VTX_3_SCALE(vtemp0.d3, nI.d3, wlzViewStri->dist);
    		WLZ_VTX_3_ADD(vo.d3, wlzViewStri->fixed, vtemp0.d3);

    		/* vso.d3 = vo.d3 - vx.d3 */
    		WLZ_VTX_3_SUB(vso.d3,vo.d3,sip.d3);
    
   	/* vs0.d3 dot n_i */
     		dtemp1  =  WLZ_VTX_3_DOT(vso.d3, nI.d3);

   	/* get the s */
     		dtemp2 =  dtemp1  / dtemp;
     
      	/*  vtemp.d3   =   (  n_straightlien * s  )  */
     		WLZ_VTX_3_SCALE(vtemp.d3, nStraghtline.d3,  dtemp2 );


    	/* now get the p_{i} */ 
     		WLZ_VTX_3_ADD(vs1.d3, sip.d3, vtemp.d3 );

   }

   /*---- get the p_{i}' = T_{i} p_{i}  ----*/
   errNum = Wlz3DSectionTransformVtxR(wlzViewStri, vs1.d3, &vtemp.d3 );
   sip1p->d3.vtX = vtemp.d3.vtX;
   sip1p->d3.vtY = vtemp.d3.vtY;
   sip1p->d3.vtZ = vtemp.d3.vtZ;

   printf("%lg  %lg  %lg\n", sip1p->d3.vtX, sip1p->d3.vtY, sip1p->d3.vtZ );


   return errNum;



}
/*!
* - Function:   WlzTrack3DVertical
* - Returns:    WlzVetex 
* - Purpose:    Track vertex through neighbour layer.	
* - Parameters:	
*
*     -#   sip:              input   WlzVertex.
*     -#   sip1p:            output  WlzVertex by tracking.
*     -#   wlzViewStri:      WlzThreeDViewStruct for layer i;
*     -#   wlzViewStrip1:    WlzThreeDViewStruct for the next layer i+-1;
*     -#   UpOrDown:         > 0 Up;  <= 0 down; 
* - Author:       J. Rao, R. Baldock
*/
static WlzErrorNum WlzTrack3DVertical( WlzVertex sip, 
                                WlzVertex *sip1p,
                                WlzThreeDViewStruct  *wlzViewStri,  
			        WlzThreeDViewStruct  *wlzViewStrip1,
				int UpOrDown)
{

   WlzVertex vtemp, vtemp0, vs, vo, vso, vtx1;
   WlzVertex vs1, nI, nIP1;
   double    dtemp, dtemp1, dtemp2;
   WlzErrorNum	       errNum = WLZ_ERR_NONE;
  

   /* output for test */
   /*
   printf("Yaw:      %f\n",  wlzViewStri->theta*180.0/3.14); 
   printf("Pitch:    %f\n",  wlzViewStri->phi*180.0/3.14 );
   printf("Roll:     %f\n",  wlzViewStri->zeta*180.0/3.14 );
   printf("distance: %f\n",  wlzViewStri->dist );
   printf("scaling:  %f\n",  wlzViewStri->scale );
   printf("%f  %f  %f\n",  wlzViewStri->fixed.vtX, wlzViewStri->fixed.vtY ,wlzViewStri->fixed.vtZ  );
   */

   
   /* vtemp0.d3 = (sx', sy', sz')   */
   WlzValueCopyDVertexToDVertex3(&vtemp0.d3, &sip.d3, 1);
   vtemp0.d3.vtZ = wlzViewStri->dist;
   
   /* reverse affine transformation the vertx to get  vs.d3 = s_i here is in OPT space */
   errNum = Wlz3DSectionTransformInvVtxR(wlzViewStri, vtemp0.d3, &vs.d3 );
   
   printf("%f  %f  %f\n", vs.d3.vtX, vs.d3.vtY, vs.d3.vtZ);

   /* as the vs.d3 is in OPT space and we want vertical tracking
      we have:
      
      vs1.d3.vtX = vs.d3.vtX
      vs1.d3.vtY = vs.d3.vtY

      vs1.d3.vtZ = ? need to be find !!!!!

      vs1.d3.vtZ = vs.d3.vtZ + s

      where s  n_z dot n_{i+1} = [ O_{i+1} - r_{i}     ] dot n_{i+1}

      */
      /*
      nz.d3.vtX = 0.0;
      nz.d3.vtY = 0.0;
      nz.d3.vtZ = 1.0;
      if( UpOrDown <= 0 )
      {
   	nz.d3.vtZ = -1.0;
      }
      */



   vtx1.d3.vtX = 0.0;
   vtx1.d3.vtY = 0.0;
   vtx1.d3.vtZ = 1.0;
   /* get the normal n_i = nI.d3   of this plan i -plane do not need !!! */
   errNum = Wlz3DSectionTransformInvVtxR(wlzViewStri, vtx1.d3, &nI.d3 );
   
   /* get the normal n_i(+-1) = nIP1.d3  of the next plan i+-1 -plane */
   errNum = Wlz3DSectionTransformInvVtxR(wlzViewStrip1, vtx1.d3, &nIP1.d3 );

   /* track the s_{i+-1} vertically in OPT space */

   /* check  the n_{i+1}_z != 0 other wise throw an erro  */
   dtemp =  nIP1.d3.vtZ;
   /* dtemp = abs(dtemp); */
   if( ( dtemp <  0.00000001 ) && ( dtemp >  -0.00000001 ) )
   {
      printf("%lg\n",dtemp);
      printf(" the z-component of n_{i+1} is zero in OPT space, we can't track vertically\n ");
      printf("%lg  %lg  %lg\n", nIP1.d3.vtX, nIP1.d3.vtY, nIP1.d3.vtZ);
      exit( 1 );

   }
   else
   {
     /* not parallel to z-direction  */
     /*  s_{i+1} = S_{i} + n_z * s
                 = S_{i} + n_z * <  [ O_{i+1} - r_{i}     ] dot n_{i+1}  /   ( n_z dot n_{i+1} ) >

     */
    
     	/*  dtemp =    ( n_z dot n_{i+1} )  */
     		dtemp  =  WLZ_VTX_3_DOT(vtx1.d3, nIP1.d3);

     	/* get the  o_i+1 
   		vo.d3.vtX   = wlzViewStr1->fixed.vtX + wlzViewStr->dist * nIP1.d3.vtX;
   		vo.d3.vtY   = wlzViewStr1->fixed.vtY + wlzViewStr->dist * nIP1.d3.vtY;
   		vo.d3.vtY   = wlzViewStr1->fixed.vtZ + wlzViewStr->dist * nIP1.d3.vtZ;
    	*/
    		WLZ_VTX_3_SCALE(vtemp0.d3, nIP1.d3, wlzViewStrip1->dist);
    		WLZ_VTX_3_ADD(vo.d3, wlzViewStrip1->fixed, vtemp0.d3);

    		/* vso.d3 = vo.d3 - vs.d3 */
    		WLZ_VTX_3_SUB(vso.d3,vo.d3,vs.d3);
    
   	/* vs0.d3 dot n_i+1 */
     		dtemp1  =  WLZ_VTX_3_DOT(vso.d3, nIP1.d3);

   	/* get the s */
     		dtemp2 =  dtemp1  / dtemp;
     
      	/*  vtemp.d3   =   (  n_z * s  )  */
     		WLZ_VTX_3_SCALE(vtemp.d3, vtx1.d3,  dtemp2 );


    	/* now get the s_{i+1} */ 
     		WLZ_VTX_3_ADD(vs1.d3, vs.d3, vtemp.d3 );

   }

   /*---- get the s_{i+1}' = T_{i+1} s_{i+1}  ----*/
   errNum = Wlz3DSectionTransformVtxR(wlzViewStrip1, vs1.d3, &vtemp.d3 );
   sip1p->d3.vtX = vtemp.d3.vtX;
   sip1p->d3.vtY = vtemp.d3.vtY;
   sip1p->d3.vtZ = vtemp.d3.vtZ;



   printf("%lg  %lg  %lg\n", sip1p->d3.vtX, sip1p->d3.vtY, sip1p->d3.vtZ );


   return errNum;
}