// Changes the size of the current point given the zoom and scroll wheel delta value void utilWheelChangePointSize(ImodView *vi, float zoom, int delta) { int ix, iy, pt; Iobj *obj; Icont *cont; float size; imodGetIndex(vi->imod, &ix, &iy, &pt); obj = imodObjectGet(vi->imod); cont = imodContourGet(vi->imod); if (!cont || pt < 0) return; size = imodPointGetSize(obj, cont, pt); if (!size && (!cont->sizes || (cont->sizes && cont->sizes[pt] < 0))) return; size += delta * utilWheelToPointSizeScaling(zoom); size = B3DMAX(0., size); vi->undo->contourDataChg(); imodPointSetSize(cont, pt, size); vi->undo->finishUnit(); imodDraw(vi, IMOD_DRAW_MOD); }
/* * Analyze spherical points in the given object and convert them to vectors and * normals for faster drawing */ int VertBufManager::analyzeSpheres(Iobj *obj, int obNum, float zscale, int xybin, float scrnScale, int quality, int fillType, int useFillColor, int thickenCont, int checkTime) { RGBTmap colors; pair<RGBTmap::iterator,bool> mapret; RGBTmap::iterator mapit; RGBTindices rInd; DrawProps defProps, contProps; b3dUInt32 contRGBT; VertBufData *vbd = obj->vertBufSphere; Icont *cont; int handleFlags, nonVboFlags = 0, numRemnant, fullState, skip, numVerts, co, pt; int colorType, cumFanInd, cumQuadInd, surfState, contState, stepRes; float drawsize; int numDefSphVert, numDefSphQuad, numDefSphFan, numTriples,indVert, indQuad, indFan; int indQuadDef, indFanDef, irem, match; if (fillType > 0) handleFlags = (useFillColor ? CHANGED_FCOLOR : CHANGED_COLOR) | CHANGED_TRANS; else { handleFlags = CHANGED_COLOR | CHANGED_TRANS; nonVboFlags = CHANGED_3DWIDTH; } colorType = useFillColor ? GEN_STORE_FCOLOR : GEN_STORE_COLOR; istoreDefaultDrawProps(obj, &defProps); // Check if there is a current VBO and it is all still valid // TODO: handle finegrain AND size changes //packRGBT(defProps, useFillColor, contRGBT); if (vbd && vbd->vbObj && fillType == vbd->fillType && vbd->useFillColor == useFillColor && quality == vbd->quality && obj->pdrawsize == vbd->pdrawsize && checkTime == vbd->checkTime && fabs((double)(scrnScale - vbd->scrnScale)) < 1.e-4 && fabs((double)(zscale - vbd->zscale)) < 1.e-4 && (fillType != 0 || thickenCont == vbd->thickenCont)) { match = 1; if (fillType == 0 && thickenCont) match = checkSelectedAreRemnants(vbd, obNum); if (match && !Imodv->standalone && obNum == Imodv->imod->cindex.object && vbd->checksum != imodObjectChecksum(obj, obNum)) match = 0; if (match) return -1; } numRemnant = 0; cumQuadInd = 0; cumFanInd = 0; numVerts = 0; for (co = 0; co < obj->contsize; co++) { cont = &obj->cont[co]; setOrClearFlags(&cont->flags, ICONT_TEMPUSE, 0); if (!imodvCheckContourDraw(cont, co, checkTime)) continue; fullState = istoreContSurfDrawProps(obj->store, &defProps, &contProps, co, cont->surf, &contState, &surfState); // Skip a gap without counting it; count one to be excluded or that can't be handled if (contProps.gap) continue; skip = 0; if ((fullState & nonVboFlags) || (thickenCont && imodvCheckThickerContour(co))) skip = 1; // Check for point changes that would need to be handled if (!skip && cont->store) { if (istoreCountItems(cont->store, colorType, 1) || istoreCountItems(cont->store, GEN_STORE_TRANS, 1)) skip = 1; if (!skip && fillType <= 0 && istoreCountItems(cont->store, GEN_STORE_3DWIDTH, 1)) skip = 1; } if (skip) { setOrClearFlags(&cont->flags, ICONT_TEMPUSE, 1); numRemnant++; continue; } // Loop on the points and determine number of vertices and indices needed for each // Since we don't skip point drawing, this doesn't need store changes checked rInd.numInds = 0; rInd.numFanInds = 0; for (pt = 0; pt < cont->psize; pt++) { // Only draw zero-size points with scattered point objects drawsize = imodPointGetSize(obj, cont, pt) / xybin; if (!iobjScat(obj->flags) && !drawsize) continue; stepRes = sphereResForSize(drawsize); numVerts += sphereCounts(2 * stepRes, stepRes, fillType, rInd.numInds, rInd.numFanInds); // For a special contour, add to list of RGBT values with the counts if it // is not on the list; if it is already on the list increment its count; if (fullState & handleFlags) { rInd.firstElement = co; packRGBT(&contProps, useFillColor, contRGBT); mapret = colors.insert(pair<b3dUInt32,RGBTindices>(contRGBT, rInd)); if (mapret.second == false) { mapret.first->second.numInds += rInd.numInds; mapret.first->second.numFanInds += rInd.numFanInds; } } else { cumQuadInd += rInd.numInds; cumFanInd += rInd.numFanInds; } } } if (!numVerts) { vbCleanupSphereVBD(obj); return 2; } // Get parameters for default sphere drawsize = obj->pdrawsize / xybin; stepRes = sphereResForSize(drawsize); numDefSphVert = sphereCounts(2 * stepRes, stepRes, fillType, numDefSphQuad, numDefSphFan); imodTrace('b', "numverts %d cumfan %d cumquad %d def vert %d quad %d fan %d rem %d", numVerts, cumFanInd, cumQuadInd, numDefSphVert,numDefSphQuad, numDefSphFan, numRemnant); vbd = allocateVBDIfNeeded(&obj->vertBufSphere); if (!vbd || drawsize < 0) { vbCleanupSphereVBD(obj); return 1; } vbd->numFanIndDefault = cumFanInd; vbd->numRemnant = numRemnant; // Now allocate whatever pieces are needed in VBD // Add up the special set sizes and re-initialize the counts to be starting indexes if (allocateSpecialSets(vbd, colors.size(), cumQuadInd, 1) || processMap(vbd, &colors, cumQuadInd, 1, cumFanInd)) { vbCleanupSphereVBD(obj); return 1; } vbd->fanIndStart = cumQuadInd; // Now allocate temps plus default sphere numTriples = (1 + (fillType > 0 ? 1 : 0)) * numVerts; if (allocateTempVerts(numTriples) || allocateTempInds(cumFanInd) || allocateDefaultSphere(numDefSphVert, numDefSphQuad + numDefSphFan, fillType)) { vbCleanupSphereVBD(obj); return 1; } if (genAndBindBuffers(vbd, numTriples, cumFanInd)) { vbCleanupSphereVBD(obj); return 1; } // Build the default sphere indVert = 0; indQuad = 0; indFan = numDefSphQuad; makeSphere(drawsize, 2 * stepRes, stepRes, mDefSphVerts, mDefSphInds, indVert, indQuad, indFan, fillType, 0., 0., 0.); imodTrace('b', "numtriples %d cumquad %d cumfan %d after def vert %d quad %d fan %d", numTriples, cumQuadInd, cumFanInd, indVert, indQuad, indFan); /*for (pt = 0; pt < indFan; pt++) { imodPrintStderr(" %d", mDefSphInds[pt]); if ((pt + 1) % 16 == 0 || pt == indFan - 1) imodPrintStderr("\n"); } */ // Set the identifiers of this vb data vbd->zscale = zscale; vbd->fillType = fillType; vbd->useFillColor = useFillColor; packRGBT(&defProps, useFillColor, vbd->defaultRGBT); vbd->checkTime = checkTime; vbd->scrnScale = scrnScale; vbd->quality = quality; vbd->pdrawsize = obj->pdrawsize; vbd->thickenCont = thickenCont; vbd->checksum = imodObjectChecksum(obj, obNum); // Process contours and points in them indVert = 0; indQuadDef = 0; indFanDef = cumQuadInd; irem = 0; for (co = 0; co < obj->contsize; co++) { cont = &obj->cont[co]; if (!imodvCheckContourDraw(cont, co, checkTime)) continue; fullState = istoreContSurfDrawProps(obj->store, &defProps, &contProps, co, cont->surf, &contState, &surfState); if (contProps.gap) continue; // Add marked contours to the remnant list if (cont->flags & ICONT_TEMPUSE) { setOrClearFlags(&cont->flags, ICONT_TEMPUSE, 0); vbd->remnantIndList[irem++] = co; continue; } // Set the starting indices for the contour's quads and fans if (fullState & handleFlags) { packRGBT(&contProps, useFillColor, contRGBT); mapit = colors.find(contRGBT); indQuad = mapit->second.numInds; indFan = mapit->second.numFanInds; } else { indQuad = indQuadDef; indFan = indFanDef; } // Loop on the points and make sohere or copy the default for (pt = 0; pt < cont->psize; pt++) { drawsize = imodPointGetSize(obj, cont, pt); if (!iobjScat(obj->flags) && !drawsize) continue; if (drawsize == obj->pdrawsize) { copyDefaultSphere(mDefSphVerts, mDefSphInds, numDefSphVert, numDefSphQuad, numDefSphFan, fillType, mVerts, mInds, indVert, indQuad, indFan, cont->pts[pt].x, cont->pts[pt].y, cont->pts[pt].z * zscale); } else { drawsize /= xybin; stepRes = sphereResForSize(drawsize); makeSphere(drawsize, 2 * stepRes, stepRes, mVerts, mInds, indVert, indQuad, indFan, fillType, cont->pts[pt].x, cont->pts[pt].y, cont->pts[pt].z * zscale); } } // Save the new indices back where they came from if (fullState & handleFlags) { mapit->second.numInds = indQuad; mapit->second.numFanInds = indFan; } else { indQuadDef = indQuad; indFanDef = indFan; } } imodTrace('b', "cumfan %d after load vert %d quad %d fan %d irem %d", cumFanInd, indVert, indQuad, indFan, irem); /* for (pt = 0; pt < cumFanInd; pt++) { imodPrintStderr(" %d", mInds[pt]); if ((pt + 1) % 16 == 0 || pt == cumFanInd - 1) imodPrintStderr("\n"); } */ // Transfer to GL b3dBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, cumFanInd * sizeof(GLuint), mInds); b3dBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); b3dBufferSubData(GL_ARRAY_BUFFER, 0, numTriples * 3 * sizeof(GLfloat), mVerts); b3dBindBuffer(GL_ARRAY_BUFFER, 0); return 0; }
/* DNM 6/17/01: pass the selection size as a parameter so that windows can make it zoom-dependent */ float imod_obj_nearest(ImodView *vi, Iobj *obj, Iindex *index, Ipoint *pnt, float selsize, int ctime, Imat *mat) { Icont *cont; int i, pindex; float distance = -1.; float temp_distance; int cz = (int)floor(pnt->z + 0.5); int twod = 0; double rad, delz; Ipoint scale, pntrot, ptsrot; /* Ignore Z value if 2d image. */ twod = (!(vi->dim & 4)); scale.x = scale.y = 1.; scale.z = ((vi->imod->zscale > 0. ? vi->imod->zscale : 1.) * vi->zbin) / vi->xybin; if (mat) imodMatTransform3D(mat, pnt, &pntrot); for (i = 0; i < obj->contsize; i++){ cont = &(obj->cont[i]); /* Don't report points not in our time. DNM - unless time is 0*/ if ((ctime) && (obj->flags & IMOD_OBJFLAG_TIME) && (cont->time) && (cont->time != ctime)) continue; if (!cont->psize) continue; if (mat) { // If a matrix is supplied, rotate each point and test with rotated pnt for (pindex = 0; pindex < cont->psize; pindex++) { imodMatTransform3D(mat, &cont->pts[pindex], &ptsrot); if ((fabs((double)(pntrot.x - ptsrot.x)) < selsize) && (fabs((double)(pntrot.y - ptsrot.y)) < selsize)) { delz = 0.5; // get radius of point and maximum Z difference that will work // Assume points are visible on too many sections in slicer if (obj->pdrawsize || cont->sizes) { rad = imodPointGetSize(obj, cont, pindex); if (rad > 1.) delz = sqrt(rad * rad - 1.); } if (fabs((double)(ptsrot.z - pntrot.z)) <= delz) { temp_distance = imodPoint3DScaleDistance(&pntrot, &ptsrot, &scale); if (distance < 0. || distance > temp_distance){ distance = temp_distance; index->contour = i; index->point = pindex; } } } } } else if ((obj->pdrawsize || cont->sizes) && !twod) { // If there could be 3D points, then allow attachment to any point // that should be visible on the plane for(pindex = 0; pindex < cont->psize; pindex++){ if ((fabs((double)(pnt->x - cont->pts[pindex].x)) < selsize) && (fabs((double)(pnt->y - cont->pts[pindex].y)) < selsize)) { // get radius of point and maximum Z difference that will work rad = imodPointGetSize(obj, cont, pindex) / vi->xybin; delz = 0.5; if (rad > 1.) delz = sqrt(rad * rad - 1.) / scale.z; if (fabs((double)(cont->pts[pindex].z - cz)) <= delz) { temp_distance = imodPoint3DScaleDistance(&(cont->pts[pindex]), pnt, &scale); if (distance < 0. || distance > temp_distance){ distance = temp_distance; index->contour = i; index->point = pindex; } } } } } else { // Skip contour if not wild and Z does not match if (!twod && !(cont->flags & ICONT_WILD) && ( cz != (int)floor(cont->pts->z + 0.5))) continue; for(pindex = 0; pindex < cont->psize; pindex++){ if ((twod || cz == (int)floor(cont->pts[pindex].z + 0.5)) && (fabs((double)(pnt->x - cont->pts[pindex].x)) < selsize) && (fabs((double)(pnt->y - cont->pts[pindex].y)) < selsize)) { temp_distance = imod_distance( &(cont->pts[pindex].x), &(cont->pts[pindex].y), pnt); if (distance < 0. || distance > temp_distance){ distance = temp_distance; index->contour = i; index->point = pindex; } } } } } return(distance); }