示例#1
0
文件: WlzExtFFStl.c 项目: dscho/Woolz
/*!
* \return	Object read from file.
* \ingroup	WlzExtFF
* \brief	Reads a Woolz object from the given stream using the
* 		stereolithography stl surface file format. This format
* 		has surface definitions defined by a name and a collection
* 		of facet normals and loops. Each facet loop has the
* 		cooordinates of it's vertices.
* 		Only triangulated surface models can be read and all solids
* 		will be treated as one.
* \param	fP			Input file stream.
* \param	dstErr			Destination error number ptr, may be
* 					NULL.
*/
WlzObject	*WlzEffReadObjStl(FILE *fP, WlzErrorNum *dstErr)
{
  int		vCnt = 0,
  		inSolid = 0,
  		inFacet = 0,
		inLoop = 0;
  char		*sav,
  		*str,
  		*tok;
  WlzDVertex3	vBuf[3];
  WlzGMModel	*model = NULL;
  WlzObject	*obj = NULL;
  WlzDomain	dom;
  WlzValues	val;
  WlzErrorNum	errNum = WLZ_ERR_NONE;
  char		cBuf[256];

  dom.core = NULL;
  val.core = NULL;
  if(fP == NULL)
  {
    errNum = WLZ_ERR_PARAM_NULL;
  }
  else
  {
    model = WlzGMModelNew(WLZ_GMMOD_3D, 0, 0, &errNum);
  }
  while((errNum == WLZ_ERR_NONE) &&
        ((str = WlzEffReadObjStlRec(fP, cBuf, 256)) != NULL))
  {
    if((tok = strtok_r(str, " \t", &sav)) != NULL)
    {
      if(strncmp(tok, "solid", 5) == 0)
      {
        if(inSolid == 0)
	{
	  inSolid = 1;
	}
	else
	{
	  errNum = WLZ_ERR_READ_INCOMPLETE;
	}
      }
      else if(strncmp(tok, "facet", 5) == 0)
      {
        if((inSolid == 1) && (inFacet == 0))
	{
	  inFacet = 1;
	  /* Normal vector is ignored. */
	}
	else
	{
	  errNum = WLZ_ERR_READ_INCOMPLETE;
	}
      }
      else if(strncmp(tok, "outer", 5) == 0)
      {
        if(((tok = strtok_r(NULL, " \t", &sav)) == NULL) ||
	   (strncmp(tok, "loop", 4) != 0) ||
           (inSolid == 0) || (inFacet == 0) || (inLoop != 0))
	{
	  errNum = WLZ_ERR_READ_INCOMPLETE;
	}
	else
	{
	  vCnt = 0;
	  inLoop = 1;
	}
      }
      else if(strncmp(tok, "vertex", 6) == 0)
      {
	char *pTok[3];

        if((vCnt < 3) &&
	   ((pTok[0] = strtok_r(NULL, " \t", &sav)) != NULL) &&
	   ((pTok[1] = strtok_r(NULL, " \t", &sav)) != NULL) &&
	   ((pTok[2] = strtok_r(NULL, " \t", &sav)) != NULL) &&
	   (sscanf(pTok[0], "%lg", &(vBuf[vCnt].vtX)) == 1) &&
	   (sscanf(pTok[1], "%lg", &(vBuf[vCnt].vtY)) == 1) &&
	   (sscanf(pTok[2], "%lg", &(vBuf[vCnt].vtZ)) == 1))
	{
	  ++vCnt;
	}
	else
	{
	  errNum = WLZ_ERR_READ_INCOMPLETE;
	}
      }
      else if(strncmp(tok, "endloop", 7) == 0)
      {
        if(inLoop == 1)
	{
	  inLoop = 0;
	  if(vCnt == 3)
	  {
	    errNum = WlzGMModelConstructSimplex3D(model, vBuf);
	  }
	  else
	  {
	    errNum = WLZ_ERR_READ_INCOMPLETE;
	  }
	}
	else
	{
	  errNum = WLZ_ERR_READ_INCOMPLETE;
	}
      }
      else if(strncmp(tok, "endfacet", 8) == 0)
      {
        if(inFacet == 1)
	{
	  inFacet = 0;
	}
	else
	{
	  errNum = WLZ_ERR_READ_INCOMPLETE;
	}
      }
      else if(strncmp(tok, "endsolid", 8) == 0)
      {
        if(inSolid == 1)
	{
	  inSolid = 0;
	}
	else
	{
	  errNum = WLZ_ERR_READ_INCOMPLETE;
	}
      }
    }
  }
  /* Create the Woolz object. */
  if(errNum == WLZ_ERR_NONE)
  {
    if((dom.ctr = WlzMakeContour(&errNum)) != NULL)
    {
      dom.ctr->model = WlzAssignGMModel(model, NULL);
      obj = WlzMakeMain(WLZ_CONTOUR, dom, val, NULL, NULL, &errNum);
    }
  }
  if(errNum != WLZ_ERR_NONE)
  {
    if(obj != NULL)
    {
      (void )WlzFreeObj(obj);
    }
    else if(dom.ctr != NULL)
    {
      (void )WlzFreeContour(dom.ctr);
    }
    else
    {
      (void )WlzGMModelFree(model);
    }
    obj = NULL;
  }
  if(dstErr)
  {
    *dstErr = errNum;
  }
  return(obj);
}
示例#2
0
/*!
* \return	A new geometric model.
* \ingroup	WlzGeoModel
* \brief	Creates a new geometric model from the given model such
* 		that no elements of the given model which intersect
* 		with elements in the knife model are included.
* 		While this code seems to work for simple models errors
* 		have been seen with complex models. The code for this
* 		function and those static functions that it calls should
* 		be considered "under construction".
* \param	given			Given model.
* \param	knife			Knife model.
* \param	dstErr			Destination error pointer, may be NULL.
*/
WlzGMModel	*WlzGMModelCut(WlzGMModel *given, WlzGMModel *knife,
			       WlzErrorNum *dstErr)
{
  int		dim = 2,
  		nBkSz,
  		nHTSz;
  WlzGMModel	*cut = NULL;
  WlzErrorNum   errNum = WLZ_ERR_NONE;
  const int	minBkSz = 1024,
  		minHTSz = 1024;

  if((given == NULL) || (knife == NULL))
  {
    errNum = WLZ_ERR_DOMAIN_NULL;
  }
  else if(given->type != knife->type)
  {
    errNum = WLZ_ERR_DOMAIN_TYPE;
  }
  else
  {
    switch(given->type)
    {
      case WLZ_GMMOD_2I: /* FALLTHROUGH */
      case WLZ_GMMOD_2D: /* FALLTHROUGH */
      case WLZ_GMMOD_2N:
        dim = 2;
	break;
      case WLZ_GMMOD_3I: /* FALLTHROUGH */
      case WLZ_GMMOD_3D: /* FALLTHROUGH */
      case WLZ_GMMOD_3N:
	dim = 3;
        break;
      default:
        errNum = WLZ_ERR_DOMAIN_TYPE;
	break;
    }
  }
  if(errNum == WLZ_ERR_NONE)
  {
    /* Make a new model. */
    if((nBkSz = given->res.vertex.numElm / 16) < minBkSz)
    {
      nBkSz = minBkSz;
    }
    if((nHTSz = given->res.vertex.numElm) < minHTSz)
    {
      nHTSz = minHTSz;
    }
    cut = WlzGMModelNew(given->type, nBkSz, nHTSz, &errNum);
  }
  if(errNum == WLZ_ERR_NONE)
  {
    if(dim == 2)
    {
      errNum = WlzGMModelCut2D(cut, given, knife);
    }
    else /* dim == 3 */
    {
      errNum = WlzGMModelCut3D(cut, given, knife);
    }
    if(errNum != WLZ_ERR_NONE)
    {
      (void )WlzGMModelFree(cut);
      cut = NULL;
    }
  }
  if(dstErr)
  {
    *dstErr = errNum;
  }
  return(cut);
}
示例#3
0
/*!
* \return	Object read from file.
* \ingroup	WlzExtFF
* \brief	Reads a Woolz object from the given stream using the
* 		stereolithography stl surface file format. This format
* 		has surface definitions defined by a name and a collection
* 		of facet normals and loops. Each facet loop has the
* 		cooordinates of it's vertices.
* 		Only triangulated surface models can be read and all solids
* 		will be treated as one.
* \param	fP			Input file stream.
* \param	dstErr			Destination error number ptr, may be
* 					NULL.
*/
WlzObject	*WlzEffReadObjStl(FILE *fP, WlzErrorNum *dstErr)
{
  int		vCnt = 0,
  		inSolid = 0,
  		inFacet = 0,
		inLoop = 0;
  char		*sav,
  		*str,
  		*tok;
  WlzDVertex3	vBuf[3];
  WlzGMModel	*model = NULL;
  WlzObject	*obj = NULL;
  WlzDomain	dom;
  WlzValues	val;
  WlzErrorNum	errNum = WLZ_ERR_NONE;
  char		buf[256];

  dom.core = NULL;
  val.core = NULL;
  if(fP == NULL)
  {
    errNum = WLZ_ERR_PARAM_NULL;
  }
  else
  {
    model = WlzGMModelNew(WLZ_GMMOD_3D, 0, 0, &errNum);
  }
  /* Read just the first 5 bytes, these will contain the string "solid" if
   * the STL file is ASCII or something else if binary. */
  if(fread(buf, sizeof(char), 5, fP) != 5)
  {
    errNum = WLZ_ERR_READ_INCOMPLETE;
  }
  else
  {
    buf[5] = '\0';
    if(strncmp(buf, "solid", 5) != 0) 		 /* Binary not ASCII */
    {
      uint32_t tIdx,
	       nT = 0;
      WlzGreyV tx = {0};

      /* Discard the remaining 75 bytes of the 80 byte header block. */
      (void )fread(buf, sizeof(char), 75, fP);
      /* Read number of triangles. */
      if(fread(buf, sizeof(char), 4, fP) != 4)
      {
	errNum = WLZ_ERR_READ_INCOMPLETE;
      }
      else
      {
	tx.bytes[0] = buf[0];
	tx.bytes[1] = buf[1];
	tx.bytes[2] = buf[2];
	tx.bytes[3] = buf[3];
	nT = (uint32_t)(tx.inv);
	if(nT < 1)
	{
	  errNum = WLZ_ERR_READ_INCOMPLETE;
	}
      }
      for(tIdx = 0; (errNum == WLZ_ERR_NONE) && (tIdx < nT); ++tIdx)
      {
	if(fread(buf, sizeof(char), 50, fP) != 50)
	{
	  errNum = WLZ_ERR_READ_INCOMPLETE;
	}
	else
	{
	  int	vIdx;
	  size_t bOff = 12;

	  for(vIdx = 0; vIdx < 3; ++vIdx)
	  {
	    tx.bytes[0] = buf[bOff++];
	    tx.bytes[1] = buf[bOff++];
	    tx.bytes[2] = buf[bOff++];
	    tx.bytes[3] = buf[bOff++];
	    vBuf[vIdx].vtX = tx.flv;
	    tx.bytes[0] = buf[bOff++];
	    tx.bytes[1] = buf[bOff++];
	    tx.bytes[2] = buf[bOff++];
	    tx.bytes[3] = buf[bOff++];
	    vBuf[vIdx].vtY = tx.flv;
	    tx.bytes[0] = buf[bOff++];
	    tx.bytes[1] = buf[bOff++];
	    tx.bytes[2] = buf[bOff++];
	    tx.bytes[3] = buf[bOff++];
	    vBuf[vIdx].vtZ = tx.flv;

	  }
	  errNum = WlzGMModelConstructSimplex3D(model, vBuf);
	}
      }
    }
    else						 /* ASCII not binary */
    {
      /* Discard rest of the first line. */
      (void )WlzEffReadObjStlRec(fP, buf, 256);
      /* Read and parse ACSII records. */
      inSolid = 1;
      while((errNum == WLZ_ERR_NONE) &&
	    ((str = WlzEffReadObjStlRec(fP, buf, 256)) != NULL))
      {
	if((tok = ALC_STRTOK_R(str, " \t", &sav)) != NULL)
	{
	  if(strncmp(tok, "solid", 5) == 0)
	  {
	    if(inSolid == 0)
	    {
	      inSolid = 1;
	    }
	    else
	    {
	      errNum = WLZ_ERR_READ_INCOMPLETE;
	    }
	  }
	  else if(strncmp(tok, "facet", 5) == 0)
	  {
	    if((inSolid == 1) && (inFacet == 0))
	    {
	      inFacet = 1;
	      /* Normal vector is ignored. */
	    }
	    else
	    {
	      errNum = WLZ_ERR_READ_INCOMPLETE;
	    }
	  }
	  else if(strncmp(tok, "outer", 5) == 0)
	  {
	    if(((tok = ALC_STRTOK_R(NULL, " \t", &sav)) == NULL) ||
	       (strncmp(tok, "loop", 4) != 0) ||
	       (inSolid == 0) || (inFacet == 0) || (inLoop != 0))
	    {
	      errNum = WLZ_ERR_READ_INCOMPLETE;
	    }
	    else
	    {
	      vCnt = 0;
	      inLoop = 1;
	    }
	  }
	  else if(strncmp(tok, "vertex", 6) == 0)
	  {
	    char *pTok[3];

	    if((vCnt < 3) &&
	       ((pTok[0] = ALC_STRTOK_R(NULL, " \t", &sav)) != NULL) &&
	       ((pTok[1] = ALC_STRTOK_R(NULL, " \t", &sav)) != NULL) &&
	       ((pTok[2] = ALC_STRTOK_R(NULL, " \t", &sav)) != NULL) &&
	       (sscanf(pTok[0], "%lg", &(vBuf[vCnt].vtX)) == 1) &&
	       (sscanf(pTok[1], "%lg", &(vBuf[vCnt].vtY)) == 1) &&
	       (sscanf(pTok[2], "%lg", &(vBuf[vCnt].vtZ)) == 1))
	    {
	      ++vCnt;
	    }
	    else
	    {
	      errNum = WLZ_ERR_READ_INCOMPLETE;
	    }
	  }
	  else if(strncmp(tok, "endloop", 7) == 0)
	  {
	    if(inLoop == 1)
	    {
	      inLoop = 0;
	      if(vCnt == 3)
	      {
		errNum = WlzGMModelConstructSimplex3D(model, vBuf);
	      }
	      else
	      {
		errNum = WLZ_ERR_READ_INCOMPLETE;
	      }
	    }
	    else
	    {
	      errNum = WLZ_ERR_READ_INCOMPLETE;
	    }
	  }
	  else if(strncmp(tok, "endfacet", 8) == 0)
	  {
	    if(inFacet == 1)
	    {
	      inFacet = 0;
	    }
	    else
	    {
	      errNum = WLZ_ERR_READ_INCOMPLETE;
	    }
	  }
	  else if(strncmp(tok, "endsolid", 8) == 0)
	  {
	    if(inSolid == 1)
	    {
	      inSolid = 0;
	    }
	    else
	    {
	      errNum = WLZ_ERR_READ_INCOMPLETE;
	    }
	  }
	}
      }
    }
  }
  /* Create the Woolz object. */
  if(errNum == WLZ_ERR_NONE)
  {
    if((dom.ctr = WlzMakeContour(&errNum)) != NULL)
    {
      dom.ctr->model = WlzAssignGMModel(model, NULL);
      obj = WlzMakeMain(WLZ_CONTOUR, dom, val, NULL, NULL, &errNum);
    }
  }
  if(errNum != WLZ_ERR_NONE)
  {
    if(obj != NULL)
    {
      (void )WlzFreeObj(obj);
    }
    else if(dom.ctr != NULL)
    {
      (void )WlzFreeContour(dom.ctr);
    }
    else
    {
      (void )WlzGMModelFree(model);
    }
    obj = NULL;
  }
  if(dstErr)
  {
    *dstErr = errNum;
  }
  return(obj);
}
示例#4
0
int             main(int argc, char **argv)
{
  int           idR,
  		nRec,
  		nFld,
		option,
  		ok = 1,
		usage = 0;
  FILE		*fP = NULL;
  char		*inFileStr,
  		*outObjFileStr;
  double	**bufD = NULL;
  WlzGMModelType modelType = WLZ_GMMOD_2D;
  WlzDVertex2	bufD2[2];
  WlzDVertex3	bufD3[3];
  WlzObject     *outObj = NULL;
  WlzDomain	ctrDom;
  WlzValues	dumVal;
  WlzGMModel	*model = NULL;
  WlzErrorNum   errNum = WLZ_ERR_NONE;
  const char	*errMsgStr;
  static char	optList[] = "23diho:";
  const char	outObjFileStrDef[] = "-",
  		inFileStrDef[] = "-";

  opterr = 0;
  ctrDom.core = NULL;
  dumVal.core = NULL;
  outObjFileStr = (char *)outObjFileStrDef;
  inFileStr = (char *)inFileStrDef;
  while(ok && ((option = getopt(argc, argv, optList)) != -1))
  {
    switch(option)
    {
      case '2':
	switch(modelType)
	{
	  case WLZ_GMMOD_2I: /* FALLTHROUGH */
	  case WLZ_GMMOD_2D:
	    break;
	  case WLZ_GMMOD_3I:
	    modelType = WLZ_GMMOD_2I;
	    break;
	  case WLZ_GMMOD_3D:
	    modelType = WLZ_GMMOD_2D;
	    break;
	  default:
	    break;
	}
	break;
      case '3':
	switch(modelType)
	{
	  case WLZ_GMMOD_2I:
	    modelType = WLZ_GMMOD_3I;
	    break;
	  case WLZ_GMMOD_2D:
	    modelType = WLZ_GMMOD_3D;
	    break;
	  case WLZ_GMMOD_3I: /* FALLTHROUGH */
	  case WLZ_GMMOD_3D:
	    break;
	  default:
	    break;
	}
	break;
      case 'd':
	switch(modelType)
	{
	  case WLZ_GMMOD_2I:
	    modelType = WLZ_GMMOD_2D;
	  case WLZ_GMMOD_2D:
	    break;
	  case WLZ_GMMOD_3I:
	    modelType = WLZ_GMMOD_3D;
	    break;
	  case WLZ_GMMOD_3D:
	    break;
	  default:
	    break;
	}
	break;
      case 'i':
	switch(modelType)
	{
	  case WLZ_GMMOD_2I:
	    break;
	  case WLZ_GMMOD_2D:
	    modelType = WLZ_GMMOD_2I;
	    break;
	  case WLZ_GMMOD_3I:
	    break;
	  case WLZ_GMMOD_3D:
	    modelType = WLZ_GMMOD_3I;
	    break;
	  default:
	    break;
	}
	break;
      case 'h':
        usage = 1;
	ok = 0;
	break;
      case 'o':
        outObjFileStr = optarg;
	break;
      default:
        usage = 1;
	ok = 0;
	break;
    }
  }
  if(ok)
  {
    if((inFileStr == NULL) || (*inFileStr == '\0') ||
       (outObjFileStr == NULL) || (*outObjFileStr == '\0'))
    {
      ok = 0;
      usage = 1;
    }
    if(ok && (optind < argc))
    {
      if((optind + 1) != argc)
      {
        usage = 1;
	ok = 0;
      }
      else
      {
        inFileStr = *(argv + optind);
      }
    }
  }
  if(ok)
  {
    if((inFileStr == NULL) ||
       (*inFileStr == '\0') ||
       ((fP = (strcmp(inFileStr, "-")?
	      fopen(inFileStr, "r"): stdin)) == NULL) ||
       (AlcDouble2ReadAsci(fP, &bufD, (size_t *) &nRec, (size_t *) &nFld) != ALC_ER_NONE))
    {
      ok = 0;
      (void )fprintf(stderr,
		     "%s: failed to read from file %s\n",
		     *argv, inFileStr);
    }
    if(fP && strcmp(inFileStr, "-"))
    {
      fclose(fP);
    }
  }
  if(ok)
  {
    ctrDom.ctr = WlzMakeContour(&errNum);
    if(errNum == WLZ_ERR_NONE)
    {
      ctrDom.ctr->model = model = WlzAssignGMModel(
      		   WlzGMModelNew(modelType, 0, 0, &errNum), NULL);
    }
    if(errNum != WLZ_ERR_NONE)
    {
      ok = 0;
      (void )WlzStringFromErrorNum(errNum, &errMsgStr);
      (void )fprintf(stderr,
      		     "%s: Failed to make contour (%s).\n",
      	     	     argv[0], errMsgStr);
    }
  }
  if(ok)
  {
    switch(modelType)
    {
      case WLZ_GMMOD_2I: /* FALLTHROUGH */
      case WLZ_GMMOD_2D:
	if(nFld != 4)
	{
	  ok = 0;
	}
	break;
      case WLZ_GMMOD_3I: /* FALLTHROUGH */
      case WLZ_GMMOD_3D:
	if(nFld != 9)
	{
	  ok = 0;
	}
	break;
      default:
	break;
    }
    if(ok == 0)
    {
      (void )fprintf(stderr,
      		     "%s: Failed to read simplicies (syntax error).\n",
		     argv[0]);
    }
  }
  if(ok)
  {
    idR = 0;
    while((errNum == WLZ_ERR_NONE) && (idR < nRec))
    {
      switch(modelType)
      {
        case WLZ_GMMOD_2I: /* FALLTHROUGH */
        case WLZ_GMMOD_2D:
          bufD2[0].vtX = *(*(bufD + idR) + 0);
          bufD2[0].vtY = *(*(bufD + idR) + 1);
          bufD2[1].vtX = *(*(bufD + idR) + 2);
          bufD2[1].vtY = *(*(bufD + idR) + 3);
	  errNum = WlzGMModelConstructSimplex2D(model, bufD2);
	  break;
        case WLZ_GMMOD_3I: /* FALLTHROUGH */
        case WLZ_GMMOD_3D:
          bufD3[0].vtX = *(*(bufD + idR) + 0);
          bufD3[0].vtY = *(*(bufD + idR) + 1);
          bufD3[0].vtZ = *(*(bufD + idR) + 2);
          bufD3[1].vtX = *(*(bufD + idR) + 3);
          bufD3[1].vtY = *(*(bufD + idR) + 4);
          bufD3[1].vtZ = *(*(bufD + idR) + 5);
          bufD3[2].vtX = *(*(bufD + idR) + 6);
          bufD3[2].vtY = *(*(bufD + idR) + 7);
          bufD3[2].vtZ = *(*(bufD + idR) + 8);
	  errNum = WlzGMModelConstructSimplex3D(model, bufD3);
	  break;
	default:
	  break;
      }
      ++idR;
    }
    if(errNum != WLZ_ERR_NONE)
    {
      ok = 0;
      (void )WlzStringFromErrorNum(errNum, &errMsgStr);
      (void )fprintf(stderr,
      		     "%s: Failed to build model (%s).\n",
		     argv[0], errMsgStr);
    }
  }
  if(ok)
  {
    if((fP = (strcmp(outObjFileStr, "-")?
	     fopen(outObjFileStr, "w"): stdout)) == NULL)
    {
      ok = 0;
      (void )fprintf(stderr,
      		     "%s: Failed to open output file %s.\n",
      	      	     argv[0], outObjFileStr);
    }
  }
  if(ok)
  {
    outObj = WlzMakeMain(WLZ_CONTOUR, ctrDom, dumVal, NULL, NULL, &errNum);
    if(errNum != WLZ_ERR_NONE)
    {
      ok = 0;
      (void )WlzStringFromErrorNum(errNum, &errMsgStr);
      (void )fprintf(stderr,
      		     "%s: Failed to create output woolz object (%s).\n",
		     argv[0], errMsgStr);
    }
  }
  if(ok)
  {
    errNum = WlzWriteObj(fP, outObj);
    if(errNum != WLZ_ERR_NONE)
    {
      ok = 0;
      (void )WlzStringFromErrorNum(errNum, &errMsgStr);
      (void )fprintf(stderr,
      		     "%s: Failed to write output object (%s).\n",
      		     argv[0], errMsgStr);
    }
  }
  if(bufD)
  {
    (void )AlcDouble2Free(bufD);
  }
  if(outObj)
  {
    (void )WlzFreeObj(outObj);
  }
  else if(ctrDom.ctr)
  {
    (void )WlzFreeContour(ctrDom.ctr);
  }
  if(fP && strcmp(outObjFileStr, "-"))
  {
    (void )fclose(fP);
  }
  if(usage)
  {
      (void )fprintf(stderr,
      "Usage: %s%s%s%sExample: %s%s",
      *argv,
      " [-o<output object>] [-h] [-2] [-3] [-d] [-i] [-o#] \n"
      "        [<input data>]\n"
      "Version: ",
      WlzVersion(),
      "\n"
      "Options:\n"
      "  -h  Prints this usage information.\n"
      "  -o  Output object file name.\n"
      "  -2  Build a 2D contour.\n"
      "  -3  Build a 3D contour.\n"
      "  -d  Build a contour with double floating point geometry.\n"
      "  -i  Build a contour with integer geometry.\n"
      "Builds a contour from the given input simplicies.\n"
      "The input data are read from stdin and the output object is written\n"
      "to stdout unless filenames are given.\n",
      *argv,
      " -d -2 -o tri.wlz\n"
      "0.0 0.0 1.0 0.0\n"
      "1.0 0.0 0.5 0.866025\n"
      "0.5 0.866025 0.0 0.0\n"
      "<eof>\n"
      "A 2D triangle is built from the three simplicies read from the\n"
      "standard input and the contour is written to tri.wlz.\n");
  }
  return(!ok);
}