/*!
* - 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;
}
예제 #2
0
int		main(int argc, char *argv[])
{
  int		idN,
  		idM,
		nSeeds,
  		nBndSeeds,
		boundFlg = 0,
		imgFlg = 0,
		interp = 0,
  		seedFlg = 0,
  		ok = 1,
  		option,
  		usage = 0;
  size_t	vtxSize = sizeof(WlzDVertex2);
  WlzObjectType	outObjType;
  WlzVertexType bndVtxType;
  WlzVertex	seed;
  WlzVertexP	bndSeeds,
		seeds;
  FILE		*fP = NULL;
  char		*outObjFileStr,
  		*refObjFileStr = NULL,
		*meshFileStr;
  const char	*errMsgStr;
  WlzErrorNum	errNum = WLZ_ERR_NONE;
  WlzObject	*outObj = NULL,
		*mshObj = NULL,
  		*refObj = NULL;
  WlzCMeshP 	mesh;
  WlzCMeshNodP	nod;
  static char   optList[] = "bhiLo:r:s:";
  const char    meshFileStrDef[] = "-",
  	        outObjFileStrDef[] = "-";

  mesh.v = NULL;
  opterr = 0;
  seeds.v = NULL;
  bndSeeds.v = NULL;
  outObjFileStr = (char *)outObjFileStrDef;
  meshFileStr = (char *)meshFileStrDef;
  seed.d3.vtX = seed.d3.vtY = seed.d3.vtZ = 0.0;
  while((usage == 0) && ((option = getopt(argc, argv, optList)) != EOF))
  {
    switch(option)
    {
      case 'b':
	boundFlg = 1;
        break;
      case 'i':
	imgFlg = 1;
        break;
      case 's':
	seedFlg = 1;
        if(sscanf(optarg, "%lg,%lg,%lg",
	          &(seed.d3.vtX), &(seed.d3.vtY), &(seed.d3.vtZ)) < 1)
	{
	  usage = 1;
	}
	break;
      case 'o':
        outObjFileStr = optarg;
	break;
      case 'r':
        refObjFileStr = optarg;
	break;
      case 'L':
        interp = 1;
	break;
      case 'h': /* FALLTHROUGH */
      default:
	usage = 1;
	break;
    }
  }
  ok = usage == 0;
  if(ok)
  {
    if((meshFileStr == NULL) || (*meshFileStr == '\0') ||
       (outObjFileStr == NULL) || (*outObjFileStr == '\0'))
    {
      ok = 0;
      usage = 1;
    }
    if(ok && (optind < argc))
    {
      if((optind + 1) != argc)
      {
        usage = 1;
        ok = 0;
      }
      else
      {
        meshFileStr = *(argv + optind);
      }
    }
  }
  if(ok && refObjFileStr)
  {
    if(((fP = (strcmp(refObjFileStr, "-")?
              fopen(refObjFileStr, "r"): stdin)) == NULL) ||
       ((refObj = WlzAssignObject(WlzReadObj(fP, &errNum), NULL)) == NULL) ||
       (errNum != WLZ_ERR_NONE))
    {
      ok = 0;
      (void )fprintf(stderr,
                     "%s: failed to read reference object from file %s\n",
                     *argv, refObjFileStr);
    }
    if(fP && strcmp(refObjFileStr, "-"))
    {
      (void )fclose(fP); fP = NULL;
    }
  }
  if(ok)
  {
    if(((fP = (strcmp(meshFileStr, "-")?
              fopen(meshFileStr, "r"): stdin)) == NULL) ||
       ((mshObj = WlzAssignObject(WlzReadObj(fP, &errNum), NULL)) == NULL) ||
       (errNum != WLZ_ERR_NONE))
    {
      ok = 0;
      (void )fprintf(stderr,
                     "%s: failed to read mesh object from file %s\n",
                     *argv, meshFileStr);
    }
    if(fP && strcmp(meshFileStr, "-"))
    {
      (void )fclose(fP); fP = NULL;
    }
  }
  if(ok)
  {
    switch(mshObj->type)
    {
      case WLZ_CMESH_2D:
	mesh.m2 = mshObj->domain.cm2;
	break;
      case WLZ_CMESH_3D:
	mesh.m3 = mshObj->domain.cm3;
	break;
      default:
        ok = 0;
	errNum = WLZ_ERR_OBJECT_TYPE;
	(void )WlzStringFromErrorNum(errNum, &errMsgStr);
	(void )fprintf(stderr,
		 "%s: Invalid mesh object, must be WLZ_CMESH_[23]D (%s),\n",
		 argv[0],
		 errMsgStr);
	break;
    }
  }
  if(ok && mshObj)
  {
    switch(mshObj->type)
    {
      case WLZ_CMESH_2D:
	vtxSize = sizeof(WlzDVertex2);
        if((refObj != NULL) && (refObj->type != WLZ_2D_DOMAINOBJ))
	{
	  ok = 0;
	}
	break;
      case WLZ_CMESH_3D:
	vtxSize = sizeof(WlzDVertex3);
        if((refObj != NULL) && (refObj->type != WLZ_3D_DOMAINOBJ))
	{
	  ok = 0;
	}
	break;
      default:
        ok = 0;
    }
    if(ok == 0)
    {
	errNum = WLZ_ERR_OBJECT_TYPE;
	(void )WlzStringFromErrorNum(errNum, &errMsgStr);
	(void )fprintf(stderr,
		 "%s: Mesh and reference objects must have the same\n"
		 "dimension (%s)\n",
		 argv[0],
		 errMsgStr);
    }
  }
  /* Create seed buffer. */
  if(ok)
  {
    nSeeds = (seedFlg != 0);
    if(boundFlg)
    {
      nSeeds += WlzCMeshSetBoundNodFlags(mesh);
    }
    if(refObj)
    {
      bndSeeds = WlzVerticesFromObjBnd(refObj, &nBndSeeds, &bndVtxType,
      				       &errNum);
      nSeeds += nBndSeeds;
    }
    if(errNum != WLZ_ERR_NONE)
    {
      ok = 0;
      (void )WlzStringFromErrorNum(errNum, &errMsgStr);
      (void )fprintf(stderr,
               "%s: Failed to extract seeds (%s)\n",
	       argv[0],
	       errMsgStr);
    }
    else if(nSeeds < 1)
    {
      ok = 0;
      (void )fprintf(stderr,
	       "%s: Number of seeds must be > 0.\n",
	       argv[0]);
    }
  }
  if(ok)
  {
    if((seeds.v = AlcMalloc(vtxSize * nSeeds)) == NULL)
    {
      ok = 0;
      errNum = WLZ_ERR_MEM_ALLOC;
      (void )WlzStringFromErrorNum(errNum, &errMsgStr);
      (void )fprintf(stderr,
		"%s: Failed to allocate seed buffer (%s)\n",
		argv[0],
		errMsgStr);
    }
  }
  if(ok)
  {
    switch(mshObj->type)
    {
      case WLZ_CMESH_2D:
	idN = 0;
	outObjType = (imgFlg != 0)? WLZ_2D_DOMAINOBJ: WLZ_CMESH_2D;
	if(seedFlg)
	{
	  idN = 1;
	  seeds.d2->vtX = seed.d2.vtX;
	  seeds.d2->vtY = seed.d2.vtY;
	}
	if(boundFlg)
	{
	  for(idM = 0; idM < mesh.m2->res.nod.maxEnt; ++idM)
	  {
	    nod.n2 = (WlzCMeshNod2D *)
	             AlcVectorItemGet(mesh.m2->res.nod.vec, idM);
	    if((nod.n2->idx >= 0) &&
	       ((nod.n2->flags & WLZ_CMESH_NOD_FLAG_BOUNDARY) != 0))
	    {
	      seeds.d2[idN++] = nod.n2->pos;
	    }
	  }
	}
	if(refObj)
	{
	  switch(bndVtxType)
	  {
	    case WLZ_VERTEX_I2:
	      WlzValueCopyIVertexToDVertex(seeds.d2 + idN, bndSeeds.i2,
	      				   nBndSeeds);
	      break;
	    case WLZ_VERTEX_F2:
	      WlzValueCopyFVertexToDVertex(seeds.d2 + idN, bndSeeds.f2,
	      				   nBndSeeds);
	      break;
	    case WLZ_VERTEX_D2:
	      WlzValueCopyDVertexToDVertex(seeds.d2 + idN, bndSeeds.d2,
	      				   nBndSeeds);
	      break;
	    default:
	      errNum = WLZ_ERR_PARAM_TYPE;
	      break;
	  }
	}
	if(errNum == WLZ_ERR_NONE)
	{
	  outObj = WlzCMeshDistance2D(mshObj, outObjType,
	                              nSeeds, seeds.d2,
				      (interp)? WLZ_INTERPOLATION_KRIG:
				                WLZ_INTERPOLATION_BARYCENTRIC,
				      &errNum);
	}
	break;
      case WLZ_CMESH_3D:
	idN = 0;
	outObjType = (imgFlg != 0)? WLZ_3D_DOMAINOBJ: WLZ_CMESH_3D;
	if(seedFlg)
	{
	  idN = 1;
	  seeds.d3->vtX = seed.d3.vtX;
	  seeds.d3->vtY = seed.d3.vtY;
	  seeds.d3->vtZ = seed.d3.vtZ;
	}
	if(boundFlg)
	{
	  for(idM = 0; idM < mesh.m3->res.nod.maxEnt; ++idM)
	  {
	    nod.n3 = (WlzCMeshNod3D *)
	             AlcVectorItemGet(mesh.m3->res.nod.vec, idM);
	    if((nod.n3->idx >= 0) &&
	       ((nod.n3->flags & WLZ_CMESH_NOD_FLAG_BOUNDARY) != 0))
	    {
	      seeds.d3[idN++] = nod.n3->pos;
	    }
	  }
	}
	if(refObj)
	{
	  switch(bndVtxType)
	  {
	    case WLZ_VERTEX_I3:
	      WlzValueCopyIVertexToDVertex3(seeds.d3 + idN, bndSeeds.i3,
	      				    nBndSeeds);
	      break;
	    case WLZ_VERTEX_F3:
	      WlzValueCopyFVertexToDVertex3(seeds.d3 + idN, bndSeeds.f3,
	      				    nBndSeeds);
	      break;
	    case WLZ_VERTEX_D3:
	      WlzValueCopyDVertexToDVertex3(seeds.d3 + idN, bndSeeds.d3,
	      				    nBndSeeds);
	      break;
	    default:
	      errNum = WLZ_ERR_PARAM_TYPE;
	      break;
	  }
	}
	if(errNum == WLZ_ERR_NONE)
	{
	  outObj = WlzCMeshDistance3D(mshObj, outObjType,
	  	                      nSeeds, seeds.d3,
				      (interp)? WLZ_INTERPOLATION_KRIG:
				                WLZ_INTERPOLATION_BARYCENTRIC,
				      &errNum);
	}
	break;
	break;
      default:
	break;
    }
    if(errNum != WLZ_ERR_NONE)
    {
      ok = 0;
      (void )WlzStringFromErrorNum(errNum, &errMsgStr);
      (void )fprintf(stderr,
		"%s: Failed to create domain object with distances (%s)\n",
		argv[0],
		errMsgStr);
    }
  }
  AlcFree(seeds.v);
  AlcFree(bndSeeds.v);
  WlzFreeObj(refObj);
  WlzFreeObj(mshObj);
  if(ok)
  {
    errNum = WLZ_ERR_WRITE_EOF;
    if(((fP = (strcmp(outObjFileStr, "-")?
              fopen(outObjFileStr, "w"): stdout)) == NULL) ||
       ((errNum = WlzWriteObj(fP, outObj)) != WLZ_ERR_NONE))
    {
      ok = 0;
      (void )fprintf(stderr,
                     "%s: failed to write output object to file %s\n",
                     *argv, outObjFileStr);
    }
    if(fP && strcmp(outObjFileStr, "-"))
    {
      (void )fclose(fP); fP = NULL;
    }
  }
  (void )WlzFreeObj(outObj);
  if(usage)
  {
    fprintf(stderr,
            "Usage: %s [-b] [-h] [-o<out obj file>] [-r<ref obj file>]\n"
	    "                        [-L] [-s #,#,#] [<input mesh file>]\n"
	    "Constructs a 2D or 3D domain object the values of which are\n"
	    "the minimum distance from the given seeds points in the given\n"
	    "conforming mesh. The domain of the output object covers the\n"
	    "input mesh.\n"
	    "Version: %s\n"
	    "Options:\n"
	    "  -h  Help, prints this usage message.\n"
            "  -i  Output an image (ie a 2 or 3D domain object) with\n"
	    "      interpolated distance values rather than a mesh with\n"
	    "      indexed values.\n"
	    "  -L  Use expensive interpolation (mainly useful as a test).\n"
	    "  -o  Output object.\n"
	    "  -b  Set seed points around the boundary of the mesh.\n"
	    "  -s  Single seed position.\n"
	    "  -r  Reference object with seed points around it's boundary.\n",
	    argv[0],
	    WlzVersion());

  }
  return(!ok);
}