Beispiel #1
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);
}
Beispiel #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		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);
}