Esempio n. 1
0
int             main(int argc, char **argv)
{
  int		option,
  		nTiePP = 0,
		dim = 0,                /* Dimension will be set by objects. */
		cdt = 0,
		cMesh = 0,
		basisFnPolyOrder = 3,
		dbgFlg = 0, 		  /* Bit wise debug flags see usage. */
		noTrObj = 0,
		outBasisTrFlag = 0,
		outMeshTrFlag = 0,
		restrictToBasisFn = 0,
		ok = 1,
		usage = 0;
  double	meshMinDist = 20.0,
  		meshMaxDist = 40.0;
  WlzVertexP	vxA0,
  		vxA1;
  WlzObject	*inObj = NULL,
		*outObj = NULL,
		*dilObj = NULL,
           	*tmpObj = NULL;
  WlzCMeshP	tarMesh;
  WlzTransform  meshTr;
  WlzMeshGenMethod meshGenMth = WLZ_MESH_GENMETHOD_GRADIENT;
  WlzBasisFnTransform *basisTr = NULL;
  WlzFnType basisFnType = WLZ_FN_BASIS_2DMQ;
  WlzInterpolationType interp = WLZ_INTERPOLATION_NEAREST;
  FILE		*fP = NULL;
  WlzErrorNum	errNum = WLZ_ERR_NONE;
  char 		*inObjFileStr,
		*basisFnTrFileStr = NULL,
		*tarMeshFileStr = NULL,
		*tiePtFileStr = NULL,
  		*outObjFileStr;
  const int	delOut = 1;
  const char    *errMsg;
  static char	optList[] = "b:m:o:p:t:D:M:Y:cdghqsyBCGLNQRTU",
  		inObjFileStrDef[] = "-",
		outObjFileStrDef[] = "-";

  opterr = 0;
  vxA0.v = NULL;
  vxA1.v = NULL;
  tarMesh.v = NULL;
  meshTr.core = NULL;
  outObjFileStr = outObjFileStrDef;
  inObjFileStr = inObjFileStrDef;
  while((usage == 0) && ((option = getopt(argc, argv, optList)) != -1))
  {
    switch(option)
    {
      case 'o':
        outObjFileStr = optarg;
	break;
      case 'b':
        basisFnTrFileStr = optarg;
        break;
      case 'B':
        meshGenMth = WLZ_MESH_GENMETHOD_BLOCK;
	break;
      case 'C':
	meshGenMth = WLZ_MESH_GENMETHOD_CONFORM;
	break;
      case 'D':
	if(1 != sscanf(optarg, "%d", &dbgFlg))
	{
	  usage = 1;
	}
	break;
      case 'c':
        basisFnType = WLZ_FN_BASIS_2DCONF_POLY;
	break;
      case 'd':
        cdt = 1;
	break;
      case 'g':
        basisFnType = WLZ_FN_BASIS_2DGAUSS;
	break;
      case 'G':
        meshGenMth = WLZ_MESH_GENMETHOD_GRADIENT;
	break;
      case 'L':
        interp = WLZ_INTERPOLATION_LINEAR;
	break;
      case 'm':
	if(sscanf(optarg, "%lg", &meshMinDist) != 1)
	{
	  usage = 1;
	}
	break;
      case 'M':
	if(sscanf(optarg, "%lg", &meshMaxDist) != 1)
	{
	  usage = 1;
	}
	break;
      case 'N':
        noTrObj = 1;
	break;
      case 'p':
        tiePtFileStr = optarg;
	break;
      case 'q':
        basisFnType = WLZ_FN_BASIS_2DMQ;
	break;
      case 'Q':
        basisFnType = WLZ_FN_BASIS_2DIMQ;
	break;
      case 'R':
        restrictToBasisFn = 1;
	break;
      case 's':
        basisFnType = WLZ_FN_BASIS_2DTPS;
	break;
      case 't':
        tarMeshFileStr = optarg;
	break;
      case 'T':
        outBasisTrFlag = 1;
	break;
      case 'y':
        basisFnType = WLZ_FN_BASIS_2DPOLY;
	break;
      case 'U':
        outMeshTrFlag = 1;
	break;
      case 'Y':
        if(sscanf(optarg, "%d", &basisFnPolyOrder) != 1)
	{
	  usage = 1;
	}
	break;
      case 'h':
      default:
        usage = 1;
	break;
    }
  }
  if(usage == 0)
  {
    if(cdt)
    {
      cMesh = 1;
      restrictToBasisFn = 1;
      meshGenMth = WLZ_MESH_GENMETHOD_CONFORM;
    }
    if((tarMeshFileStr != NULL) && (cMesh == 0))
    {
      usage = 1;
    }
  }
  if(usage == 0)
  {
    if((inObjFileStr == NULL) || (*inObjFileStr == '\0') ||
       (((tiePtFileStr == NULL) || (*tiePtFileStr == '\0')) &&
	((basisFnTrFileStr == NULL) || (*basisFnTrFileStr == '\0'))) ||
       (outObjFileStr == NULL) || (*outObjFileStr == '\0'))
    {
      usage = 1;
    }
  }
  if((usage == 0) && (optind < argc))
  {
    if((optind + 1) != argc)
    {
      usage = 1;
    }
    else
    {
      inObjFileStr = *(argv + optind);
    }
  }
  ok = (usage == 0);
  /* Read input object that's to be transformed. */
  if(ok)
  {
    errNum = WLZ_ERR_READ_EOF;
    if((inObjFileStr == NULL) ||
	(*inObjFileStr == '\0') ||
	((fP = (strcmp(inObjFileStr, "-")?
		fopen(inObjFileStr, "r"): stdin)) == NULL) ||
	((inObj = WlzAssignObject(WlzReadObj(fP, &errNum), NULL)) == NULL) ||
	(errNum != WLZ_ERR_NONE))
    {
      ok = 0;
    }
    if(fP)
    {
      if(strcmp(inObjFileStr, "-"))
      {
	fclose(fP);
      }
      fP = NULL;
    }
    if(ok)
    {
      switch(inObj->type)
      {
        case WLZ_2D_DOMAINOBJ:
	  dim = 2;
	  break;
	case WLZ_3D_DOMAINOBJ:
	  dim = 3;
	  break;
        default:
	  errNum = WLZ_ERR_OBJECT_TYPE;
	  break;
      }
      if(errNum != WLZ_ERR_NONE)
      {
        ok = 0;
      }
    }
    if(ok == 0)
    {
      (void )WlzStringFromErrorNum(errNum, &errMsg);
      (void )fprintf(stderr,
		     "%s: Failed to read object from file %s (%s)\n",
		     *argv, inObjFileStr, errMsg);
    }
  }
  /* Read target mesh if required. */
  if(ok)
  {
    if(tarMeshFileStr != NULL)
    {
      errNum = WLZ_ERR_READ_EOF;
      if((tarMeshFileStr == NULL) ||
	  (*tarMeshFileStr == '\0') ||
	  ((fP = (strcmp(tarMeshFileStr, "-")?
		  fopen(tarMeshFileStr, "r"): stdin)) == NULL) ||
	  ((tmpObj = WlzAssignObject(WlzReadObj(fP,
	                                        &errNum), NULL)) == NULL) ||
	  (errNum != WLZ_ERR_NONE))
      {
	ok = 0;
      }
      else
      {
        switch(tmpObj->type)
	{
	  case WLZ_CMESH_2D:
	    if(dim == 0)
	    {
	      dim = 2;
	    }
	    if(dim != 2)
	    {
	      errNum = WLZ_ERR_OBJECT_TYPE;
	    }
	    else
	    {
	      if(tmpObj->domain.core == NULL)
	      {
		errNum = WLZ_ERR_DOMAIN_NULL;
	      }
	      else if(tmpObj->domain.cm2->type != WLZ_CMESH_2D)
	      {
		errNum = WLZ_ERR_DOMAIN_DATA;
	      }
	      else
	      {
		tarMesh.m2 = tmpObj->domain.cm2;
		tmpObj->domain.cm2 = NULL;
	      }
	    }
	    break;
	  case WLZ_CMESH_3D:
	    if(dim == 0)
	    {
	      dim = 3;
	    }
	    if(dim != 3)
	    {
	      errNum = WLZ_ERR_OBJECT_TYPE;
	    }
	    else
	    {
	      if(tmpObj->domain.core == NULL)
	      {
		errNum = WLZ_ERR_DOMAIN_NULL;
	      }
	      else if(tmpObj->domain.cm3->type != WLZ_CMESH_3D)
	      {
		errNum = WLZ_ERR_DOMAIN_DATA;
	      }
	      else
	      {
		tarMesh.m3 = tmpObj->domain.cm3;
		tmpObj->domain.cm3 = NULL;
	      }
	    }
	    break;
	  default:
	    errNum = WLZ_ERR_OBJECT_TYPE;
	    break;
	}
        if(errNum != WLZ_ERR_NONE)
	{
	  ok = 0;
	}
      }
      (void )WlzFreeObj(tmpObj);
      tmpObj = NULL;
      if(ok == 0)
      {
	(void )WlzStringFromErrorNum(errNum, &errMsg);
	(void )fprintf(stderr,
		 "%s: Failed to read target mesh object from file %s (%s).\n",
		       *argv, tarMeshFileStr, errMsg);
      }
    }
  }
  /* Either read the basis function transform from a file or compute it
   * from a set of tie points. */
  if(ok)
  {
    if(basisFnTrFileStr)
    {
      errNum = WLZ_ERR_UNSPECIFIED;
      ok = 0;
      (void )fprintf(stderr,
      		     "%s: Reading basis function transforms has not been\n"
		     "implemented yet\n",
		     *argv);
    }
    else if(tiePtFileStr)
    {
      if((fP = (strcmp(tiePtFileStr, "-")?
                fopen(tiePtFileStr, "r"): stdin)) == NULL)
      {
        ok = 0;
	errNum = WLZ_ERR_READ_EOF;
	(void )WlzStringFromErrorNum(errNum, &errMsg);
	(void )fprintf(stderr,
		       "%s: Failed to open tie points file %s (%s).\n",
		       *argv, tiePtFileStr, errMsg);
      }
      else
      {
        if(dim == 2)
	{
	  errNum = WlzBFTOGetVertices2D(&nTiePP, &(vxA0.d2), &(vxA1.d2),
	  				fP, tarMesh.m2, argv[0], tiePtFileStr);
	}
	else /* dim == 3 */
	{
	  errNum = WlzBFTOGetVertices3D(&nTiePP, &(vxA0.d3), &(vxA1.d3),
	  				fP, tarMesh.m3, argv[0], tiePtFileStr);
	}
	if(errNum != WLZ_ERR_NONE)
	{
	  ok = 0;
	}
      }
      if(fP && strcmp(tiePtFileStr, "-"))
      {
	fclose(fP);
      }
      fP = NULL;
    }
  }
  if(ok)
  {
    if(dim == 3)
    {
      /* Promote basis function type from 2D to 3D. */
      switch(basisFnType)
      {
        case WLZ_FN_BASIS_2DIMQ:
          basisFnType = WLZ_FN_BASIS_3DIMQ;
	  break;
        case WLZ_FN_BASIS_2DMQ:
          basisFnType = WLZ_FN_BASIS_3DMQ;
	  break;
        default:
	  errNum = WLZ_ERR_DOMAIN_TYPE;
	  ok = 0;
	  (void )WlzStringFromErrorNum(errNum, &errMsg);
	  (void )fprintf(stderr,
	                 "%s: invalid basis function type for 3D (%s).\n",
			 *argv, errMsg);
      }
    }
  }
  if(ok)
  {
    if(restrictToBasisFn)
    {
      if(cMesh)
      {
	if(tarMesh.v == NULL)
	{
	  meshTr.obj = WlzCMeshTransformFromObj(inObj,
				meshGenMth, meshMinDist, meshMaxDist,
				&dilObj, delOut, &errNum);
        }
      }
      else
      {
	meshTr.mesh = WlzMeshFromObj(inObj,
			      meshGenMth, meshMinDist, meshMaxDist,
			      &errNum);

      }
      if(errNum != WLZ_ERR_NONE)
      {
	ok = 0;
	(void )WlzStringFromErrorNum(errNum, &errMsg);
	(void )fprintf(stderr,
		       "%s: Failed to compute a mesh for the object (%s).\n",
		       *argv, errMsg);
      }
      if(errNum == WLZ_ERR_NONE)
      {
	if(tarMesh.v == NULL)
	{
	  if(dim == 2)
	  {
	    basisTr = WlzBasisFnTrFromCPts2D(basisFnType, basisFnPolyOrder,
					   nTiePP, vxA0.d2, nTiePP, vxA1.d2,
					   (cdt)? meshTr.obj->domain.cm2: NULL,
					   &errNum);
	  }
	  else /* dim == 3 */
	  {
	    basisTr = WlzBasisFnTrFromCPts3D(basisFnType, basisFnPolyOrder,
					   nTiePP, vxA0.d3, nTiePP, vxA1.d3,
					   (cdt)? meshTr.obj->domain.cm3: NULL,
					   &errNum);
	  }
	}
	else
	{
	  if(dim == 2)
	  {
	    basisTr = WlzBasisFnTrFromCPts2D(basisFnType, basisFnPolyOrder,
	    				     nTiePP, vxA1.d2, nTiePP, vxA0.d2,
					     tarMesh.m2, &errNum);
	  }
	  else /* dim == 3 */
	  {
	    basisTr = WlzBasisFnTrFromCPts3D(basisFnType, basisFnPolyOrder,
	    				     nTiePP, vxA1.d3, nTiePP, vxA0.d3,
					     tarMesh.m3, &errNum);
	  }
	}
	if(errNum != WLZ_ERR_NONE)
	{
	  ok = 0;
	  (void )WlzStringFromErrorNum(errNum, &errMsg);
	  (void )fprintf(stderr,
		   "%s: Failed to compute basis function transform (%s).\n",
		       *argv, errMsg);
	}
      }
    }
    else /* Use affine and basis functions to define mesh. */
    {
      meshTr.mesh = WlzMeshTransformFromCPts(inObj,
      				basisFnType, basisFnPolyOrder,
      				nTiePP, vxA0.d2, nTiePP, vxA1.d2,
				meshGenMth, meshMinDist, meshMaxDist,
				&errNum);
    }
  }
  if(ok)
  {
    if(outBasisTrFlag)
    {
      errNum = WLZ_ERR_UNIMPLEMENTED;
      ok = 0;
      (void )fprintf(stderr,
      		     "%s: Writing basis function transforms has not been\n"
		     "implemented yet\n",
		     *argv);
    }
    else /* Transform the object and then write it out. */
    {
      if(restrictToBasisFn)
      {
	if(errNum == WLZ_ERR_NONE)
	{
	  if(cMesh)
	  {
	    if(tarMesh.v == NULL)
	    {
	      errNum = WlzBasisFnSetCMesh(meshTr.obj, basisTr);
	    }
	    else
	    {
	       meshTr.obj = WlzBasisFnInvertMakeCMeshTr(basisTr, tarMesh,
	       				&errNum);
	    }
	  }
	  else
	  {
	    errNum = WlzBasisFnSetMesh(meshTr.mesh, basisTr);
	  }
	  if(errNum != WLZ_ERR_NONE)
	  {
	    ok = 0;
	    (void )WlzStringFromErrorNum(errNum, &errMsg);
	    (void )fprintf(stderr,
			   "%s: Failed to set the mesh displacements (%s).\n",
			   *argv, errMsg);
	  }
	}
      }
      if(errNum == WLZ_ERR_NONE)
      {
	if(outMeshTrFlag)
	{
	  if(cMesh)
	  {
	    errNum = WLZ_ERR_WRITE_EOF;
	    if(((fP = (strcmp(outObjFileStr, "-")?
		      fopen(outObjFileStr, "w"):
		      stdout)) == NULL) ||
	       ((errNum = WlzWriteObj(fP, meshTr.obj)) != WLZ_ERR_NONE))
	    {
	      ok = 0;
	      (void )WlzStringFromErrorNum(errNum, &errMsg);
	      (void )fprintf(stderr,
			     "%s: Failed to write CMesh object (%s).\n",
			     *argv, errMsg);
	    }
	    if(fP && strcmp(outObjFileStr, "-"))
	    {
	      fclose(fP);
	    }
	  }
	  else
	  {
	    errNum = WLZ_ERR_UNIMPLEMENTED;
	    ok = 0;
	    (void )fprintf(stderr,
			   "%s: Writing mesh transforms has not been\n"
			   "implemented yet\n",
			   *argv);
	  }
	}
	else
	{
	  if(noTrObj == 0)
	  {
	    if(cMesh)
	    {
	      outObj = WlzCMeshTransformObj(inObj, meshTr.obj, interp,
					    &errNum);
	    }
	    else
	    {
	      outObj = WlzMeshTransformObj(inObj, meshTr.mesh, interp,
					   &errNum);
	    }
	  }
	}
      }
      if(errNum == WLZ_ERR_NONE)
      {
	if(dbgFlg & 1)
	{
	  if(cMesh)
	  {
	    WlzCMeshOutputPS(meshTr.obj, inObj, dilObj, outObj);
	  }
	  else
	  {
	    WlzMeshOutputPS(meshTr.mesh);
	  }
	}
      }
      if(errNum != WLZ_ERR_NONE)
      {
	ok = 0;
	(void )WlzStringFromErrorNum(errNum, &errMsg);
	(void )fprintf(stderr,
		       "%s: Failed to transform object (%s).\n",
		       *argv, errMsg);
      }
      if((errNum == WLZ_ERR_NONE) && (noTrObj == 0) &&
         (outBasisTrFlag == 0) && (outMeshTrFlag == 0))
      {
	errNum = WLZ_ERR_WRITE_EOF;
	if(((fP = (strcmp(outObjFileStr, "-")?
		  fopen(outObjFileStr, "w"):
		  stdout)) == NULL) ||
	   ((errNum = WlzWriteObj(fP, outObj)) != WLZ_ERR_NONE))
	{
	  ok = 0;
	  (void )WlzStringFromErrorNum(errNum, &errMsg);
	  (void )fprintf(stderr,
			 "%s: Failed to write output object (%s).\n",
			 *argv, errMsg);
	}
	if(fP && strcmp(outObjFileStr, "-"))
	{
	  fclose(fP);
	}
      }
    }
  }
  AlcFree(vxA0.v);
  AlcFree(vxA1.v);
  (void )WlzCMeshFree(tarMesh);
  if(cMesh)
  {
    (void )WlzFreeObj(meshTr.obj);
  }
  else
  {
    (void )WlzMeshFreeTransform(meshTr.mesh);
  }
  (void )WlzBasisFnFreeTransform(basisTr);
  (void )WlzFreeObj(inObj);
  (void )WlzFreeObj(outObj);
  (void )WlzFreeObj(dilObj);
  if(usage != 0)
  {
    (void )fprintf(stderr,
    "Usage: %s%sExample: %s%s",
    *argv,
    " [-o<out object>] [-p<tie points file>]\n"
    "                  [-m<min mesh dist>] [-M<max mesh dist>]\n"
    "                  [-b<basis fn transform>] [-Y<order of polynomial>]\n"
    "                  [-D<flags>]\n"
    "                  [-d] [-g] [-h] [-q] [-s] [-t] [-y]\n"
    "                  [-B] [-C] [-G] [-L] [-N] [-T]\n"
    "                  [<in object>]\n"
    "Options:\n"
    "  -b  Basis function transform object.\n"
    "  -B  Block mesh generation method (default).\n"
    "  -C  Use conforming mesh.\n"
    "  -D  Debug flags:\n"
    "        1  Output the mesh as postscript to standard error output.\n"
    "        2  Output basis function distance maps to standard error\n"
    "           output.\n"
    "      These debug flags are only intended for use when debuging and\n"
    "      they may be combined by an or operation (eg 11 = 1 | 2 | 8).\n"
    "  -G  Gradient mesh generation method.\n"
    "  -L  Use linear interpolation instead of nearest neighbour.\n"
    "  -m  Minimum mesh node separation distance (default 10.0)\n"
    "  -M  Maximum mesh node separation distance (default 100.0)\n"
    "  -N  Don't transform the object (useful for testing)\n"
    "  -R  Restrict the transformation to only a basis function transform\n"
    "      instead of the default which uses a least squares affine and\n"
    "      basis function transform.\n"
    "  -o  Output object file name.\n"
    "  -p  Tie point file.\n"
    "  -c  Use conformal polynomial basis function if tie points are given.\n"
    "  -d  Compute transform using conforming distance transforms, also\n"
    "      sets the mesh generation to produce a conforming mesh and\n"
    "      restricts the transformation to a basis function transform\n"
    "      only (ie no least squares affine).\n"
    "  -g  Use Gaussian basis function if tie points are given.\n"
    "  -h  Help, prints this usage message.\n"
    "  -q  Use multi-quadric basis function if tie points are given.\n"
    "  -Q  Use inverse-multi-quadric basis function if tie points are given.\n"
    "  -s  Use thin plate spline basis function (default) if tie points\n"
    "      are given.\n"
    "  -t  Target mesh. Only valid for conforming meshes. If given then the\n"
    "      target mesh is used to compute a target-to-source radial basis\n"
    "      function, with distances computed in the target mesh. This is\n"
    "      then inverted as a mesh transform is created.\n"
    "  -T  Output a basis function transform instead of a transformed\n"
    "      object.\n"
    "  -U  Output a mesh transform instead of a transformed object.\n"
    "  -y  Use polynomial basis function if tie points are given.\n"
    "  -Y  Polynomial order for polynomial basis function (default 3).\n"
    "Computes and applies Woolz basis function transforms.\n"
    "Tie points may be read from an ascii file with the 2D format:\n"
    "  <x> <y> <displacement x> <displacement y>\n"
    "and the 3D format:\n"
    "  <x> <y> <z> <displacement x> <displacement y> <displacement z>\n"
    "Objects are read from stdin and written to stdout unless the filenames\n"
    "are given.\n",
    *argv,
    " -o tied.wlz -p points.tie myobj.wlz\n"
    "A thin plate spline basis function transform is computed from the\n"
    "tie points read from the file points.tie. This transform is then\n"
    "applied to the object is read from myobj.wlz. The resulting object\n"
    "is then written to tied.wlz.\n");
  }
  return(!ok);
}
Esempio n. 2
0
int		main(int argc, char *argv[])
{
  int		objCnt,
  		option,
  		inv = 0,
		nStep = 1,
		timer = 0,
		useStep = 0,
  		ok = 1,
  		usage = 0;
  double        transition = 1.0;
  FILE		*inFP = NULL,
  		*outFP = NULL;
  char		*txFileStr = NULL,
                *inFileStr = NULL,
                *outFileStr = NULL,
                *outObjFileBodyStr = NULL,
                *outObjFileExtStr = NULL,
                outObjFileStr[FILENAME_MAX];
  WlzInterpolationType interp = WLZ_INTERPOLATION_NEAREST;
  const char	*errMsgStr;
  WlzObject	*trObj = NULL,
                *inObj = NULL,
                *outObj = NULL;
  WlzErrorNum	errNum = WLZ_ERR_NONE;
  struct timeval times[3];
  static char   optList[] = "iho:t:s:x:ELb:e:";
  const char    txFileStrDef[] = "-",
  		inFileStrDef[] = "-",
                outFileStrDef[] = "-",
                outObjFileExtStrDef[] = "wlz";


  opterr = 0;
  txFileStr = (char *)txFileStrDef;
  inFileStr = (char *)inFileStrDef;
  outFileStr = (char *)outFileStrDef;
  outObjFileExtStr = (char *)outObjFileExtStrDef;
  (void )memset(times, 0, 3 * sizeof(struct timeval));
  while((usage == 0) && ((option = getopt(argc, argv, optList)) != EOF))
  {
    switch(option)
    {
      case 'b':
        outObjFileBodyStr = optarg;
        break;
      case 'e':
        outObjFileExtStr = optarg;
        break;
      case 'i':
        inv = 1;
	break;
      case 'o':
        outFileStr = optarg;
	break;
      case 't':
        txFileStr = optarg;
        break;
      case 'E':
        timer = 1;
	break;
      case 'L':
        interp = WLZ_INTERPOLATION_LINEAR;
        break;
      case 's':
        useStep = 1;
	if(sscanf(optarg, "%d", &nStep) != 1)
	{
	  usage = 1;
	}
        break;
      case 'x':
        useStep = 0;
        if(sscanf(optarg, "%lg", &transition) != 1)
	{
	  usage = 1;
	}
        break;
      case 'h':
      default:
	usage = 1;
	break;
    }
  }
  if((usage == 0) && (optind < argc))
  {
    if((optind + 1) != argc)
    {
      usage = 1;
    }
    else
    {
      inFileStr = argv[optind];
    }
  }
  ok = usage == 0;
  if(useStep && ok && (transition < 0 || transition > 1.0))
  {
      ok = 0;
      (void )fprintf(stderr,
          "%s: Error: transition must be between 0 and 1.\n",
          *argv);
  }
  if(outObjFileBodyStr && outObjFileExtStr &&
     (strlen(outObjFileExtStr) +
      strlen(outObjFileExtStr)) > (FILENAME_MAX - 24))
  {
    ok = 0;
    (void )fprintf(stderr,
                   "%s: Output filename length exceeded!\n",
                   *argv);
  }

  if(ok)
  {
    if(((inFP = (strcmp(txFileStr, "-")?
	        fopen(txFileStr, "r"): stdin)) == NULL) ||
       ((trObj = WlzAssignObject(WlzReadObj(inFP, &errNum), NULL)) == NULL))
    {
      if(errNum == WLZ_ERR_NONE)
      {
        errNum = WLZ_ERR_READ_INCOMPLETE;
      }
    }
    if(errNum == WLZ_ERR_NONE)
    {
      switch(trObj->type)
      {
        case WLZ_CMESH_2D:  /* FALLTHROUGH */
        case WLZ_CMESH_2D5: /* FALLTHROUGH */
	case WLZ_CMESH_3D:
	  break;
        default:
	  errNum = WLZ_ERR_OBJECT_TYPE;
	  break;
      }
    }
    if(errNum != WLZ_ERR_NONE)
    {
      ok = 0;
      (void )WlzStringFromErrorNum(errNum, &errMsgStr);
      (void )fprintf(stderr,
	  "%s: Failed to read constrained mesh transform object from\n"
          "file %s (%s)\n",
	  *argv, txFileStr, errMsgStr);
    }
    if((inFP != NULL) && strcmp(txFileStr, "-"))
    {
      (void )fclose(inFP); inFP = NULL;
    }
  }
  if(ok && inv)
  {
    WlzObject *nTrObj;

    nTrObj = WlzCMeshTransformInvert(trObj, &errNum);
    if(errNum == WLZ_ERR_NONE)
    {
      (void )WlzFreeObj(trObj);
      trObj = WlzAssignObject(nTrObj, NULL);
    }
    else
    {
      ok = 0;
      (void )WlzStringFromErrorNum(errNum, &errMsgStr);
      (void )fprintf(stderr,
                     "%s Failed to invert transform (%s).\n",
                     argv[0], errMsgStr);
    }
  }
  inFP = NULL;
  if(ok)
  {
      if((inFP = (strcmp(inFileStr, "-")?
                 fopen(inFileStr, "r"): stdin)) == NULL)
      {
	errNum = WLZ_ERR_READ_INCOMPLETE;
      }
  }
  if(ok)
  {
    objCnt = 0;
    while(errNum == WLZ_ERR_NONE)
    {
      errNum = WLZ_ERR_READ_EOF;
      if((inObj = WlzAssignObject(WlzReadObj(inFP, &errNum), NULL)) == NULL)
      {
	if(objCnt > 0)
	{
	  errNum = WLZ_ERR_EOO;
	}
	else
	{
	  (void )WlzStringFromErrorNum(errNum, &errMsgStr);
	  (void )fprintf(stderr,
	      "%s: Failed to open input object file %s (%s).\n",
	      *argv, inFileStr, errMsgStr);
	}
      }
      if(errNum == WLZ_ERR_NONE)
      {
	if(useStep)
	{
	  int step = FILENAME_MAX;

	  step = 0;
	  while((step < nStep) && (errNum == WLZ_ERR_NONE))
	  {
	    WlzObject *stepTrObj = NULL;

	    (void )sprintf(outObjFileStr, "%s%04d%04d.%s",
			   outObjFileBodyStr, objCnt, step, outObjFileExtStr);
	    stepTrObj = WlzAssignObject(
			WlzCopyScaleCMeshValue(
			  (double )step / (double )(nStep -1),
			  trObj, &errNum), NULL);
	    if(errNum == WLZ_ERR_NONE)
	    {
	      outObj = WlzCMeshTransformObj(inObj, stepTrObj, interp, &errNum);
	      if(errNum != WLZ_ERR_NONE)
	      {
		(void )WlzStringFromErrorNum(errNum, &errMsgStr);
		(void )fprintf(stderr,
		    "%s: Failed to apply transform (%s).\n",
		    *argv, errMsgStr);
	      }
	    }
	    if(errNum == WLZ_ERR_NONE)
	    {
	      if(outObjFileBodyStr)
	      {
		if((outFP = fopen(outObjFileStr, "w")) == NULL)
		{
		  (void )fprintf(stderr,
		      "%s: Failed to open output file %s.\n",
		      *argv, outObjFileStr);
		}
	      }
	      else
	      {
		outFP = stdout;
	      }
	    }
	    if(errNum == WLZ_ERR_NONE)
	    {
	      if((errNum = WlzWriteObj(outFP, outObj)) != WLZ_ERR_NONE)
	      {
		(void )WlzStringFromErrorNum(errNum, &errMsgStr);
		(void )fprintf(stderr,
		    "%s: Failed to write output object (%s).\n",
		    *argv, errMsgStr);
	      }
	    }
	    WlzFreeObj(stepTrObj);
	    WlzFreeObj(outObj);
	    ++step;
	  }
	  if(errNum != WLZ_ERR_NONE && ok)
	  {
	    (void )WlzStringFromErrorNum(errNum, &errMsgStr);
	    (void )fprintf(stderr,
		"%s: Failed to create object sequence (%s).\n",
		*argv, errMsgStr);
	  }
	}
	else
	{
	  errNum = WlzScaleCMeshValue(transition, trObj);
	  if(errNum == WLZ_ERR_NONE)
	  {
            gettimeofday(times + 0, NULL);
	    outObj = WlzCMeshTransformObj(inObj, trObj, interp, &errNum);
            gettimeofday(times + 1, NULL);
	    if(errNum != WLZ_ERR_NONE)
	    {
	      (void )WlzStringFromErrorNum(errNum, &errMsgStr);
	      (void )fprintf(stderr,
		  "%s: Failed to apply transform (%s).\n",
		  *argv, errMsgStr);
	    }
	  }
	  if(errNum == WLZ_ERR_NONE)
	  {
	    errNum = WLZ_ERR_WRITE_EOF;
	    if(((outFP  = (strcmp(outFileStr, "-")?
		      fopen(outFileStr, "w"):
		      stdout)) == NULL) ||
		((errNum = WlzWriteObj(outFP , outObj)) != WLZ_ERR_NONE))
	    {
	      (void )WlzStringFromErrorNum(errNum, &errMsgStr);
	      (void )fprintf(stderr,
		  "%s: Failed to write output object %s (%s).\n",
		  *argv, outFileStr, errMsgStr);
	    }
	    if(outFP && strcmp(outFileStr, "-"))
	    {
	      (void )fclose(outFP);
	    }
	  }
	  (void )WlzFreeObj(outObj);
	}
      }
      (void )WlzFreeObj(inObj);
      ++objCnt;
    }
    if(errNum != WLZ_ERR_NONE)
    {
      if(errNum == WLZ_ERR_EOO)
      {
	errNum = WLZ_ERR_NONE;
      }
      else
      {
	ok = 0;
      }
    }
  }
  (void )WlzFreeObj(trObj);
  if((inFP != NULL) && strcmp(inFileStr, "-"))
  {
    (void )fclose(inFP); inFP = NULL;
  }
  if(timer)
  {
    ALC_TIMERSUB(times + 1, times + 0, times + 2);
    (void )fprintf(stderr,
    "%s: Elapsed time to transform the object was: %g seconds\n",
    *argv,
    times[2].tv_sec + (0.000001 * times[2].tv_usec));
  }
  if(usage)
  {
      fprintf(stderr,
            "Usage: %s [-h] [-t<input transfrom>] [-i] [-N] \n"
            "        [-x<interpolation value> [-o<output woolz file>]] | \n"
            "        [-s<number of interpolations> [-b <output body>] \n"
            "        [-e <output extension>]] ] [<input object>]\n"
            "Reads a constrained mesh transform object, applies it\n"
            "to objects generating output transformed objects.\n"
            "Partly transformed object can be generated if interpolation\n"
            "values between 0 and 1 are given(0 means no transformation)\n"
            "Alternatively a set of interpolations covering the full range\n"
	    "of transformation is computed if the number of interpolations\n"
	    "is given. For this, the output base filename and its extension\n"
	    "are must be supplied.\n"
	    "Version: %s\n"
            "Options are:\n"
            "  -h  Help, prints this usage message.\n"
            "  -t  Transform object.\n"
            "  -i  Invert the transform after reading.\n"
            "  -E  Output execution time to stderr.\n"
            "  -L  Use WLZ_INTERPOLATION_LINEAR (instead of the default\n"
	    "      WLZ_INTERPOLATION_NEAREST).\n"
            "  -x  Interpolation value, with 0 <= ivalue <= 1.\n"
            "  -o  Output object file\n"
            "  -s  Number of intermediate interpolations.\n"
            "  -b  Output object file body\n"
            "  -e  Output object file extension (default wlz)\n"
            "Parameters -x (and the auxiliary -o) respectively\n"
            "-s (and the auxiliary -b and -e) are mutually exclusive.\n"
	    "Example:\n"
            "  %s -t transform.wlz -i -o out.wlz in.wlz\n"
            "Applies the inverse transform read from transform.wlz to\n"
            "the in.wlz object and writes the result to out.wlz\n"
            "  %s -t transform.wlz -s 5 -b out_ -e wlz in.wlz\n"
            "Applies the transform read from transform.wlz to\n"
            "the in.wlz and generates out_000000.wlz ... out_000005.wlz\n"
            "with interpolation values 0, 0.2, ... 1.0\n.",
            argv[0],
	    WlzVersion(),
	    argv[0],
	    argv[0]);
  }
  return(!ok);
}