Exemplo n.º 1
0
SoIndexedFaceSet * Mesh2DView::
Faces2D(
  SoIndexedFaceSet * faces,
  WlzErrorNum& errNum)
{
  int		nElm = 0;
  WlzCMeshElm2D *elm;

  int           iFcount = 0; //face index count

  WlzCMesh2D *mesh=obj->getObj()->domain.cm2;

  // check if it is 2D mesh and if it has faces
  if(!(mesh && (mesh->type == WLZ_CMESH_2D) &&
	((nElm = mesh->res.elm.maxEnt) > 0)))
  {
    errNum = WLZ_ERR_DOMAIN_TYPE;
  }

  if (errNum == WLZ_ERR_NONE)
  {
    for(int i = 0; i < nElm; ++i)
    {
      elm = (WlzCMeshElm2D *)AlcVectorItemGet(mesh->res.elm.vec, i);
      if(elm->idx >= 0)
      {
	faces->coordIndex.set1Value(iFcount++, elm->edu[0].nod->idx);
	faces->coordIndex.set1Value(iFcount++, elm->edu[1].nod->idx);
	faces->coordIndex.set1Value(iFcount++, elm->edu[2].nod->idx);
	faces->coordIndex.set1Value(iFcount++, -1);
      }
    }
  }
  return(faces);
}
Exemplo n.º 2
0
SoCoordinate3 * Mesh2DView::
Vertices2D(
  SoCoordinate3 * vertices,
  WlzErrorNum& errNum)
{
  int           nNod = 0;
  WlzCMeshNod2D	*nod;
  WlzCMesh2D 	*mesh=obj->getObj()->domain.cm2;

  if(!(mesh && (mesh->type == WLZ_CMESH_2D) &&
	((nNod = mesh->res.nod.maxEnt) > 0)))
  {
    errNum = WLZ_ERR_DOMAIN_TYPE;
  }
  if(errNum == WLZ_ERR_NONE)
  {
    /* Output all nodes but use (0, 0, 0) for those that are invalid. */
    for(int i = 0; i < nNod; ++i)
    {
      nod = (WlzCMeshNod2D *)AlcVectorItemGet(mesh->res.nod.vec, i);
      if(nod->idx >= 0)
      {
	vertices->point.set1Value(i, nod->pos.vtX, nod->pos.vtY,
	                          -0.0001);  //view mesh in front
      }
      else
      {
	vertices->point.set1Value(i, 0, 0, 0);
      }
    }
  }
  return(vertices);
}
Exemplo n.º 3
0
/*!
* \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 lie within the
* 		knide domain.
* 		It is assumed that the model is a valid 3D model and that
* 		the knife is a valid 3D (plane) domain object.
* \param	given			Given model.
* \param	knife			Knife object.
* \param	dstErr			Destination error pointer, may be NULL.
*/
static WlzErrorNum WlzGMModelCutDom3D(WlzGMModel *cut, WlzGMModel *given,
				      WlzObject *knife)
{
  WlzPlaneDomain *kDom = NULL;
  WlzErrorNum   errNum = WLZ_ERR_NONE;

  if(knife == NULL)
  {
    errNum = WLZ_ERR_OBJECT_NULL;
  }
  else if((cut == NULL) || (given == NULL) ||
          ((kDom = knife->domain.p) == NULL))
  {
    errNum = WLZ_ERR_DOMAIN_NULL;
  }
  else
  {
    int idF,
    	gMaxF;
    AlcVector *gFVec;

    /* 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. */
    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;
	WlzDVertex3 v[3];

	(void )WlzGMFaceGetG3D(gFace, v + 0, v + 1, v + 2);
	add = (WlzInsideDomain3D(kDom, v[0].vtZ, v[0].vtY, v[0].vtX,
	                         NULL) == 0) &&
	      (WlzInsideDomain3D(kDom, v[1].vtZ, v[1].vtY, v[1].vtX, 
				 NULL) == 0) &&
	      (WlzInsideDomain3D(kDom, v[2].vtZ, v[2].vtY, v[2].vtX, 
				 NULL) == 0);
	if(add)
	{
	  /* Given model face does not intersect the knife domain so add it
	   * to the cut model. */
	  errNum = WlzGMModelConstructSimplex3D(cut, v);
	}
      }
    }
  }
  return(errNum);
}
Exemplo n.º 4
0
/*!
* \return	Coordinates of center of mass.
* \ingroup	WlzFeatures
* \brief	Calculates the centre of mass of a geometric model.
* \param	model			Given geometric model.
* \param	dstMass			Destination pointer for mass, may be
* 					NULL.
* \param	dstErr			Destination pointer for error, may be
* 					NULL.
*/
static WlzDVertex3 WlzCentreOfMassGM(WlzGMModel *model, double *dstMass,
				     WlzErrorNum *dstErr)
{
  int        	iCnt,
  		idI = 0,
  		mass = 0;
  WlzGMVertex	*vertex;
  AlcVector	*vec;
  WlzDVertex3	pos,
  		cMass;
  WlzErrorNum	errNum = WLZ_ERR_NONE;

  vec = model->res.vertex.vec;
  iCnt = model->res.vertex.numIdx;
  cMass.vtX = cMass.vtY = cMass.vtZ = 0.0;
  while((errNum == WLZ_ERR_NONE) && (iCnt-- > 0))
  {
    vertex = (WlzGMVertex *)AlcVectorItemGet(vec, idI++);
    if(vertex->idx >= 0)
    {
      ++mass;
      (void )WlzGMVertexGetG3D(vertex, &pos);
      cMass.vtX += pos.vtX; cMass.vtY += pos.vtY; cMass.vtZ += pos.vtZ;
    }
  }
  if(errNum == WLZ_ERR_NONE)
  {
    if(mass > 0)
    {
      cMass.vtX /= mass; cMass.vtY /= mass; cMass.vtZ /= mass;
    }
    if(dstMass)
    {
      *dstMass = (double )mass;
    }
  }
  if(dstErr)
  {
    *dstErr = errNum;
  }
  return(cMass);
}
Exemplo n.º 5
0
/*!
* \return	void
* \brief	Outputs the mesh and displaced mesh of the given mesh
*		transform as Postscript to the standard error output.
* \param	mObj			Given mesh transform object.
* \param	sObj			Source object.
* \param	dilObj			Dilated object.
* \param	outObj			Transformed object.
*/
static void	WlzCMeshOutputPS(WlzObject *mObj,
				 WlzObject *sObj, WlzObject *dilObj,
				 WlzObject *outObj)
{
  int		idE,
  		idN,
		useElm;
  double	scale;
  double	*dsp;
  WlzDVertex2	pos,
  		offset;
  WlzDVertex2	elmVx[3];
  WlzDBox2	bBox;
  WlzCMeshNod2D	*nod;
  WlzCMeshElm2D *elm;
  WlzCMesh2D	*mesh;
  WlzIndexedValues *ixv;
  WlzObject	*bObj = NULL;
  char		buf[100];

  (void )fprintf(stderr, "%%!\n"
			 "/Times-Courier findfont\n"
			 "1 scalefont\n"
			 "setfont\n"
  			 "1 setlinecap\n"
			 "1 setlinejoin\n"
			 "0.01 setlinewidth\n");
  if((mObj != NULL) && (mObj->type == WLZ_CMESH_2D) &&
     ((mesh = mObj->domain.cm2) != NULL) &&
     ((ixv = mObj->values.x) != NULL))
  {
    /* Compute the bounding box of the mesh transform. */
    bBox.xMin = bBox.yMin = DBL_MAX;
    bBox.xMax = bBox.yMax = DBL_MIN;
    for(idN = 0; idN < mesh->res.nod.maxEnt; ++idN)
    {
      nod = (WlzCMeshNod2D *)AlcVectorItemGet(mesh->res.nod.vec, idN);
      if(nod->idx >= 0)
      {
	if(nod->pos.vtX < bBox.xMin)
	{
	  bBox.xMin = nod->pos.vtX;
	}
	else if(nod->pos.vtX > bBox.xMax)
	{
	  bBox.xMax = nod->pos.vtX;
	}
	if(nod->pos.vtY < bBox.yMin)
	{
	  bBox.yMin = nod->pos.vtY;
	}
	else if(nod->pos.vtY > bBox.yMax)
	{
	  bBox.yMax = nod->pos.vtY;
	}
        dsp = (double *)WlzIndexedValueGet(ixv, idN);
	pos.vtX = nod->pos.vtX + dsp[0];
	pos.vtY = nod->pos.vtY + dsp[1];
	if(pos.vtX < bBox.xMin)
	{
	  bBox.xMin = pos.vtX;
	}
	else if(pos.vtX > bBox.xMax)
	{
	  bBox.xMax = pos.vtX;
	}
	if(pos.vtY < bBox.yMin)
	{
	  bBox.yMin = pos.vtY;
	}
	else if(pos.vtY > bBox.yMax)
	{
	  bBox.yMax = pos.vtY;
	}
      }
    }
    if(((pos.vtX = fabs(bBox.xMax - bBox.xMin)) > 1.0) &&
       ((pos.vtY = fabs(bBox.yMax - bBox.yMin)) > 1.0))
    {
      /* Compute scale and offset for an A4 page. */
      if((4.0 * pos.vtX) > (3.0 * pos.vtY))
      {
        scale = 500.0 / (bBox.xMax - bBox.xMin);
      }
      else
      {
        scale = 700.0 / (bBox.yMax - bBox.yMin);
      }
      offset.vtX = (bBox.xMin * scale) - 50;
      offset.vtY = (bBox.yMin * -scale) - 750;
      (void )fprintf(stderr, "255 0 0 setrgbcolor\n");
      for(idE = 0; idE < mesh->res.elm.maxEnt; ++idE)
      {
        elm = (WlzCMeshElm2D *)AlcVectorItemGet(mesh->res.elm.vec, idE);
	if(elm->idx >= 0)
	{
	  for(idN = 0; idN < 3; ++idN)
	  {
	    pos = elm->edu[idN].nod->pos;
	    elmVx[idN].vtX = (pos.vtX * scale) - offset.vtX;
	    elmVx[idN].vtY = (pos.vtY * -scale) - offset.vtY;
	  }
	  (void )fprintf(stderr,
			 "%g %g moveto "
			 "%g %g lineto "
			 "%g %g lineto "
			 "%g %g lineto "
			 "stroke\n",
			 elmVx[0].vtX, elmVx[0].vtY,
			 elmVx[1].vtX, elmVx[1].vtY,
			 elmVx[2].vtX, elmVx[2].vtY,
			 elmVx[0].vtX, elmVx[0].vtY);
	  WLZ_VTX_2_ADD3(pos, elmVx[0], elmVx[1], elmVx[2]);
	  WLZ_VTX_2_SCALE(pos, pos, 0.333333);
	  (void )sprintf(buf, "%d", elm->idx);
	  (void )fprintf(stderr,
			 "%g %g moveto "
			 "(%s) show\n",
			 pos.vtX, pos.vtY,
			 buf);
	}
      }
      (void )fprintf(stderr, "0 0 255 setrgbcolor\n");
      for(idE = 0; idE < mesh->res.elm.maxEnt; ++idE)
      {
        elm = (WlzCMeshElm2D *)AlcVectorItemGet(mesh->res.elm.vec, idE);
	if(elm->idx >= 0)
	{
	  /* Display only those elements that have all nodes inside the
	   * domain.  
	  useElm = ((elm->edg[0].nod->flags | elm->edg[1].nod->flags |
	             elm->edg[2].nod->flags) &
		    WLZ_CMESH_NOD_FLAG_OUTSIDE) == 0;
	  */
	  useElm = 1;
	  if(useElm)
	  {
	    for(idN = 0; idN < 3; ++idN)
	    {
	      pos = elm->edu[idN].nod->pos;
	      dsp = (double *)WlzIndexedValueGet(ixv, elm->edu[idN].nod->idx);
	      pos.vtX += dsp[0];
	      pos.vtY += dsp[1];
	      elmVx[idN].vtX = (pos.vtX * scale) - offset.vtX;
	      elmVx[idN].vtY = (pos.vtY * -scale) - offset.vtY;
	    }
	    (void )fprintf(stderr,
			   "%g %g moveto "
			   "%g %g lineto "
			   "%g %g lineto "
			   "%g %g lineto "
			   "stroke\n",
			   elmVx[0].vtX, elmVx[0].vtY,
			   elmVx[1].vtX, elmVx[1].vtY,
			   elmVx[2].vtX, elmVx[2].vtY,
			   elmVx[0].vtX, elmVx[0].vtY);
	    WLZ_VTX_2_ADD3(pos, elmVx[0], elmVx[1], elmVx[2]);
	    WLZ_VTX_2_SCALE(pos, pos, 0.333333);
	    (void )sprintf(buf, "%d", elm->idx);
	    (void )fprintf(stderr,
	    		   "%g %g moveto "
			   "(%s) show\n",
			   pos.vtX, pos.vtY,
			   buf);
	  }
	}
      }
      (void )fprintf(stderr, "0 255 0 setrgbcolor\n");
      if((bObj = WlzObjToBoundary(sObj, 1, NULL)) != NULL)
      {
        WlzBndOutputPS(bObj->domain.b, scale, offset);
      }
      (void )fprintf(stderr, "0 255 255 setrgbcolor\n");
      if((bObj = WlzObjToBoundary(dilObj, 1, NULL)) != NULL)
      {
        WlzBndOutputPS(bObj->domain.b, scale, offset);
      }
      (void )fprintf(stderr, "127 0 127 setrgbcolor\n");
      if((bObj = WlzObjToBoundary(outObj, 1, NULL)) != NULL)
      {
        WlzBndOutputPS(bObj->domain.b, scale, offset);
      }
      (void )fprintf(stderr, "showpage\n");
    }
  }
}
Exemplo n.º 6
0
/*!
* \return	Woolz error number.
* \ingroup	WlzExtFF
* \brief	Writes the given Woolz object (which is known to be a
* 		WLZ_CONTOUR) to the given file stream using the
* 		stereolithography stl file format, see WlzEffReadObjStl().
* \param	fP			Output file stream.
* \param	obj			Given woolz object (must not be NULL).
*/
static WlzErrorNum WlzEffWriteObjCtrStl(FILE *fP, WlzObject *obj)
{
  int		nFce,
  		nVtx;
  WlzGMModel	*model;
  WlzGMResIdxTb *resIdxTb = NULL;
  WlzErrorNum	errNum = WLZ_ERR_NONE;

  if((obj->domain.core == NULL) || ((model = obj->domain.ctr->model) == NULL))
  {
    errNum = WLZ_ERR_DOMAIN_NULL;
  }
  else
  {
    switch(model->type)
    {
      case WLZ_GMMOD_3I: /* FALLTHROUGH */
      case WLZ_GMMOD_3D: /* FALLTHROUGH */
      case WLZ_GMMOD_3N:
        break;
      default:
        errNum = WLZ_ERR_DOMAIN_TYPE;
	break;
    }
  }
  /* Check there are verticies and faces. */
  if(errNum == WLZ_ERR_NONE)
  {
    if((model->res.vertex.numElm < 3) || ((nFce = model->res.face.numElm) < 1))
    {
      errNum = WLZ_ERR_DOMAIN_DATA;
    }
  }
  if(errNum == WLZ_ERR_NONE)
  {
    if(fprintf(fP, "solid ascii\n") <= 0)
    {
      errNum = WLZ_ERR_WRITE_INCOMPLETE;
    }
  }
  if(errNum == WLZ_ERR_NONE)
  {
    int		idF;
    WlzGMFace	*fce;
    AlcVector	*vec;
    WlzDVertex3 nrm;
    WlzDVertex3	vBuf[3];

    vec = model->res.face.vec;
    for(idF = 0; idF < model->res.face.numIdx; ++idF)
    {
      fce = (WlzGMFace *)AlcVectorItemGet(vec, idF);
      if(fce->idx >= 0)
      {
        errNum = WlzGMFaceGetG3D(fce, vBuf + 0, vBuf + 1, vBuf + 2);
	if(errNum == WLZ_ERR_NONE)
	{
	  nrm = WlzGeomTriangleNormal(vBuf[0], vBuf[1], vBuf[2]);
	  if(fprintf(fP,
		     "  facet normal %g %g %g\n"
		     "    outer loop\n"
		     "      vertex %g %g %g\n"
		     "      vertex %g %g %g\n"
		     "      vertex %g %g %g\n"
		     "    endloop\n"
		     "  endfacet\n",
		     nrm.vtX, nrm.vtY, nrm.vtZ,
		     vBuf[0].vtX, vBuf[0].vtY, vBuf[0].vtZ,
		     vBuf[1].vtX, vBuf[1].vtY, vBuf[1].vtZ,
		     vBuf[2].vtX, vBuf[2].vtY, vBuf[2].vtZ) <= 0)
	  {
	    errNum = WLZ_ERR_WRITE_INCOMPLETE;
	    break;
	  }
	}
      }
    }
  }
  WlzGMModelResIdxFree(resIdxTb);
  if(errNum == WLZ_ERR_NONE)
  {
    if(fprintf(fP, "endsolid\n") <= 0)
    {
      errNum = WLZ_ERR_WRITE_INCOMPLETE;
    }
  }
  return(errNum);
}
Exemplo n.º 7
0
/*!
* \return	Woolz error number.
* \ingroup	WlzExtFF
* \brief	Writes the given Woolz object (which is known to be a
* 		WLZ_CMESH_2D5) object to the given file stream using the
* 		stereolithography stl file format, see WlzEffReadObjStl().
* \param	fP			Output file stream.
* \param	obj			Given woolz object (must not be NULL).
*/
static WlzErrorNum WlzEffWriteObjCM2D5Stl(FILE *fP, WlzObject *obj)
{
  int		*nodTbl = NULL;
  WlzCMesh2D5	*mesh;
  WlzErrorNum	errNum = WLZ_ERR_NONE;

  if(obj->domain.core == NULL)
  {
    errNum = WLZ_ERR_DOMAIN_NULL;
  }
  else
  {
    mesh = obj->domain.cm2d5;
    if(mesh->type != WLZ_CMESH_2D5)
    {
      errNum = WLZ_ERR_DOMAIN_TYPE;
    }
  }
  if(errNum == WLZ_ERR_NONE)
  {
    if((nodTbl = (int *)AlcMalloc(mesh->res.nod.maxEnt * sizeof(int))) == NULL)
    {
      errNum = WLZ_ERR_MEM_ALLOC;
    }
  }
  if(errNum == WLZ_ERR_NONE)
  {
    if(fprintf(fP, "solid ascii\n") <= 0)
    {
      errNum = WLZ_ERR_WRITE_INCOMPLETE;
    }
  }
  /* Output the elements. */
  if(errNum == WLZ_ERR_NONE)
  {
    int		idE;
    WlzDVertex3	nrm;
    WlzCMeshElm2D5 *elm;
    WlzCMeshNod2D5 *nod[3];

    for(idE = 0; idE < mesh->res.elm.maxEnt; ++idE)
    {
      elm = (WlzCMeshElm2D5 *)AlcVectorItemGet(mesh->res.elm.vec, idE);
      if(elm->idx >= 0)
      {
        WlzCMeshElmGetNodes2D5(elm, nod + 0, nod + 1, nod + 2);
        nrm = WlzGeomTriangleNormal(nod[0]->pos, nod[1]->pos, nod[2]->pos);
	if(fprintf(fP,
	           "  facet normal %g %g %g\n"
		   "    outer loop\n"
	           "      vertex %g %g %g\n"
	           "      vertex %g %g %g\n"
	           "      vertex %g %g %g\n"
		   "    endloop\n"
	           "  endfacet\n",
		   nrm.vtX, nrm.vtY, nrm.vtZ,
		   nod[0]->pos.vtX, nod[0]->pos.vtY, nod[0]->pos.vtZ,
		   nod[1]->pos.vtX, nod[1]->pos.vtY, nod[1]->pos.vtZ,
		   nod[2]->pos.vtX, nod[2]->pos.vtY, nod[2]->pos.vtZ) <= 0)
	{
	  errNum = WLZ_ERR_WRITE_INCOMPLETE;
	  break;
	}
      }
    }
  }
  if(errNum == WLZ_ERR_NONE)
  {
    if(fprintf(fP, "endsolid\n") <= 0)
    {
      errNum = WLZ_ERR_WRITE_INCOMPLETE;
    }
  }
  return(errNum);
}
Exemplo n.º 8
0
/*!
* \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);
}
Exemplo n.º 9
0
/*!
* \return	Woolz error number.
* \ingroup	WlzExtFF
* \brief	Writes the given Woolz object to the given stream using the
* 		Netgen neutral mesh file format.
* \param	fP			Output file stream.
* \param	obj			Given woolz object.
*/
WlzErrorNum	WlzEffWriteObjEMT(FILE *fP, WlzObject *obj)
{
  int		nBFce = 0,
     		nElm = 0,
		nNod = 0;
  int		*nodTbl = NULL;
  WlzCMesh3D	*mesh;
  WlzErrorNum	errNum = WLZ_ERR_NONE;

  if(fP == NULL)
  {
    errNum = WLZ_ERR_PARAM_NULL;
  }
  else if(obj == NULL)
  {
    errNum = WLZ_ERR_OBJECT_NULL;
  }
  else if(obj->type != WLZ_CMESH_3D)
  {
    errNum = WLZ_ERR_OBJECT_TYPE;
  }
  else if(obj->domain.core == NULL)
  {
    errNum = WLZ_ERR_DOMAIN_NULL;
  }
  else
  {
    mesh = obj->domain.cm3;
    if(mesh->type != WLZ_CMESH_3D)
    {
      errNum = WLZ_ERR_DOMAIN_TYPE;
    }
  }
  if(errNum == WLZ_ERR_NONE)
  {
    if((nodTbl = (int *)
		 AlcMalloc(mesh->res.nod.maxEnt * sizeof(int))) == NULL)
    {
      errNum = WLZ_ERR_MEM_ALLOC;
    }
  }
  /* Compute the number of boundary faces while building an element table to
   * avoid deleted elements. */
  if(errNum == WLZ_ERR_NONE)
  {
    int		idE;

    nNod = mesh->res.nod.numEnt;
    for(idE = 0; idE < mesh->res.elm.maxEnt; ++idE)
    {
      WlzCMeshElm3D *elm;

      elm = (WlzCMeshElm3D *)AlcVectorItemGet(mesh->res.elm.vec, idE);
      if(elm->idx >= 0)
      {
	int	idF;

	for(idF = 0; idF < 4; ++idF)
	{
	  if((elm->face[idF].opp == NULL) ||
	     (elm->face[idF].opp == &(elm->face[idF])))
	  
	  {
	    ++nBFce;
	  }
	}
        ++nElm;
      }
    }
  }
  /* Output the number of nodes. */
  if(errNum == WLZ_ERR_NONE)
  {
    if(fprintf(fP, "%d\n", nNod) <= 0)
    {
      errNum = WLZ_ERR_WRITE_INCOMPLETE;
    }
  }
  /* Output the node positions while building a node table to avoid deleted
   * nodes. */
  if(errNum == WLZ_ERR_NONE)
  {
    int		idC = 0,
    		idN;

    for(idN = 0; idN < mesh->res.nod.maxEnt; ++idN)
    {
      WlzCMeshNod3D *nod;

      nod = (WlzCMeshNod3D *)AlcVectorItemGet(mesh->res.nod.vec, idN);
      if(nod->idx >= 0)
      {
        nodTbl[idN] = ++idC;
	if(fprintf(fP, "  %lg %lg %lg\n",
	           nod->pos.vtX, nod->pos.vtY, nod->pos.vtZ) <= 0)
        {
	  errNum = WLZ_ERR_WRITE_INCOMPLETE;
	  break;
	}
      }
    }
  }
  /* Output the number of elements. */
  if(errNum == WLZ_ERR_NONE)
  {
    if(fprintf(fP, "%d\n", nElm) <= 0)
    {
      errNum = WLZ_ERR_WRITE_INCOMPLETE;
    }
  }
  /* Output the elements using the node indices. */
  if(errNum == WLZ_ERR_NONE)
  {
    int		idE;
    WlzCMeshNod3D *nBuf[4];

    for(idE = 0; idE < mesh->res.elm.maxEnt; ++idE)
    {
      WlzCMeshElm3D *elm;

      elm = (WlzCMeshElm3D *)AlcVectorItemGet(mesh->res.elm.vec, idE);
      if(elm->idx >= 0)
      {
	WlzCMeshElmGetNodes3D(elm,
			      &(nBuf[0]), &(nBuf[1]), &(nBuf[2]), &(nBuf[3]));
        if(fprintf(fP, "  1 %d %d %d %d\n",
	           nodTbl[(nBuf[0])->idx],
		   nodTbl[(nBuf[1])->idx],
	           nodTbl[(nBuf[2])->idx],
		   nodTbl[(nBuf[3])->idx]) <= 0)
        {
	  errNum = WLZ_ERR_WRITE_INCOMPLETE;
	  break;
	}
      }
    }
  }
  /* Output the number of boundary faces. */
  if(errNum == WLZ_ERR_NONE)
  {
    if(fprintf(fP, "%d\n", nBFce) <= 0)
    {
      errNum = WLZ_ERR_WRITE_INCOMPLETE;
    }
  }
  /* Output the boundary faces defined by the node indices. */
  if(errNum == WLZ_ERR_NONE)
  {
    int		idE;

    for(idE = 0; idE < mesh->res.elm.maxEnt; ++idE)
    {
      WlzCMeshElm3D *elm;

      elm = (WlzCMeshElm3D *)AlcVectorItemGet(mesh->res.elm.vec, idE);
      if(elm->idx >= 0)
      {
	int	idF;

        for(idF = 0; idF < 4; ++idF)
	{
	  WlzCMeshFace *fce;

	  fce = elm->face + idF;
	  if((fce->opp == NULL) || (fce->opp == fce))
	  {
	    WlzCMeshEdgU3D *edu;

	    edu = fce->edu;
            if(fprintf(fP, "  1 %d %d %d\n",
		       nodTbl[edu->nod->idx], 
		       nodTbl[edu->next->nod->idx], 
		       nodTbl[edu->next->next->nod->idx]) <= 0)
	    {
	      errNum = WLZ_ERR_WRITE_INCOMPLETE;
	      break;
	    }
	  }
	}
      }
      if(errNum != WLZ_ERR_NONE)
      {
        break;
      }
    }
  }
  AlcFree(nodTbl);
  return(errNum);
}
Exemplo n.º 10
0
/*!
* \return	Woolz error code.
* \ingroup	BinWlzApp
* \brief	Outputs a VTK tensor file from a conforming mesh object.
* \param	prog:			Program name.
* \param	inFileStr		Name of input file object was read
* 					from.
* \param	fP			Opened file.
* \param	obj			Given conforming mesh object.
*/
static WlzErrorNum WlzVTKTensorFromCMesh(char *prog, char *inFileStr,
					 FILE *fP, WlzObject *obj)
{
  int		idE,
		maxElm;
  WlzCMesh3D	*mesh;
  AlcVector	*elmVec;
  WlzIndexedValues *ixv;
  WlzErrorNum	errNum = WLZ_ERR_NONE;
  
  mesh = obj->domain.cm3;
  ixv = obj->values.x;
  elmVec = mesh->res.elm.vec;
  maxElm = mesh->res.elm.maxEnt;
  if(fprintf(fP,
	     "# vtk DataFile Version 1.0\n"
	     "Output from Woolz WLZ_CMESH_3D file %s via %s\n"
	     "ASCII\n"
	     "DATASET POLYDATA\n"
	     "POINTS %d float\n",
	     inFileStr, prog,  maxElm) <= 0)
  {
    errNum = WLZ_ERR_WRITE_INCOMPLETE;
  }
  if(errNum == WLZ_ERR_NONE)
  {
    for(idE = 0; idE < maxElm; ++idE)
    {
      WlzDVertex3 c;
      WlzCMeshElm3D *elm;
      WlzCMeshNod3D *nod[4];
      
      elm = (WlzCMeshElm3D *)AlcVectorItemGet(elmVec, idE);
      if(elm->idx >= 0)
      {
	nod[0] = WLZ_CMESH_ELM3D_GET_NODE_0(elm);
	nod[1] = WLZ_CMESH_ELM3D_GET_NODE_1(elm);
	nod[2] = WLZ_CMESH_ELM3D_GET_NODE_2(elm);
	nod[3] = WLZ_CMESH_ELM3D_GET_NODE_2(elm);
	c.vtX = 0.25 * (nod[0]->pos.vtX + nod[1]->pos.vtX + 
			nod[2]->pos.vtX + nod[3]->pos.vtX);
	c.vtY = 0.25 * (nod[0]->pos.vtY + nod[1]->pos.vtY + 
			nod[2]->pos.vtY + nod[3]->pos.vtY);
	c.vtZ = 0.25 * (nod[0]->pos.vtZ + nod[1]->pos.vtZ + 
			nod[2]->pos.vtZ + nod[3]->pos.vtZ);
      }
      else
      {
	WLZ_VTX_3_ZERO(c);
      }
      if(fprintf(fP,
		 "%f %f %f\n", c.vtX, c.vtY, c.vtZ) <= 0)
      {
	errNum = WLZ_ERR_WRITE_INCOMPLETE;
	break;
      }
    }
  }
  if(errNum == WLZ_ERR_NONE)
  {
    if(fprintf(fP,
	       "POINT_DATA %d\n"
	       "TENSORS tensors float\n",
	       maxElm) <= 0)
    {
      errNum = WLZ_ERR_WRITE_INCOMPLETE;
    }
  }
  if(errNum == WLZ_ERR_NONE)
  {
    for(idE = 0; idE < maxElm; ++idE)
    {
      WlzCMeshElm3D *elm;

      elm = (WlzCMeshElm3D *)AlcVectorItemGet(elmVec, idE);
      if(elm->idx >= 0)
      {
	double *t;

	t = (double *)WlzIndexedValueGet(ixv, elm->idx);
	if(fprintf(fP,
		   "%f %f %f "
		   "%f %f %f "
		   "%f %f %f \n",
		   t[0], t[1], t[2],
		   t[3], t[4], t[5],
		   t[6], t[7], t[8]) <= 0)
	{
	  errNum = WLZ_ERR_WRITE_INCOMPLETE;
	  break;
	}
      }
      else
      {
	if(fprintf(fP,
		   "0 0 0\n"
		   "0 0 0\n"
		   "0 0 0\n\n") <= 0)
	errNum = WLZ_ERR_WRITE_INCOMPLETE;
	break;
      }
    }
  }
  return(errNum);
}
Exemplo n.º 11
0
/*!
* \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);
}
Exemplo n.º 12
0
/*!
* \return	Woolz error code.
* \brief	Prints boundary node coordinates for a conforming mesh.
* \param	fP			File pointer opened for acsii write.
* \param	obj			Object containing the conforming mesh.
*/
static WlzErrorNum WlzBoundaryVerticesCMesh(FILE *fP, WlzObject *obj)
{
  WlzErrorNum	errNum = WLZ_ERR_NONE;

  if(obj == NULL)
  {
    errNum = WLZ_ERR_OBJECT_NULL;
  }
  else if(obj->domain.core == NULL)
  {
    errNum = WLZ_ERR_DOMAIN_NULL;
  }
  else
  {
    int		idx,
    		mN;
    WlzCMeshP	mesh;
    AlcVector	*vec;

    switch(obj->type)
    {
      case WLZ_CMESH_2D:
        mesh.m2 = obj->domain.cm2;
	mN = mesh.m2->res.nod.maxEnt;
	vec = mesh.m2->res.nod.vec;
	for(idx = 0; idx < mN; ++idx)
	{
	  WlzCMeshNod2D *nod;

          nod = (WlzCMeshNod2D *)AlcVectorItemGet(vec, idx);
          if(nod->idx >= 0)
	  {
	    if(WlzCMeshNodIsBoundary2D(nod))
	    {
	      (void )fprintf(fP, "%lg %lg\n", nod->pos.vtX, nod->pos.vtY);
	    }
	  }
	}
	break;
      case WLZ_CMESH_2D5:
        mesh.m2d5 = obj->domain.cm2d5;
	mN = mesh.m2d5->res.nod.maxEnt;
	vec = mesh.m2d5->res.nod.vec;
	for(idx = 0; idx < mN; ++idx)
	{
	  WlzCMeshNod2D5 *nod;

          nod = (WlzCMeshNod2D5 *)AlcVectorItemGet(vec, idx);
          if(nod->idx >= 0)
	  {
	    if(WlzCMeshNodIsBoundary2D5(nod))
	    {
	      (void )fprintf(fP, "%lg %lg %lg\n",
	                     nod->pos.vtX, nod->pos.vtY, nod->pos.vtZ);
	    }
	  }
	}
	break;
      case WLZ_CMESH_3D:
        mesh.m3 = obj->domain.cm3;
	mN = mesh.m3->res.nod.maxEnt;
	vec = mesh.m3->res.nod.vec;
	for(idx = 0; idx < mN; ++idx)
	{
	  WlzCMeshNod3D *nod;

          nod = (WlzCMeshNod3D *)AlcVectorItemGet(vec, idx);
          if(nod->idx >= 0)
	  {
	    if(WlzCMeshNodIsBoundary3D(nod))
	    {
	      (void )fprintf(fP, "%lg %lg %lg\n",
	                     nod->pos.vtX, nod->pos.vtY, nod->pos.vtZ);
	    }
	  }
	}
	break;
      default:
	errNum = WLZ_ERR_OBJECT_TYPE;
	break;
    }
    if((errNum == WLZ_ERR_NONE) && feof(fP))
    {
      errNum = WLZ_ERR_WRITE_INCOMPLETE;
    }
  }
  return(errNum);
}
Exemplo n.º 13
0
/*!
* \return	Woolz error number.
* \ingroup	WlzExtFF
* \brief	Writes the given Woolz object to a pair of files
* 		using the node/ele two part mesh file format.  The
* 		given file name is used to generate the '.node' and '.ele'
* 		filenames.
* \param	gvnFileName		Given file name with '.node' or
* 					no extension.
* \param	obj			Given woolz object.
*/
WlzErrorNum	WlzEffWriteObjNodeEle(const char *gvnFileName, WlzObject *obj)
{
  int		cnt,
  		idE,
  		idN,
		bnd = 0,
		dim = 0,
  		nElm = 0,
		nNod = 0,
		maxElm = 0,
		maxNod = 0;
  char		*fileName = NULL,
  		*nodeFileName = NULL,
		*eleFileName = NULL;
  int		*nodTbl = NULL;
  FILE		*fP = NULL;
  WlzCMeshP	mesh;
  WlzCMeshElm2D	*elm2;
  WlzCMeshElm3D	*elm3;
  WlzCMeshNod2D	*nod2[4];
  WlzCMeshNod3D	*nod3[4];
  WlzErrorNum	errNum = WLZ_ERR_NONE;

  mesh.v = NULL;
  if(obj == NULL)
  {
    errNum = WLZ_ERR_OBJECT_NULL;
  }
  else if(obj->domain.core == NULL)
  {
    errNum = WLZ_ERR_DOMAIN_NULL;
  }
  else if((gvnFileName == NULL) || (*gvnFileName == '\0'))
  {
    errNum = WLZ_ERR_PARAM_NULL;
  }
  else
  {
    errNum = WlzEffNodeEleFileNames(&fileName, &nodeFileName, &eleFileName,
                                    gvnFileName);
  }
  /* Open the node file. */
  if(errNum == WLZ_ERR_NONE)
  {
    if((nodeFileName == NULL) || (*nodeFileName == '\0') ||
       ((fP = fopen(nodeFileName, "w")) == NULL))
    {
      errNum = WLZ_ERR_READ_EOF;
    }
#ifdef _WIN32
    if(fP != NULL)
    {
      if(_setmode(_fileno(fP), 0x8000) == -1)
      {
        errNum = WLZ_ERR_READ_EOF;
      }
    }
#endif
  }
  if(errNum == WLZ_ERR_NONE)
  {
    switch(obj->type)
    {
      case WLZ_CMESH_2D:
	if((mesh.m2 = obj->domain.cm2) == NULL)
	{
	  errNum = WLZ_ERR_DOMAIN_NULL;
	}
	else if(mesh.m2->type == WLZ_CMESH_2D)
	{
	  dim = 2;
	  nNod = mesh.m2->res.nod.numEnt;
	  nElm = mesh.m2->res.elm.numEnt;
	  maxNod = mesh.m2->res.nod.maxEnt;
	  maxElm = mesh.m2->res.elm.maxEnt;
	}
	else
	{
	  errNum = WLZ_ERR_DOMAIN_TYPE;
	}
        break;
      case WLZ_CMESH_3D:
	if((mesh.m3 = obj->domain.cm3) == NULL)
	{
	  errNum = WLZ_ERR_DOMAIN_NULL;
	}
	else if(mesh.m3->type == WLZ_CMESH_3D)
	{
	  dim = 3;
	  nNod = mesh.m3->res.nod.numEnt;
	  nElm = mesh.m3->res.elm.numEnt;
	  maxNod = mesh.m3->res.nod.maxEnt;
	  maxElm = mesh.m3->res.elm.maxEnt;
	}
	else
	{
	  errNum = WLZ_ERR_DOMAIN_TYPE;
	}
        break;
      default:
        errNum = WLZ_ERR_OBJECT_TYPE;
        break;
    }
  }
  if(errNum == WLZ_ERR_NONE)
  {
    if((nodTbl = (int *)AlcMalloc(maxNod * sizeof(int))) == NULL)
    {
      errNum = WLZ_ERR_MEM_ALLOC;
    }
  }
  /* Output comment identifying the file followed by the number of nodes,
   * dimension, the number of attributes and the number of boundary markers.
   * On following records output the node psoitions. */
  if(errNum == WLZ_ERR_NONE)
  {
    if(fprintf(fP, "#%s\n%d %d %d %d\n", nodeFileName, nNod, dim, 0, 1) <= 0)
    {
      errNum = WLZ_ERR_WRITE_INCOMPLETE;
    }
  }
  /* Output node positions while building a node table to avoid deleted
   * nodes. */
  if(errNum == WLZ_ERR_NONE)
  {
    cnt = 0;
    if(dim == 2)
    {
      for(idN = 0; idN < maxNod; ++idN)
      {
	nod2[0] = (WlzCMeshNod2D *)AlcVectorItemGet(mesh.m2->res.nod.vec, idN);
	if(nod2[0]->idx >= 0)
	{
	  nodTbl[idN] = cnt++;
	  if(fprintf(fP, "%d %lg %lg %d\n",
		     cnt,
		     nod2[0]->pos.vtX, nod2[0]->pos.vtY,
		     bnd) <= 0)
	  {
	    errNum = WLZ_ERR_WRITE_INCOMPLETE;
	    break;
	  }
	}
      }
    }
    else /* dim == 3 */
    {
      for(idN = 0; idN < maxNod; ++idN)
      {
	nod3[0] = (WlzCMeshNod3D *)AlcVectorItemGet(mesh.m3->res.nod.vec, idN);
	if(nod3[0]->idx >= 0)
	{
	  nodTbl[idN] = cnt++;
	  if(fprintf(fP, "%d %lg %lg %lg %d\n",
		     cnt,
		     nod3[0]->pos.vtX, nod3[0]->pos.vtY, nod3[0]->pos.vtZ,
		     bnd) <= 0)
	  {
	    errNum = WLZ_ERR_WRITE_INCOMPLETE;
	    break;
	  }
	}
      }
    }
  }
  /* Close the node file. */
  if(fP)
  {
    (void )fclose(fP);
    fP = NULL;
  }
  /* Open the element file. */
  if(errNum == WLZ_ERR_NONE)
  {
    if((eleFileName == NULL) || (*eleFileName == '\0') ||
       ((fP = fopen(eleFileName, "w")) == NULL))
    {
      errNum = WLZ_ERR_READ_EOF;
    }
#ifdef _WIN32
    if(fP != NULL)
    {
      if(_setmode(_fileno(fP), 0x8000) == -1)
      {
        errNum = WLZ_ERR_READ_EOF;
      }
    }
#endif
  }
  /* Output comment identifying the file followed by the number of elements,
   * # the number of nodes per element and the number of attributes. */
  if(errNum == WLZ_ERR_NONE)
  {
    if(fprintf(fP, "#%s\n%d %d %d\n", eleFileName, nElm, dim + 1, 0) <= 0)
    {
      errNum = WLZ_ERR_WRITE_INCOMPLETE;
    }
  }
  /* Output the node indices for each element. */
  if(errNum == WLZ_ERR_NONE)
  {
    cnt = 0;
    if(dim == 2)
    {
      for(idE = 0; idE < maxElm; ++idE)
      {
	elm2 = (WlzCMeshElm2D *)AlcVectorItemGet(mesh.m2->res.elm.vec, idE);
	if(elm2->idx >= 0)
	{
	  nod2[0] = WLZ_CMESH_ELM2D_GET_NODE_0(elm2);
	  nod2[1] = WLZ_CMESH_ELM2D_GET_NODE_1(elm2);
	  nod2[2] = WLZ_CMESH_ELM2D_GET_NODE_2(elm2);
	  if(fprintf(fP, "%d %d %d %d\n",
		     ++cnt,
		     nodTbl[nod2[0]->idx] + 1,
		     nodTbl[nod2[1]->idx] + 1,
		     nodTbl[nod2[2]->idx] + 1) <= 0)
	  {
	    errNum = WLZ_ERR_WRITE_INCOMPLETE;
	    break;
	  }
	}
      }
    }
    else /* dim == 3 */
    {
      for(idE = 0; idE < maxElm; ++idE)
      {
	elm3 = (WlzCMeshElm3D *)AlcVectorItemGet(mesh.m3->res.elm.vec, idE);
	if(elm3->idx >= 0)
	{
	  nod3[0] = WLZ_CMESH_ELM3D_GET_NODE_0(elm3);
	  nod3[1] = WLZ_CMESH_ELM3D_GET_NODE_1(elm3);
	  nod3[2] = WLZ_CMESH_ELM3D_GET_NODE_2(elm3);
	  nod3[3] = WLZ_CMESH_ELM3D_GET_NODE_3(elm3);
	  if(fprintf(fP, "%d %d %d %d %d\n",
		     ++cnt,
		     nodTbl[nod3[0]->idx] + 1,
		     nodTbl[nod3[1]->idx] + 1,
		     nodTbl[nod3[2]->idx] + 1,
		     nodTbl[nod3[3]->idx] + 1) <= 0)
	  {
	    errNum = WLZ_ERR_WRITE_INCOMPLETE;
	    break;
	  }
	}
      }
    }
  }
  /* Close the element file. */
  if(fP)
  {
    (void )fclose(fP);
    fP = NULL;
  }
  AlcFree(nodTbl);
  return(errNum);
}
Exemplo n.º 14
0
/*!
* \return	Object read from file.
* \ingroup	WlzExtFF
* \brief	Reads a Woolz object from a pair of files using the node/ele
* 		format. The given file name is used to generate the '.node'
* 		and '.ele' filenames.
* \param	gvnFileName		Given file name.
* \param	dstErr			Destination error number ptr, may be
* 					NULL.
*/
WlzObject	*WlzEffReadObjNodeEle(const char *gvnFileName,
				      WlzErrorNum *dstErr)
{
  int		cnt,
		idx,
  		idE,
  		idN,
		bnd = 0,
		dim = 0,
		nAtr = 0,
		nBnd = 0,
  		nElm = 0,
  		nNod = 0,
		nodPerElm = 0;
  FILE		*fP = NULL;
  char		*fileName = NULL,
  		*nodeFileName = NULL,
		*eleFileName = NULL,
		*str;
  int 		eBuf[4];
  WlzVertexP    vBuf;
  WlzCMeshP	mesh;
  WlzObject	*obj = NULL;
  WlzDomain	dom;
  WlzValues	val;
  WlzErrorNum	errNum = WLZ_ERR_NONE;
  char		cBuf[256];
  WlzCMeshNod2D	*nBuf2[4];
  WlzCMeshNod3D	*nBuf3[4];

  vBuf.v = NULL;
  mesh.v = NULL;
  dom.core = NULL;
  val.core = NULL;
  if((gvnFileName == NULL) || (*gvnFileName == '\0'))
  {
    errNum = WLZ_ERR_PARAM_NULL;
  }
  else
  {
    errNum = WlzEffNodeEleFileNames(&fileName, &nodeFileName, &eleFileName,
                                    gvnFileName);
  }
  if(errNum == WLZ_ERR_NONE)
  {
    if((nodeFileName == NULL) || (*nodeFileName == '\0') ||
       ((fP = fopen(nodeFileName, "r")) == NULL))
    {
      errNum = WLZ_ERR_READ_EOF;
    }
#ifdef _WIN32
    if(fP != NULL)
    {
      if(_setmode(_fileno(fP), 0x8000) == -1)
      {
        errNum = WLZ_ERR_READ_EOF;
      }
    }
#endif
  }
  if(fP == NULL)
  {
    errNum = WLZ_ERR_PARAM_NULL;
  }
  else
  {
    /* Optional records may be comments starting with a '#' but apart
     * from these the first line should have four integers specifying
     * the number of nodes, the dimension, the number of attributes
     * and the number of boundary markers. */
    cnt = 0;
    do
    {
      if((str = WlzEffReadObjNodeEleRec(fP, cBuf, 256)) == NULL)
      {
	errNum = WLZ_ERR_READ_INCOMPLETE;
      }
      else if(*str != '#')
      {
	if((cnt = sscanf(str, "%d %d %d %d",
	                 &nNod, &dim, &nAtr, &nBnd)) != 4)
	{
	  errNum = WLZ_ERR_READ_INCOMPLETE;
	}
      }
    } while((errNum == WLZ_ERR_NONE) && (cnt != 4));
  }
  /* Check for reasonable number of nodes, etc.... */
  if(errNum == WLZ_ERR_NONE)
  {
    if((nNod <= 0) || ((dim != 2) && (dim != 3)) || (nAtr != 0) || (nBnd != 1))
    {
      errNum = WLZ_ERR_READ_INCOMPLETE;
    }
  }
  if(errNum == WLZ_ERR_NONE)
  {
    idN = 0;
    if(dim == 2)
    {
      /* Create a new 2D constrained mesh. */
      mesh.m2 = WlzCMeshNew2D(&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.v = AlcMalloc(sizeof(WlzDVertex2) * nNod)) == NULL)
	{
	  errNum = WLZ_ERR_MEM_ALLOC;
	}
      }
      while((errNum == WLZ_ERR_NONE) && (idN < nNod))
      {
	if((str = WlzEffReadObjNodeEleRec(fP, cBuf, 256)) == NULL)
	{
	  errNum = WLZ_ERR_READ_INCOMPLETE;
	  break;
	}
	else if(*str != '#')
	{
	  if((sscanf(str, "%d %lg %lg %d",
		     &idx,
		     &(vBuf.d2[idN].vtX), &(vBuf.d2[idN].vtY),
		     &bnd) == 4) && (idx = idN + 1))
	  {
	    if(idN == 0)
	    {
	      mesh.m2->bBox.xMin = mesh.m2->bBox.xMax = vBuf.d2[idN].vtX;
	      mesh.m2->bBox.yMin = mesh.m2->bBox.yMax = vBuf.d2[idN].vtY;
	    }
	    else
	    {
	      if(vBuf.d2[idN].vtX < mesh.m2->bBox.xMin)
	      {
		mesh.m2->bBox.xMin = vBuf.d2[idN].vtX;
	      }
	      else if(vBuf.d2[idN].vtX > mesh.m2->bBox.xMax)
	      {
		mesh.m2->bBox.xMax = vBuf.d2[idN].vtX;
	      }
	      if(vBuf.d2[idN].vtY < mesh.m2->bBox.yMin)
	      {
		mesh.m2->bBox.yMin = vBuf.d2[idN].vtY;
	      }
	      else if(vBuf.d2[idN].vtY > mesh.m2->bBox.yMax)
	      {
		mesh.m2->bBox.yMax = vBuf.d2[idN].vtY;
	      }
	    }
	    ++idN;
	  }
	  else
	  {
	    errNum = WLZ_ERR_READ_INCOMPLETE;
	    break;
	  }
	}
      }
      /* Create the nodes. */
      if(errNum == WLZ_ERR_NONE)
      {
	if(AlcVectorExtendAndGet(mesh.m2->res.nod.vec, nNod) == NULL)
	{
	  errNum = WLZ_ERR_MEM_ALLOC;
	}
	else
	{
	  errNum = WlzCMeshReassignGridCells2D(mesh.m2, nNod);
	}
      }
      if(errNum == WLZ_ERR_NONE)
      {
	for(idN = 0; idN < nNod; ++idN)
	{
	   nBuf2[0] = WlzCMeshNewNod2D(mesh.m2, vBuf.d2[idN], NULL);
	   nBuf2[0]->pos = vBuf.d2[idN];
	   nBuf2[0]->flags = 0;
	}
      }
    }
    else /* dim == 3 */
    {
      /* Create a new 3D constrained mesh. */
      mesh.m3 = 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.v = AlcMalloc(sizeof(WlzDVertex3) * nNod)) == NULL)
	{
	  errNum = WLZ_ERR_MEM_ALLOC;
	}
      }
      while((errNum == WLZ_ERR_NONE) && (idN < nNod))
      {
	if((str = WlzEffReadObjNodeEleRec(fP, cBuf, 256)) == NULL)
	{
	  errNum = WLZ_ERR_READ_INCOMPLETE;
	  break;
	}
	else if(*str != '#')
	{
	  if((sscanf(str, "%d %lg %lg %lg %d",
		     &idx,
		     &(vBuf.d3[idN].vtX), &(vBuf.d3[idN].vtY),
		     &(vBuf.d3[idN].vtZ),
		     &bnd) == 5) && (idx = idN + 1))
	  {
	    if(idN == 0)
	    {
	      mesh.m3->bBox.xMin = mesh.m3->bBox.xMax = vBuf.d3[idN].vtX;
	      mesh.m3->bBox.yMin = mesh.m3->bBox.yMax = vBuf.d3[idN].vtY;
	      mesh.m3->bBox.zMin = mesh.m3->bBox.zMax = vBuf.d3[idN].vtZ;
	    }
	    else
	    {
	      if(vBuf.d3[idN].vtX < mesh.m3->bBox.xMin)
	      {
		mesh.m3->bBox.xMin = vBuf.d3[idN].vtX;
	      }
	      else if(vBuf.d3[idN].vtX > mesh.m3->bBox.xMax)
	      {
		mesh.m3->bBox.xMax = vBuf.d3[idN].vtX;
	      }
	      if(vBuf.d3[idN].vtY < mesh.m3->bBox.yMin)
	      {
		mesh.m3->bBox.yMin = vBuf.d3[idN].vtY;
	      }
	      else if(vBuf.d3[idN].vtY > mesh.m3->bBox.yMax)
	      {
		mesh.m3->bBox.yMax = vBuf.d3[idN].vtY;
	      }
	      if(vBuf.d3[idN].vtZ < mesh.m3->bBox.zMin)
	      {
		mesh.m3->bBox.zMin = vBuf.d3[idN].vtZ;
	      }
	      else if(vBuf.d3[idN].vtZ > mesh.m3->bBox.zMax)
	      {
		mesh.m3->bBox.zMax = vBuf.d3[idN].vtZ;
	      }
	    }
	    ++idN;
	  }
	  else
	  {
	    errNum = WLZ_ERR_READ_INCOMPLETE;
	    break;
	  }
	}
      }
      /* Create the nodes. */
      if(errNum == WLZ_ERR_NONE)
      {
	if(AlcVectorExtendAndGet(mesh.m3->res.nod.vec, nNod) == NULL)
	{
	  errNum = WLZ_ERR_MEM_ALLOC;
	}
	else
	{
	  errNum = WlzCMeshReassignGridCells3D(mesh.m3, nNod);
	}
      }
      if(errNum == WLZ_ERR_NONE)
      {
	for(idN = 0; idN < nNod; ++idN)
	{
	   nBuf3[0] = WlzCMeshNewNod3D(mesh.m3, vBuf.d3[idN], NULL);
	   nBuf3[0]->pos = vBuf.d3[idN];
	   nBuf3[0]->flags = 0;
	}
      }
    }
  }
  AlcFree(vBuf.v);
  /* Close node file. */
  if(fP)
  {
    (void )fclose(fP);
    fP = NULL;
  }
  /* Read in the elements from the .ele file and create them. */
  if(errNum == WLZ_ERR_NONE)
  {
    if((eleFileName == NULL) || (*eleFileName == '\0') ||
       ((fP = fopen(eleFileName, "r")) == NULL))
    {
      errNum = WLZ_ERR_READ_EOF;
    }
#ifdef _WIN32
    if(fP != NULL)
    {
      if(_setmode(_fileno(fP), 0x8000) == -1)
      {
        errNum = WLZ_ERR_READ_EOF;
      }
    }
#endif
  }
  if(errNum == WLZ_ERR_NONE)
  {
    /* Optional records may be comments starting with a '#' but apart
     * from these the first line should have four integers specifying
     * the number of nodes, the dimension, the number of attributes
     * and the number of boundary markers. */
    cnt = 0;
    do
    {
      if((str = WlzEffReadObjNodeEleRec(fP, cBuf, 256)) == NULL)
      {
	errNum = WLZ_ERR_READ_INCOMPLETE;
      }
      else if(*str != '#')
      {
	if((cnt = sscanf(str, "%d %d %d",
	                 &nElm, &nodPerElm, &nAtr)) != 3)
	{
	  errNum = WLZ_ERR_READ_INCOMPLETE;
	}
      }
    } while((errNum == WLZ_ERR_NONE) && (cnt != 3));
  }
  /* Check for reasonable number of nodes, etc.... */
  if(errNum == WLZ_ERR_NONE)
  {
    if((nElm <= 0) || (nodPerElm != dim + 1) || (nAtr != 0))
    {
      errNum = WLZ_ERR_READ_INCOMPLETE;
    }
  }
  if(errNum == WLZ_ERR_NONE)
  {
    idE = 0;
    if(dim == 2)
    {
      if(AlcVectorExtendAndGet(mesh.m2->res.elm.vec, nElm) == NULL)
      {
        errNum = WLZ_ERR_MEM_ALLOC;
      }
      while((errNum == WLZ_ERR_NONE) && (idE < nElm))
      {
	if((str = WlzEffReadObjNodeEleRec(fP, cBuf, 256)) == NULL)
	{
	  errNum = WLZ_ERR_READ_INCOMPLETE;
	  break;
	}
	else if(*str != '#')
	{
	  if(sscanf(str, "%d %d %d %d",
		    &idx, eBuf + 0, eBuf + 1, eBuf + 2) == 4)
	  {
	    if((idx != idE + 1) ||
	       (eBuf[0] <= 0) || (eBuf[0] > nNod) ||
	       (eBuf[1] <= 0) || (eBuf[1] > nNod) ||
	       (eBuf[2] <= 0) || (eBuf[2] > nNod))
	    {
	      errNum = WLZ_ERR_MEM_ALLOC;
	      break;
	    }
	    for(idN = 0; idN < 4; ++idN)
	    {
	      nBuf2[idN] = (WlzCMeshNod2D *)
			   AlcVectorItemGet(mesh.m2->res.nod.vec,
			                    eBuf[idN] - 1);
	    }
	    (void )WlzCMeshNewElm2D(mesh.m2, nBuf2[0], nBuf2[2], nBuf2[1],
				    1, &errNum);
	    ++idE;
	  }
	  else
	  {
	    errNum = WLZ_ERR_READ_INCOMPLETE;
	    break;
	  }
        }
      }
      if(errNum == WLZ_ERR_NONE)
      {
	WlzCMeshUpdateMaxSqEdgLen2D(mesh.m2);
	dom.cm2 = mesh.m2;
	obj = WlzMakeMain(WLZ_CMESH_2D, dom, val, NULL, NULL, &errNum);
      }
    }
    else /* dim == 3 */
    {
      if(AlcVectorExtendAndGet(mesh.m3->res.elm.vec, nElm) == NULL)
      {
        errNum = WLZ_ERR_MEM_ALLOC;
      }
      while((errNum == WLZ_ERR_NONE) && (idE < nElm))
      {
	if((str = WlzEffReadObjNodeEleRec(fP, cBuf, 256)) == NULL)
	{
	  errNum = WLZ_ERR_READ_INCOMPLETE;
	  break;
	}
	else if(*str != '#')
	{
	  if(sscanf(str, "%d %d %d %d %d",
		    &idx, eBuf + 0, eBuf + 1, eBuf + 2, eBuf + 3) == 5)
	  {
	    if((eBuf[0] <= 0) || (eBuf[0] > nNod) ||
	       (eBuf[1] <= 0) || (eBuf[1] > nNod) ||
	       (eBuf[2] <= 0) || (eBuf[2] > nNod) ||
	       (eBuf[3] <= 0) || (eBuf[3] > nNod))
	    {
	      errNum = WLZ_ERR_MEM_ALLOC;
	      break;
	    }
	    for(idN = 0; idN < 4; ++idN)
	    {
	      nBuf3[idN] = (WlzCMeshNod3D *)
			   AlcVectorItemGet(mesh.m3->res.nod.vec,
			                    eBuf[idN] - 1);
	    }
	    (void )WlzCMeshNewElm3D(mesh.m3,
				    nBuf3[0], nBuf3[1], nBuf3[3], nBuf3[2], 1, &errNum);
	    ++idE;
	  }
	  else
	  {
	    errNum = WLZ_ERR_READ_INCOMPLETE;
	    break;
	  }
        }
      }
      if(errNum == WLZ_ERR_NONE)
      {
	WlzCMeshUpdateMaxSqEdgLen3D(mesh.m3);
	dom.cm3 = mesh.m3;
	obj = WlzMakeMain(WLZ_CMESH_3D, dom, val, NULL, NULL, &errNum);
      }
    }
  }
  /* Close element file. */
  if(fP)
  {
    (void )fclose(fP);
  }
  if(errNum != WLZ_ERR_NONE)
  {
    if(dim == 2)
    {
      (void )WlzCMeshFree2D(mesh.m2);
    }
    else if(dim == 3)
    {
      (void )WlzCMeshFree3D(mesh.m3);
    }
  }
  if(dstErr)
  {
    *dstErr = errNum;
  }
  return(obj);
}
Exemplo n.º 15
0
int		main(int argc, char *argv[])
{
  int		idN,
  		idM,
		nSeeds,
  		nBndSeeds,
		boundFlg = 0,
		imgFlg = 0,
		interp = 0,
  		seedFlg = 0,
  		ok = 1,
  		option,
  		usage = 0;
  size_t	vtxSize = sizeof(WlzDVertex2);
  WlzObjectType	outObjType;
  WlzVertexType bndVtxType;
  WlzVertex	seed;
  WlzVertexP	bndSeeds,
		seeds;
  FILE		*fP = NULL;
  char		*outObjFileStr,
  		*refObjFileStr = NULL,
		*meshFileStr;
  const char	*errMsgStr;
  WlzErrorNum	errNum = WLZ_ERR_NONE;
  WlzObject	*outObj = NULL,
		*mshObj = NULL,
  		*refObj = NULL;
  WlzCMeshP 	mesh;
  WlzCMeshNodP	nod;
  static char   optList[] = "bhiLo:r:s:";
  const char    meshFileStrDef[] = "-",
  	        outObjFileStrDef[] = "-";

  mesh.v = NULL;
  opterr = 0;
  seeds.v = NULL;
  bndSeeds.v = NULL;
  outObjFileStr = (char *)outObjFileStrDef;
  meshFileStr = (char *)meshFileStrDef;
  seed.d3.vtX = seed.d3.vtY = seed.d3.vtZ = 0.0;
  while((usage == 0) && ((option = getopt(argc, argv, optList)) != EOF))
  {
    switch(option)
    {
      case 'b':
	boundFlg = 1;
        break;
      case 'i':
	imgFlg = 1;
        break;
      case 's':
	seedFlg = 1;
        if(sscanf(optarg, "%lg,%lg,%lg",
	          &(seed.d3.vtX), &(seed.d3.vtY), &(seed.d3.vtZ)) < 1)
	{
	  usage = 1;
	}
	break;
      case 'o':
        outObjFileStr = optarg;
	break;
      case 'r':
        refObjFileStr = optarg;
	break;
      case 'L':
        interp = 1;
	break;
      case 'h': /* FALLTHROUGH */
      default:
	usage = 1;
	break;
    }
  }
  ok = usage == 0;
  if(ok)
  {
    if((meshFileStr == NULL) || (*meshFileStr == '\0') ||
       (outObjFileStr == NULL) || (*outObjFileStr == '\0'))
    {
      ok = 0;
      usage = 1;
    }
    if(ok && (optind < argc))
    {
      if((optind + 1) != argc)
      {
        usage = 1;
        ok = 0;
      }
      else
      {
        meshFileStr = *(argv + optind);
      }
    }
  }
  if(ok && refObjFileStr)
  {
    if(((fP = (strcmp(refObjFileStr, "-")?
              fopen(refObjFileStr, "r"): stdin)) == NULL) ||
       ((refObj = WlzAssignObject(WlzReadObj(fP, &errNum), NULL)) == NULL) ||
       (errNum != WLZ_ERR_NONE))
    {
      ok = 0;
      (void )fprintf(stderr,
                     "%s: failed to read reference object from file %s\n",
                     *argv, refObjFileStr);
    }
    if(fP && strcmp(refObjFileStr, "-"))
    {
      (void )fclose(fP); fP = NULL;
    }
  }
  if(ok)
  {
    if(((fP = (strcmp(meshFileStr, "-")?
              fopen(meshFileStr, "r"): stdin)) == NULL) ||
       ((mshObj = WlzAssignObject(WlzReadObj(fP, &errNum), NULL)) == NULL) ||
       (errNum != WLZ_ERR_NONE))
    {
      ok = 0;
      (void )fprintf(stderr,
                     "%s: failed to read mesh object from file %s\n",
                     *argv, meshFileStr);
    }
    if(fP && strcmp(meshFileStr, "-"))
    {
      (void )fclose(fP); fP = NULL;
    }
  }
  if(ok)
  {
    switch(mshObj->type)
    {
      case WLZ_CMESH_2D:
	mesh.m2 = mshObj->domain.cm2;
	break;
      case WLZ_CMESH_3D:
	mesh.m3 = mshObj->domain.cm3;
	break;
      default:
        ok = 0;
	errNum = WLZ_ERR_OBJECT_TYPE;
	(void )WlzStringFromErrorNum(errNum, &errMsgStr);
	(void )fprintf(stderr,
		 "%s: Invalid mesh object, must be WLZ_CMESH_[23]D (%s),\n",
		 argv[0],
		 errMsgStr);
	break;
    }
  }
  if(ok && mshObj)
  {
    switch(mshObj->type)
    {
      case WLZ_CMESH_2D:
	vtxSize = sizeof(WlzDVertex2);
        if((refObj != NULL) && (refObj->type != WLZ_2D_DOMAINOBJ))
	{
	  ok = 0;
	}
	break;
      case WLZ_CMESH_3D:
	vtxSize = sizeof(WlzDVertex3);
        if((refObj != NULL) && (refObj->type != WLZ_3D_DOMAINOBJ))
	{
	  ok = 0;
	}
	break;
      default:
        ok = 0;
    }
    if(ok == 0)
    {
	errNum = WLZ_ERR_OBJECT_TYPE;
	(void )WlzStringFromErrorNum(errNum, &errMsgStr);
	(void )fprintf(stderr,
		 "%s: Mesh and reference objects must have the same\n"
		 "dimension (%s)\n",
		 argv[0],
		 errMsgStr);
    }
  }
  /* Create seed buffer. */
  if(ok)
  {
    nSeeds = (seedFlg != 0);
    if(boundFlg)
    {
      nSeeds += WlzCMeshSetBoundNodFlags(mesh);
    }
    if(refObj)
    {
      bndSeeds = WlzVerticesFromObjBnd(refObj, &nBndSeeds, &bndVtxType,
      				       &errNum);
      nSeeds += nBndSeeds;
    }
    if(errNum != WLZ_ERR_NONE)
    {
      ok = 0;
      (void )WlzStringFromErrorNum(errNum, &errMsgStr);
      (void )fprintf(stderr,
               "%s: Failed to extract seeds (%s)\n",
	       argv[0],
	       errMsgStr);
    }
    else if(nSeeds < 1)
    {
      ok = 0;
      (void )fprintf(stderr,
	       "%s: Number of seeds must be > 0.\n",
	       argv[0]);
    }
  }
  if(ok)
  {
    if((seeds.v = AlcMalloc(vtxSize * nSeeds)) == NULL)
    {
      ok = 0;
      errNum = WLZ_ERR_MEM_ALLOC;
      (void )WlzStringFromErrorNum(errNum, &errMsgStr);
      (void )fprintf(stderr,
		"%s: Failed to allocate seed buffer (%s)\n",
		argv[0],
		errMsgStr);
    }
  }
  if(ok)
  {
    switch(mshObj->type)
    {
      case WLZ_CMESH_2D:
	idN = 0;
	outObjType = (imgFlg != 0)? WLZ_2D_DOMAINOBJ: WLZ_CMESH_2D;
	if(seedFlg)
	{
	  idN = 1;
	  seeds.d2->vtX = seed.d2.vtX;
	  seeds.d2->vtY = seed.d2.vtY;
	}
	if(boundFlg)
	{
	  for(idM = 0; idM < mesh.m2->res.nod.maxEnt; ++idM)
	  {
	    nod.n2 = (WlzCMeshNod2D *)
	             AlcVectorItemGet(mesh.m2->res.nod.vec, idM);
	    if((nod.n2->idx >= 0) &&
	       ((nod.n2->flags & WLZ_CMESH_NOD_FLAG_BOUNDARY) != 0))
	    {
	      seeds.d2[idN++] = nod.n2->pos;
	    }
	  }
	}
	if(refObj)
	{
	  switch(bndVtxType)
	  {
	    case WLZ_VERTEX_I2:
	      WlzValueCopyIVertexToDVertex(seeds.d2 + idN, bndSeeds.i2,
	      				   nBndSeeds);
	      break;
	    case WLZ_VERTEX_F2:
	      WlzValueCopyFVertexToDVertex(seeds.d2 + idN, bndSeeds.f2,
	      				   nBndSeeds);
	      break;
	    case WLZ_VERTEX_D2:
	      WlzValueCopyDVertexToDVertex(seeds.d2 + idN, bndSeeds.d2,
	      				   nBndSeeds);
	      break;
	    default:
	      errNum = WLZ_ERR_PARAM_TYPE;
	      break;
	  }
	}
	if(errNum == WLZ_ERR_NONE)
	{
	  outObj = WlzCMeshDistance2D(mshObj, outObjType,
	                              nSeeds, seeds.d2,
				      (interp)? WLZ_INTERPOLATION_KRIG:
				                WLZ_INTERPOLATION_BARYCENTRIC,
				      &errNum);
	}
	break;
      case WLZ_CMESH_3D:
	idN = 0;
	outObjType = (imgFlg != 0)? WLZ_3D_DOMAINOBJ: WLZ_CMESH_3D;
	if(seedFlg)
	{
	  idN = 1;
	  seeds.d3->vtX = seed.d3.vtX;
	  seeds.d3->vtY = seed.d3.vtY;
	  seeds.d3->vtZ = seed.d3.vtZ;
	}
	if(boundFlg)
	{
	  for(idM = 0; idM < mesh.m3->res.nod.maxEnt; ++idM)
	  {
	    nod.n3 = (WlzCMeshNod3D *)
	             AlcVectorItemGet(mesh.m3->res.nod.vec, idM);
	    if((nod.n3->idx >= 0) &&
	       ((nod.n3->flags & WLZ_CMESH_NOD_FLAG_BOUNDARY) != 0))
	    {
	      seeds.d3[idN++] = nod.n3->pos;
	    }
	  }
	}
	if(refObj)
	{
	  switch(bndVtxType)
	  {
	    case WLZ_VERTEX_I3:
	      WlzValueCopyIVertexToDVertex3(seeds.d3 + idN, bndSeeds.i3,
	      				    nBndSeeds);
	      break;
	    case WLZ_VERTEX_F3:
	      WlzValueCopyFVertexToDVertex3(seeds.d3 + idN, bndSeeds.f3,
	      				    nBndSeeds);
	      break;
	    case WLZ_VERTEX_D3:
	      WlzValueCopyDVertexToDVertex3(seeds.d3 + idN, bndSeeds.d3,
	      				    nBndSeeds);
	      break;
	    default:
	      errNum = WLZ_ERR_PARAM_TYPE;
	      break;
	  }
	}
	if(errNum == WLZ_ERR_NONE)
	{
	  outObj = WlzCMeshDistance3D(mshObj, outObjType,
	  	                      nSeeds, seeds.d3,
				      (interp)? WLZ_INTERPOLATION_KRIG:
				                WLZ_INTERPOLATION_BARYCENTRIC,
				      &errNum);
	}
	break;
	break;
      default:
	break;
    }
    if(errNum != WLZ_ERR_NONE)
    {
      ok = 0;
      (void )WlzStringFromErrorNum(errNum, &errMsgStr);
      (void )fprintf(stderr,
		"%s: Failed to create domain object with distances (%s)\n",
		argv[0],
		errMsgStr);
    }
  }
  AlcFree(seeds.v);
  AlcFree(bndSeeds.v);
  WlzFreeObj(refObj);
  WlzFreeObj(mshObj);
  if(ok)
  {
    errNum = WLZ_ERR_WRITE_EOF;
    if(((fP = (strcmp(outObjFileStr, "-")?
              fopen(outObjFileStr, "w"): stdout)) == NULL) ||
       ((errNum = WlzWriteObj(fP, outObj)) != WLZ_ERR_NONE))
    {
      ok = 0;
      (void )fprintf(stderr,
                     "%s: failed to write output object to file %s\n",
                     *argv, outObjFileStr);
    }
    if(fP && strcmp(outObjFileStr, "-"))
    {
      (void )fclose(fP); fP = NULL;
    }
  }
  (void )WlzFreeObj(outObj);
  if(usage)
  {
    fprintf(stderr,
            "Usage: %s [-b] [-h] [-o<out obj file>] [-r<ref obj file>]\n"
	    "                        [-L] [-s #,#,#] [<input mesh file>]\n"
	    "Constructs a 2D or 3D domain object the values of which are\n"
	    "the minimum distance from the given seeds points in the given\n"
	    "conforming mesh. The domain of the output object covers the\n"
	    "input mesh.\n"
	    "Version: %s\n"
	    "Options:\n"
	    "  -h  Help, prints this usage message.\n"
            "  -i  Output an image (ie a 2 or 3D domain object) with\n"
	    "      interpolated distance values rather than a mesh with\n"
	    "      indexed values.\n"
	    "  -L  Use expensive interpolation (mainly useful as a test).\n"
	    "  -o  Output object.\n"
	    "  -b  Set seed points around the boundary of the mesh.\n"
	    "  -s  Single seed position.\n"
	    "  -r  Reference object with seed points around it's boundary.\n",
	    argv[0],
	    WlzVersion());

  }
  return(!ok);
}