Пример #1
0
/*! 
* \ingroup      WlzAllocation
* \brief        Free's a WlzContour data structure.
*
* \return       Error number, values: WLZ_ERR_NONE, WLZ_ERR_DOMAIN_NULL, WLZ_ERR_DOMAIN_TYPE and from WlzUnlink().
* \param    ctr				Contour to be freed.
* \par      Source:
*                WlzFreeSpace.c
*/
WlzErrorNum	WlzFreeContour(WlzContour *ctr)
{
  WlzErrorNum	errNum = WLZ_ERR_NONE;

  if(ctr == NULL)
  {
    errNum = WLZ_ERR_DOMAIN_NULL;
  }
  else if(ctr->type != WLZ_CONTOUR)
  {
    errNum = WLZ_ERR_DOMAIN_TYPE;
  }
  else
  {
    if(WlzUnlink(&(ctr->linkcount), &errNum))
    {
      if(ctr->model && WlzUnlink(&(ctr->model->linkcount), &errNum))
      {
        (void )WlzGMModelFree(ctr->model);
      }
      AlcFree((void *)ctr);
    }
  }
  return(errNum);
}
Пример #2
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		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);
}
Пример #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
/*!
* \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);
}
Пример #5
0
int		main(int argc, char *argv[])
{
  int		ok,
  		option,
		usage = 0;
  FILE		*fP = NULL;
  WlzDomain	oDom;
  WlzValues	oVal;
  char		*mFileStr,
  		*kFileStr,
		*oFileStr;
  WlzObject	*mObj = NULL,
		*kObj = NULL,
		*oObj = NULL;
  WlzErrorNum	errNum = WLZ_ERR_NONE;
  const char	*errMsgStr;
  static char	optList[] = "hk:o:";
  const char    fileStrDef[] = "-";

  oDom.core = NULL;
  oVal.core = NULL;
  /* Parse the argument list and check for input files. */
  opterr = 0;
  mFileStr = (char *)fileStrDef;
  kFileStr = (char *)fileStrDef;
  oFileStr = (char *)fileStrDef;
  while((option = getopt(argc, argv, optList)) != EOF)
  {
    switch(option)
    {
      case 'k':
	kFileStr = optarg;
	break;
      case 'o':
	oFileStr = optarg;
	break;
      case 'h':
      default:
	usage = 1;
	break;
    }
  }
  ok = !usage;
  if(ok && (optind < argc))
  {
    if((optind + 1) != argc)
    {
      usage = 1;
      ok = 0;
    }
    else
    {
      mFileStr = argv[optind];
    }
  }
  /* Read the model contour object. */
  if(ok)
  {
    if((mFileStr == NULL) ||
       (*mFileStr == '\0') ||
       ((fP = (strcmp(mFileStr, "-")?
              fopen(mFileStr, "r"): stdin)) == NULL) ||
       ((mObj = WlzAssignObject(WlzReadObj(fP, &errNum), NULL)) == NULL))
    {
      ok = 0;
      (void )fprintf(stderr,
                     "%s: Failed to read model contour object from file %s.\n",
                     argv[0], mFileStr);
    }
    if(fP && strcmp(mFileStr, "-"))
    {
      (void )fclose(fP); fP = NULL;
    }
  }
  /* Read the knife object. */
  if(ok)
  {
    if((kFileStr == NULL) ||
       (*kFileStr == '\0') ||
       ((fP = (strcmp(kFileStr, "-")?
              fopen(kFileStr, "r"): stdin)) == NULL) ||
       ((kObj = WlzAssignObject(WlzReadObj(fP, &errNum), NULL)) == NULL))
    {
      ok = 0;
      (void )fprintf(stderr,
                     "%s: Failed to read knife contour object from file %s.\n",
                     argv[0], kFileStr);
    }
    if(fP && strcmp(kFileStr, "-"))
    {
      (void )fclose(fP); fP = NULL;
    }
  }
  if(ok)
  {
    oDom.ctr = WlzMakeContour(&errNum);
    switch(kObj->type)
    {
      case WLZ_2D_DOMAINOBJ: /* FALLTHROUGH */
      case WLZ_3D_DOMAINOBJ:
	if(errNum == WLZ_ERR_NONE)
	{
	  oDom.ctr->model = WlzGMModelCutDom(mObj->domain.ctr->model,
					     kObj, &errNum);
	}
	break;
      case WLZ_CONTOUR:
	if(errNum == WLZ_ERR_NONE)
	{
	  oDom.ctr->model = WlzGMModelCut(mObj->domain.ctr->model,
					  kObj->domain.ctr->model, &errNum);
	}
	break;
      default:
        errNum = WLZ_ERR_OBJECT_TYPE;
	break;
    }
    if(errNum == WLZ_ERR_NONE)
    {
      oObj = WlzMakeMain(WLZ_CONTOUR, oDom, oVal, NULL, NULL, &errNum);
    }
    if(errNum != WLZ_ERR_NONE)
    {
      if(oDom.ctr != NULL)
      {
	(void )WlzFreeContour(oDom.ctr);
      }
      else if(oDom.ctr->model != NULL)
      {
	(void )WlzGMModelFree(oDom.ctr->model);
      }
      ok = 0;
      (void )WlzStringFromErrorNum(errNum, &errMsgStr);
      (void )fprintf(stderr,
                     "%s: Failed to cut contour (%s).\n",
		     argv[0], errMsgStr);
    }
  }
  if(ok)
  {
    if((fP = (strcmp(oFileStr, "-")?
	     fopen(oFileStr, "w"): stdout)) == NULL)
    {
      ok = 0;
      (void )fprintf(stderr,
                     "%s: Failed to open output file %s.\n",
                     argv[0], oFileStr);
    }
  }
  if(ok)
  {
    errNum = WlzWriteObj(fP, oObj);
    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(fP && strcmp(oFileStr, "-"))
  {
      (void )fclose(fP);
  }
  (void )WlzFreeObj(mObj);
  (void )WlzFreeObj(kObj);
  (void )WlzFreeObj(oObj);
  if(usage)
  {
    (void )fprintf(stderr,
    "Usage: %s [-k <knife>] [-o <out>] [-h] [<model>]\n"
    "Given model and knife contours; creates a new contour which consists\n"
    "of all simplices of the model that do not intersect simplices of the\n"
    "knife. This may be used to cut into a contour removing sections from\n"
    "it.\n"
    "Options are:\n"
    "  -k  The knife contour object.\n"
    "  -o  Output object file.\n"
    "  -h  Help - prints this usage message\n",
    argv[0]);
  }
  return(!ok);
}