コード例 #1
0
ファイル: WlzGeoModelCut.c プロジェクト: dscho/Woolz
/*!
* \return	Woolz error code.
* \ingroup	WlzGeoModel
* \brief	Copies elements from the given model to the cut model on
* 		the condition that the elements do not intersects any
* 		elements of the knide model.
* 		All models are assumed to be valid 3D models.
* \param	given			Given model.
* \param	knife			Knife model.
* \param	dstErr			Destination error pointer, may be NULL.
*/
static WlzErrorNum WlzGMModelCut3D(WlzGMModel *cut, WlzGMModel *given,
				   WlzGMModel *knife)
{
  WlzGMGridWSp3D *kGrid = NULL;
  WlzErrorNum   errNum = WLZ_ERR_NONE;

  if((cut == NULL) || (knife == NULL) || (given == NULL))
  {
    errNum = WLZ_ERR_DOMAIN_NULL;
  }
  else
  {
    int cutDim,
    	givenDim,
    	knifeDim;

    cutDim = WlzGMModelGetDimension(cut, NULL);
    givenDim = WlzGMModelGetDimension(given, NULL);
    knifeDim = WlzGMModelGetDimension(knife, NULL);
    if((cutDim != 3) || (givenDim != 3) || (knifeDim != 3))
    {
      errNum = WLZ_ERR_DOMAIN_TYPE;
    }
  }
  /* Create a cell grid workspace for the knife model. */
  if(errNum == WLZ_ERR_NONE)
  {
    kGrid = WlzGeoModelGridWSpNew3D(knife, WLZ_GMELM_FACE, &errNum);
  }
  /* For each face of the given model, if it does not intersect a face of
   * the knife model then add it to the new cut model. */
  if(errNum == WLZ_ERR_NONE)
  {
    int idF,
        idX,
	idY,
	idZ,
    	gMaxF;
    AlcVector *gFVec;

    gMaxF = given->res.face.numIdx;
    gFVec = given->res.face.vec;
    for(idF = 0; idF < gMaxF; ++idF)
    {
      WlzGMFace *gFace;

      gFace = (WlzGMFace *)AlcVectorItemGet(gFVec, idF);
      if(gFace->idx >= 0)
      {
        int	add = 1;
	WlzDVertex3 gVtx[3];
	WlzIBox3 cBox;
	WlzDBox3 fBox;

	(void )WlzGMFaceGetG3D(gFace, gVtx + 0, gVtx + 1, gVtx + 2);
	fBox = WlzBoundingBoxVtx3D(3, gVtx, NULL);
	cBox = WlzGeoModelGridCellsInDBox(kGrid, fBox);
	/* For each cell that the bonding box intersects. */
        for(idZ = cBox.zMin; idZ <= cBox.zMax; ++idZ)
        {
          WlzDVertex3 kCellMin,
                      kCellMax;

          kCellMin.vtZ = kGrid->org.vtZ + kGrid->cellSz * idZ;
          kCellMax.vtZ = kGrid->org.vtZ + kGrid->cellSz * (idZ + 1);
          for(idY = cBox.yMin; idY <= cBox.yMax; ++idY)
          {
            kCellMin.vtY = kGrid->org.vtY + kGrid->cellSz * idY;
            kCellMax.vtY = kGrid->org.vtY + kGrid->cellSz * (idY + 1);
            for(idX = cBox.xMin; idX <= cBox.xMax; ++idX)
            {
	      WlzDVertex3 kVtx[3];
	      WlzGMGridWSpCell3D *kCell;

              kCellMin.vtX = kGrid->org.vtX + kGrid->cellSz * idX;
              kCellMax.vtX = kGrid->org.vtX + kGrid->cellSz * (idX + 1);
              /* Test if the face of the given model intersects the faces
	       * of the knife grid cells. */
	      kCell = *(*(*(kGrid->cells + idZ) + idY) + idX);
	      while(kCell != NULL)
	      {
		WlzGMFace *kFace;

		kFace = kCell->elem.face;
		(void )WlzGMFaceGetG3D(kFace, kVtx + 0, kVtx + 1, kVtx + 2);
		if(WlzGeomTriangleTriangleIntersect3D(
		                  gVtx[0], gVtx[1], gVtx[2],
		                  kVtx[0], kVtx[1], kVtx[2]) != 0)
		{
		  add = 0;
		  idX = cBox.xMax + 1;            /* Break from these loops. */
		  idY = cBox.yMax + 1;
		  idZ = cBox.zMax + 1;
		  break;
		}
		if(errNum != WLZ_ERR_NONE)
		{
		  goto RETURN;
		}
	        kCell = kCell->next;
	      }
            }
	  }
	}
	if(add)
	{
	  /* Given model face does not intersect the knife model face
	   * so just add it to the cut model. */
	  errNum = WlzGMModelConstructSimplex3D(cut, gVtx);
	}
      }
    }
  }
RETURN:
  if(kGrid)
  {
    (void )WlzGeoModelGridFree3D(kGrid);
  }
  return(errNum);
}
コード例 #2
0
ファイル: WlzExtFFEMT.c プロジェクト: VirtualFlyBrain/Woolz
/*!
* \return	Object read from file.
* \ingroup	WlzExtFF
* \brief	Reads a Woolz object from the given stream using the
* 		GRUMMP vmesh tetrahedral mesh file format.
* \param	fP			Input file stream.
* \param	dstErr			Destination error number ptr, may be
* 					NULL.
*/
WlzObject	*WlzEffReadObjEMT(FILE *fP, WlzErrorNum *dstErr)
{
  int		nElm = 0,
		nNod = 0;
  char		*str;
  WlzDVertex3   *vBuf = NULL;
  WlzCMesh3D	*mesh = NULL;
  WlzObject	*obj = NULL;
  WlzErrorNum	errNum = WLZ_ERR_NONE;
  char		cBuf[256];

  if(fP == NULL)
  {
    errNum = WLZ_ERR_PARAM_NULL;
  }
  else
  {
    int		idC = 0;

    /* Optional records may be comments starting with a '#' but apart
     * from these the first line should have a single integer specifying
     * the number of nodes. */
    do
    {
      if((str = WlzEffReadObjEMTRec(fP, cBuf, 256)) == NULL)
      {
	errNum = WLZ_ERR_READ_INCOMPLETE;
      }
      else if(*str != '#')
      {
	if((idC = sscanf(str, "%d", &nNod)) != 1)
	{
	  errNum = WLZ_ERR_READ_INCOMPLETE;
	}
      }
    } while((errNum == WLZ_ERR_NONE) && (idC != 1));
  }
  /* Check for reasonable number of nodes. */
  if(errNum == WLZ_ERR_NONE)
  {
    if(nNod <= 0)
    {
      errNum = WLZ_ERR_READ_INCOMPLETE;
    }
  }
  /* Create a new 3D constrained mesh. */
  if(errNum == WLZ_ERR_NONE)
  {
    mesh = WlzCMeshNew3D(&errNum);
  }
  /* Read in the node positions into a temporary buffer computing their
   * bounding box and then create the nodes. */
  if(errNum == WLZ_ERR_NONE)
  {
    if((vBuf = AlcMalloc(sizeof(WlzDVertex3) * nNod)) == NULL)
    {
      errNum = WLZ_ERR_MEM_ALLOC;
    }
  }
  if(errNum == WLZ_ERR_NONE)
  {
    int		idN = 0;

    while(idN < nNod)
    {
      if((str = WlzEffReadObjEMTRec(fP, cBuf, 256)) == NULL)
      {
	errNum = WLZ_ERR_READ_INCOMPLETE;
	break;
      }
      else if(*str != '#')
      {
	if(sscanf(str, "%lg %lg %lg",
		  &(vBuf[idN].vtX), &(vBuf[idN].vtY), &(vBuf[idN].vtZ)) != 3)
	{
	  errNum = WLZ_ERR_READ_INCOMPLETE;
	  break;
	}
	++idN;
      }
    }
  }
  if(errNum == WLZ_ERR_NONE)
  {
    mesh->bBox = WlzBoundingBoxVtx3D(nNod, vBuf, NULL);
    if(AlcVectorExtendAndGet(mesh->res.nod.vec, nNod) == NULL)
    {
      errNum = WLZ_ERR_MEM_ALLOC;
    }
  }
  if(errNum == WLZ_ERR_NONE)
  {
    errNum = WlzCMeshReassignGridCells3D(mesh, nNod);
  }
  if(errNum == WLZ_ERR_NONE)
  {
    int		idN;

    for(idN = 0; idN < nNod; ++idN)
    {
       (void )WlzCMeshNewNod3D(mesh, vBuf[idN], NULL);
    }
  }
  AlcFree(vBuf);
  /* Read the number of elements in the mesh. */
  if(errNum == WLZ_ERR_NONE)
  {
    int		idC = 0;

    /* Optional records may be comments starting with a '#' but apart
     * from these the first line should have a single integer specifying
     * the number of nodes. */
    do
    {
      if((str = WlzEffReadObjEMTRec(fP, cBuf, 256)) == NULL)
      {
	errNum = WLZ_ERR_READ_INCOMPLETE;
      }
      else if(*str != '#')
      {
	if((idC = sscanf(str, "%d", &nElm)) != 1)
	{
	  errNum = WLZ_ERR_READ_INCOMPLETE;
	}
      }
    } while((errNum == WLZ_ERR_NONE) && (idC != 1));
  }
  /* Check for reasonable number of elements. */
  if(errNum == WLZ_ERR_NONE)
  {
    if(nElm <= 0)
    {
      errNum = WLZ_ERR_READ_INCOMPLETE;
    }
  }
  /* Allocate room for the elements in the mesh. */
  if(errNum == WLZ_ERR_NONE)
  {
    if(AlcVectorExtendAndGet(mesh->res.elm.vec, nElm) == NULL)
    {
      errNum = WLZ_ERR_MEM_ALLOC;
    }
  }
  /* Read the elements adding them to the mesh. */
  if(errNum == WLZ_ERR_NONE)
  {
    int		idE = 0;

    while(idE < nElm)
    {
      if((str = WlzEffReadObjEMTRec(fP, cBuf, 256)) == NULL)
      {
	errNum = WLZ_ERR_READ_INCOMPLETE;
	break;
      }
      else if(*str != '#')
      {
	int	dummyI;
	int	nIdx[4];
	WlzCMeshNod3D *nBuf[4];

	if((sscanf(str, "%d %d %d %d %d",
		   &dummyI,
		   &(nIdx[0]), &(nIdx[1]), &(nIdx[2]), &(nIdx[3])) != 5) ||
	   (nIdx[0] <= 0) || (nIdx[0] > nNod) ||
	   (nIdx[1] <= 0) || (nIdx[1] > nNod) ||
	   (nIdx[2] <= 0) || (nIdx[2] > nNod) ||
	   (nIdx[3] <= 0) || (nIdx[3] > nNod))
	{
	  errNum = WLZ_ERR_READ_INCOMPLETE;
	  break;
	}
	else
	{
	  int	idN;

	  for(idN = 0; idN < 4; ++idN)
	  {
	    nBuf[idN] = (WlzCMeshNod3D *)
			AlcVectorItemGet(mesh->res.nod.vec, nIdx[idN] - 1);
	  }
	  (void )WlzCMeshNewElm3D(mesh, nBuf[0], nBuf[1], nBuf[3], nBuf[2], 1,
				  &errNum);
	  if(errNum != WLZ_ERR_NONE)
	  {
	    break;
	  }
	  ++idE;
	}
      }
    }
  }
  /* Ignore the boundary faces in the file, they're redundant information. */
  if(errNum == WLZ_ERR_NONE)
  {
    WlzDomain	dom;
    WlzValues	val;

    val.core = NULL;
    dom.cm3 = mesh;
    WlzCMeshDelUnusedNodes3D(mesh);
    WlzCMeshUpdateMaxSqEdgLen3D(mesh);
    obj = WlzMakeMain(WLZ_CMESH_3D, dom, val, NULL, NULL, &errNum);
  }
  if(errNum != WLZ_ERR_NONE)
  {
    (void )WlzCMeshFree3D(mesh);
  }
  if(dstErr)
  {
    *dstErr = errNum;
  }
  return(obj);
}
コード例 #3
0
ファイル: WlzContourFromPoints.c プロジェクト: dscho/Woolz
int             main(int argc, char **argv)
{
  int		dim = 3,
  		nSPts,
  		nIPts,
		nOPts,
		option,
		planeFlg = 0,
		planeIdx = 0,
		ok = 1,
		usage = 0;
  double	delta,
  		tau,
		sAlpha,
		iAlpha,
		oAlpha,
		iDist,
		oDist,
		samFac = 1.0;
  WlzObject 	*dObj = NULL;
  WlzBox	bBox0,
  		bBox1;
  WlzVertexP	sPts,
  		iPts,
		oPts;
  WlzPixelV	bgdV;
  WlzDomain	outDom;
  WlzValues	dumVal;
  WlzObject	*outObj = NULL;
  FILE		*fP = NULL;
  WlzErrorNum	errNum = WLZ_ERR_NONE;
  char 		*sFileStr,
  		*iFileStr,
  		*oFileStr,
		*outObjFileStr;
  const char    *errMsg;
  static char	optList[] = "h23o:S:I:O:a:b:c:d:e:D:M:T:X:",
		defFileStr[] = "-";

  bgdV.type = WLZ_GREY_DOUBLE;
  outDom.core = NULL;
  dumVal.core = NULL;
  sPts.v = iPts.v = oPts.v = NULL;
  /* Parse the command line. */
  opterr = 0;
  sFileStr = iFileStr = oFileStr = outObjFileStr = defFileStr;
  while(ok && ((option = getopt(argc, argv, optList)) != -1))
  {
    switch(option)
    {
      case '2':
        dim = 2;
	break;
      case '3':
        dim = 3;
	break;
      case 'o':
        outObjFileStr = optarg;
	break;
      case 'S':
        sFileStr = optarg;
	break;
      case 'I':
        iFileStr = optarg;
	break;
      case 'O':
        oFileStr = optarg;
	break;
      case 'a':
        if(sscanf(optarg, "%lg", &sAlpha) != 1)
	{
	  usage = 1;
	}
	break;
      case 'b':
        if(sscanf(optarg, "%lg", &iAlpha) != 1)
	{
	  usage = 1;
	}
	break;
      case 'c':
        if(sscanf(optarg, "%lg", &oAlpha) != 1)
	{
	  usage = 1;
	}
	break;
      case 'd':
        if(sscanf(optarg, "%lg", &iDist) != 1)
	{
	  usage = 1;
	}
	break;
      case 'e':
        if(sscanf(optarg, "%lg", &oDist) != 1)
	{
	  usage = 1;
	}
	break;
      case 'D':
        if(sscanf(optarg, "%lg", &delta) != 1)
	{
	  usage = 1;
	}
	break;
      case 'M':
        if(sscanf(optarg, "%lg", &samFac) != 1)
	{
	  usage = 1;
	}
	break;
      case 'T':
        if(sscanf(optarg, "%lg", &tau) != 1)
	{
	  usage = 1;
	}
	break;
      case 'X':
        if(sscanf(optarg, "%d", &planeIdx) != 1)
	{
	  usage = 1;
	}
	else
	{
	  planeFlg = 1;
	}
	break;
      case 'h':
      default:
        usage = 1;
	break;
    }
  }
  if(ok && (optind < argc))
  {
    usage = 1;
  }
  if((outObjFileStr == NULL) || (*outObjFileStr == '\0') ||
     (sFileStr == NULL) || (*sFileStr == '\0') ||
     (iFileStr == NULL) || (*iFileStr == '\0') ||
     (oFileStr == NULL) || (*oFileStr == '\0'))
  {
    usage = 1;
  }
  ok = ok && !usage;
  /* Read the surface, inside and outside points. */
  if(ok)
  {
    if(strcmp(sFileStr, "-"))
    {
      if((fP = fopen(sFileStr, "r")) == NULL)
      {
	ok = 0;
	errNum = WLZ_ERR_READ_EOF;
	(void )WlzStringFromErrorNum(errNum, &errMsg);
	(void )fprintf(stderr,
		       "%s: failed to open surface points file %s (%s).\n",
		       *argv, sFileStr, errMsg);
      }
    }
    else
    {
      fP = stdin;
    }
  }
  if(ok)
  {
    sPts = WlzCFPReadVtxArray(fP, dim, &nSPts, &errNum);
    if(errNum != WLZ_ERR_NONE)
    {
      ok = 0;
      (void )WlzStringFromErrorNum(errNum, &errMsg);
      (void )fprintf(stderr,
	             "%s: failed to read points from file %s (%s).\n",
		     *argv, sFileStr, errMsg);
    }
  }
  if(fP)
  {
    if(strcmp(sFileStr, "-"))
    {
      (void )fclose(fP);
    }
    fP = NULL;
  }
  if(ok)
  {
    if(strcmp(sFileStr, "-"))
    {
      if((fP = fopen(iFileStr, "r")) == NULL)
      {
	ok = 0;
	errNum = WLZ_ERR_READ_EOF;
	(void )WlzStringFromErrorNum(errNum, &errMsg);
	(void )fprintf(stderr,
		       "%s: failed to open inside points file %s (%s).\n",
		       *argv, iFileStr, errMsg);
      }
    }
    else
    {
      fP = stdin;
    }
  }
  if(ok)
  {
    iPts = WlzCFPReadVtxArray(fP, dim, &nIPts, &errNum);
    if(errNum != WLZ_ERR_NONE)
    {
      ok = 0;
      (void )WlzStringFromErrorNum(errNum, &errMsg);
      (void )fprintf(stderr,
	             "%s: failed to read points from file %s (%s).\n",
		     *argv, sFileStr, errMsg);
    }
  }
  if(fP)
  {
    if(strcmp(iFileStr, "-"))
    {
      (void )fclose(fP);
    }
    fP = NULL;
  }
  if(ok)
  {
    if(strcmp(sFileStr, "-"))
    {
      if((fP = fopen(oFileStr, "r")) == NULL)
      {
	ok = 0;
	errNum = WLZ_ERR_READ_EOF;
	(void )WlzStringFromErrorNum(errNum, &errMsg);
	(void )fprintf(stderr,
		       "%s: failed to open outside points file %s (%s).\n",
		       *argv, oFileStr, errMsg);
      }
    }
    else
    {
      fP = stdin;
    }
  }
  if(ok)
  {
    oPts = WlzCFPReadVtxArray(fP, dim, &nOPts, &errNum);
    if(errNum != WLZ_ERR_NONE)
    {
      ok = 0;
      (void )WlzStringFromErrorNum(errNum, &errMsg);
      (void )fprintf(stderr,
	             "%s: failed to read points from file %s (%s).\n",
		     *argv, oFileStr, errMsg);
    }
  }
  if(fP)
  {
    if(strcmp(oFileStr, "-"))
    {
      (void )fclose(fP);
    }
    fP = NULL;
  }
  if(ok)
  {
    bgdV.v.dbv = oDist;
    bgdV.type = WLZ_GREY_DOUBLE;
    switch(dim)
    {
      case 2:
        errNum = WLZ_ERR_UNIMPLEMENTED;
	break;
      case 3:
	/* Compute ounding box of points. */
	bBox0.d3 = WlzBoundingBoxVtx3D(nSPts, sPts.d3, NULL);
	bBox1.d3 = WlzBoundingBoxVtx3D(nIPts, iPts.d3, NULL);
	bBox0.d3 = WlzBoundingBoxUnion3D(bBox0.d3, bBox1.d3);
	bBox1.d3 = WlzBoundingBoxVtx3D(nOPts, oPts.d3, NULL);
	bBox0.d3 = WlzBoundingBoxUnion3D(bBox0.d3, bBox1.d3);
	/* Create distance object that will be used to accumulate distance
	   values. If only a 2D contour is required then create a distance
	   object with a single plane. */
	dObj = WlzMakeCuboid((planeFlg)?
	                     planeIdx: (int )floor(bBox0.d3.zMin) - 2,
			     (planeFlg)?
			     planeIdx: (int )ceil(bBox0.d3.zMax) + 2,
			     (int )floor(bBox0.d3.yMin) - 2,
			     (int )ceil(bBox0.d3.yMax) + 2,
			     (int )floor(bBox0.d3.xMin) - 2,
			     (int )ceil(bBox0.d3.xMax) + 2,
			     WLZ_GREY_DOUBLE, bgdV,
			     NULL, NULL, &errNum);
	if((dObj == NULL) || (errNum != WLZ_ERR_NONE))
	{
	  ok = 0;
	  if(errNum == WLZ_ERR_NONE)
	  {
	    errNum = WLZ_ERR_MEM_ALLOC;
	  }
	  (void )WlzStringFromErrorNum(errNum, &errMsg);
	  (void )fprintf(stderr,
	  		 "%s: failed to allocate distance object (%s).\n",
			 *argv, errMsg);

	}
	/* Compute contour using given distance object. */
	outDom.ctr = WlzContourFromPoints(dObj, WLZ_VERTEX_D3,
					  nSPts, sPts, sAlpha,
					  nIPts, iPts, iDist, iAlpha,
					  nOPts, oPts, oDist, oAlpha,
					  delta, tau, samFac,
					  &errNum);
	WlzFreeObj(dObj);
	break;
    }
    if(errNum != WLZ_ERR_NONE)
    {
      ok = 0;
      (void )WlzStringFromErrorNum(errNum, &errMsg);
      (void )fprintf(stderr,
	             "%s: failed to compute contour from points (%s).\n",
		     *argv, errMsg);
    }
  }
  /* Compute the contour from the point sets. */
  if(ok)
  {
    outObj = WlzMakeMain(WLZ_CONTOUR, outDom, dumVal, NULL, NULL, &errNum);
    if(errNum != WLZ_ERR_NONE)
    {
      ok = 0;
      (void )WlzStringFromErrorNum(errNum, &errMsg);
      (void )fprintf(stderr,
                     "%s: Failed to create output woolz object (%s).\n",
                     argv[0], errMsg);
    }
    if(outObj)
    {
      outDom.core = NULL;
    }
  }
  /* Write out the contour object. */
  if(ok)
  {
    if(strcmp(outObjFileStr, "-"))
    {
      if((fP = fopen(outObjFileStr, "w")) == NULL)
      {
	ok = 0;
	errNum = WLZ_ERR_WRITE_EOF;
	(void )WlzStringFromErrorNum(errNum, &errMsg);
	(void )fprintf(stderr,
		       "%s: failed to open output object file %s (%s).\n",
		       *argv, outObjFileStr, errMsg);
      }
    }
    else
    {
      fP = stdout;
    }
    if(ok)
    {
      if((errNum = WlzWriteObj(fP, outObj)) != WLZ_ERR_NONE)
      {
	ok = 0;
	(void )WlzStringFromErrorNum(errNum, &errMsg);
	(void )fprintf(stderr,
		       "%s: failed to write output object to file %s (%s).\n",
		       *argv, outObjFileStr, errMsg);
      }
    }
    if(strcmp(outObjFileStr, "-"))
    {
      (void )fclose(fP);
    }
    fP = NULL;
  }
  AlcFree(sPts.v);
  AlcFree(iPts.v);
  AlcFree(oPts.v);
  (void )WlzFreeDomain(outDom);
  (void )WlzFreeObj(outObj);
  /* Tidy up and exit. */
  if(usage)
  {
    (void )fprintf(stderr,
    "Usage: %s%s",
    *argv,
    "WlzContourFromPoints [-h] [-2] [-3] [-o<out object>]\n"
    "                     [-S<surface points file>]\n"
    "                     [-I<inside points file>] [-O<outside points file>]\n"
    "                     [-a#] [-b#] [-c#] [-d#] [-e#] [-D#] [-M#] [-T#]\n"
    "                     [-X#]\n"
    "Options:\n"
    "  -h  Print this usage message.\n"
    "  -2  Points are 2D and contour is a curve in 2D.\n"
    "  -3  Points are 3D and contour is a surface in 3D.\n"
    "  -o  Output object file name.\n"
    "  -S  On surface points file.\n"
    "  -I  Inside points file.\n"
    "  -O  Outside points file.\n"
    "  -a  Surface points alpha value.\n"
    "  -b  Inside points alpha value.\n"
    "  -c  Outside points alpha value.\n"
    "  -d  Inside points distance value.\n"
    "  -e  Outside points distance value.\n"
    "  -D  Delta multiorder spline soothing value.\n"
    "  -M  Distance object sampling factor (can be used to reduce the\n"
    "      number of surface facets.)\n"
    "  -T  Tau multiorder spline soothing value.\n"
    "  -X  Plane for 2D contour from 3D point sets.\n"
    "Computes a contour from three point sets: inside; outside and on a\n"
    "surface.\n"
    "All points are given using the following ascii format:\n"
    "  <vertex x> <vertex y> [<vertex z>]\n");
  }
  return(!ok);
}