/*! * \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); }
/*! * \return Dimension of the given object: * \ingroup WlzFeatures * \brief Returns the dimension of the given object. * \param obj Given object. * \param dstErr Destination error pointer, may be NULL. */ int WlzObjectDimension(WlzObject *obj, WlzErrorNum *dstErr) { int dim = 0; WlzErrorNum errNum = WLZ_ERR_NONE; if(obj == NULL) { errNum = WLZ_ERR_OBJECT_NULL; } else { switch(obj->type) { /* Objects which don't have a dimension. */ case WLZ_CONVOLVE_FLOAT: /* FALLTHROUGH */ case WLZ_CONVOLVE_INT: /* FALLTHROUGH */ case WLZ_EMPTY_OBJ: /* FALLTHROUGH */ case WLZ_HISTOGRAM: /* FALLTHROUGH */ case WLZ_LUT: /* FALLTHROUGH */ case WLZ_PROPERTY_OBJ: /* FALLTHROUGH */ case WLZ_TEXT: dim = 0; break; /* Objects which are clearly 2D. */ case WLZ_2D_DOMAINOBJ: /* FALLTHROUGH */ case WLZ_2D_POLYGON: /* FALLTHROUGH */ case WLZ_BOUNDLIST: /* FALLTHROUGH */ case WLZ_CMESH_2D: /* FALLTHROUGH */ case WLZ_RECTANGLE: dim = 2; break; /* Objects which are clearly 3D. */ case WLZ_3D_DOMAINOBJ: /* FALLTHROUGH */ case WLZ_3D_POLYGON: /* FALLTHROUGH */ case WLZ_3D_WARP_TRANS: /* FALLTHROUGH */ case WLZ_CMESH_2D5: /* FALLTHROUGH */ case WLZ_CMESH_3D: dim = 3; break; /* Objects which need to have their domain checked. */ case WLZ_TRANS_OBJ: if(obj->domain.core == NULL) { errNum = WLZ_ERR_DOMAIN_NULL; } else { dim = WlzAffineTransformDimension(obj->domain.t, &errNum); } break; case WLZ_CONV_HULL: if(obj->domain.core == NULL) { errNum = WLZ_ERR_DOMAIN_NULL; } else { switch(obj->domain.core->type) { case WLZ_CONVHULL_DOMAIN_2D: dim = 2; break; case WLZ_CONVHULL_DOMAIN_3D: dim = 3; break; default: errNum = WLZ_ERR_DOMAIN_TYPE; break; } } break; case WLZ_CONTOUR: if((obj->domain.core == NULL) || (obj->domain.ctr->model == NULL)) { errNum = WLZ_ERR_DOMAIN_NULL; } else { dim = WlzGMModelGetDimension(obj->domain.ctr->model, &errNum); } break; case WLZ_POINTS: if(obj->domain.core == NULL) { errNum = WLZ_ERR_DOMAIN_NULL; } else { switch(obj->domain.pts->type) { case WLZ_POINTS_2I: /* FALLTHROUGH */ case WLZ_POINTS_2D: dim = 2; break; case WLZ_POINTS_3I: /* FALLTHROUGH */ case WLZ_POINTS_3D: dim = 3; break; default: errNum = WLZ_ERR_DOMAIN_TYPE; break; } } break; case WLZ_AFFINE_TRANS: if(obj->domain.core == NULL) { errNum = WLZ_ERR_DOMAIN_NULL; } else { dim = WlzAffineTransformDimension(obj->domain.t, &errNum); } break; case WLZ_COMPOUND_ARR_1: /* FALLTHROUGH */ case WLZ_COMPOUND_ARR_2: { int idx; WlzCompoundArray *ca; ca = (WlzCompoundArray *)obj; if(ca->n < 0) { errNum = WLZ_ERR_OBJECT_NULL; } else { dim = WlzObjectDimension(ca->o[0], &errNum); for(idx = 1; (errNum == WLZ_ERR_NONE) && (idx < ca->n); ++idx) { int d; d = WlzObjectDimension(ca->o[idx], &errNum); if((errNum == WLZ_ERR_NONE) && (d != dim)) { errNum = WLZ_ERR_OBJECT_TYPE; } } } } break; case WLZ_MESH_TRANS: if(obj->domain.core == NULL) { errNum = WLZ_ERR_DOMAIN_NULL; } else { switch(obj->domain.core->type) { case WLZ_TRANSFORM_2D_MESH: dim = 2; break; case WLZ_TRANSFORM_2D5_MESH: /* FALLTHROUGH */ case WLZ_TRANSFORM_3D_MESH: dim = 3; break; default: errNum = WLZ_ERR_DOMAIN_TYPE; break; } } break; case WLZ_CMESH_TRANS: if(obj->domain.core == NULL) { errNum = WLZ_ERR_DOMAIN_NULL; } else { switch(obj->domain.core->type) { case WLZ_TRANSFORM_2D_CMESH: dim = 2; break; case WLZ_TRANSFORM_2D5_CMESH: /* FALLTHROUGH */ case WLZ_TRANSFORM_3D_CMESH: dim = 3; break; default: errNum = WLZ_ERR_DOMAIN_TYPE; break; } } break; /* Objects which aren't supported. */ case WLZ_COMPOUND_LIST_1: /* FALLTHROUGH */ case WLZ_COMPOUND_LIST_2: /* FALLTHROUGH */ case WLZ_FMATCHOBJ: /* FALLTHROUGH */ case WLZ_WARP_TRANS: /* FALLTHROUGH */ default: errNum = WLZ_ERR_OBJECT_TYPE; break; } } if(dstErr) { *dstErr = errNum; } return(dim); }