//understand the edge vertex computation from [email protected] //ASSUMPTION: eye is along z-axis //vo: volume vertex coords model-space coords //tx: texture vertex coords tex-space coords //axis: axis to slice along world-space coords void vRenderer::renderTexture3D(float sampleFrequency,GLdouble mv[16],float vo[8][3],float tx[8][3],float axis[3]) { float rv[8][3]; //the rotated volume (may include a scale) float maxval = -10; //(tmp) float minval = 10; int minvert = 0, maxvert = 0; GLdouble mvinv[16]; int i, j, k; inverseMatrix(mvinv, mv); //invert model view matrix for(i=0; i<8; ++i){ translateV3(rv[i], mv, vo[i]); //get the rotated vol coords //now get the max and min z in view space if(maxval < MAX(maxval, rv[i][2])){ maxval = MAX(maxval, rv[i][2]); maxvert = i; } if(minval > MIN(minval, rv[i][2])){ minval = MIN(minval, rv[i][2]); minvert = i; //determine the starting corner for slicing } } //find the slice plane point 'sp' (initial) and the slice plane normal 'sn' //sp is the slice starting point, simply the vertex farthest from the eye float sp[3] = {vo[minvert][0], vo[minvert][1], vo[minvert][2]}; // float sp[3] = {vo[maxvert][0], vo[maxvert][1], vo[maxvert][2]}; float vpn[3]; vpn[0] = axis[0]; vpn[1] = axis[1]; vpn[2] = axis[2]; //now calculate sn which is the normalized vpn in the model space //ie where the orginal slices are stored float sn[3]; translateV3(sn, mvinv, vpn); //move vpn to sn (model space); //now normalize this float normsn = (float)sqrt(sn[0]*sn[0] + sn[1]*sn[1] + sn[2]*sn[2]); //normalize sn[0]/=normsn; sn[1]/=normsn; sn[2]/=normsn; //now find the distance we need to slice (|max_vertex - min_vertex|) float maxd[3] = {0, 0, maxval}; //(tmp) only use z-coord (view space) float mind[3] = {0, 0, minval}; //(tmp) ditto (view space) float maxv[3], minv[3]; //(tmp) translateV3(maxv, mvinv, maxd); //translate back to model space translateV3(minv, mvinv, mind); //ditto maxv[0] -= minv[0]; //subtract maxv[1] -= minv[1]; maxv[2] -= minv[2]; //now take the norm of this vector... we have the distance to be sampled //this distance is in the world space float dist = (float)sqrt(maxv[0]*maxv[0] + maxv[1]*maxv[1] + maxv[2]*maxv[2]); #if defined(ADDCGGL) || defined(ADDARBGL) glColor4f(1.0f,1.0f,1.0f,0.01); #else glColor4f(1.0f,1.0f,1.0f,0.1); #endif GlErr("vRenderer","drawVA"); //distance between samples float sampleSpacing = 1.0 / (myVolume->maxDim* sampleFrequency); float del[3] = {sn[0]*sampleSpacing, sn[1]*sampleSpacing, sn[2]*sampleSpacing}; int samples = (int)((dist) / sampleSpacing);//(total distance to be sam //highly un-optimized!!!!!!!!! float poly[6][3]; // for edge intersections float tcoord[6][3]; // for texture intersections float tpoly[6][3]; // for transformed edge intersections int edges; // total number of edge intersections //the dep texture should be scaled glBindTexture(GL_TEXTURE_3D, myVolume->texName); //sp:slice plane point //sn:the slice dirn to cut thru the volume //the above 2 are in world coord space for(i = 0 ; i < samples; ++i){ //for each slice //increment the slice plane point by the slice distance // sp[0] -= del[0]; // sp[1] -= del[1]; // sp[2] -= del[2]; sp[0] += del[0]; sp[1] += del[1]; sp[2] += del[2]; edges = 0; //now check each edge of the volume for intersection with.. //the plane defined by sp & sn //front bottom edge edges += intersect(vo[0], vo[1], tx[0], tx[1], rv[0], rv[1], sp, sn, poly[edges], tcoord[edges], tpoly[edges]); //front left edge edges += intersect(vo[0], vo[2], tx[0], tx[2], rv[0], rv[2], sp, sn, poly[edges], tcoord[edges], tpoly[edges]); //front right edge edges += intersect(vo[1], vo[3], tx[1], tx[3], rv[1], rv[3], sp, sn, poly[edges], tcoord[edges], tpoly[edges]); //left bottom edge edges += intersect(vo[4], vo[0], tx[4], tx[0], rv[4], rv[0], sp, sn, poly[edges], tcoord[edges], tpoly[edges]); //right bottom edge edges += intersect(vo[1], vo[5], tx[1], tx[5], rv[1], rv[5], sp, sn, poly[edges], tcoord[edges], tpoly[edges]); //front top edge edges += intersect(vo[2], vo[3], tx[2], tx[3], rv[2], rv[3], sp, sn, poly[edges], tcoord[edges], tpoly[edges]); //back bottom edge edges += intersect(vo[4], vo[5], tx[4], tx[5], rv[4], rv[5], sp, sn, poly[edges], tcoord[edges], tpoly[edges]); //back left edge edges += intersect(vo[4], vo[6], tx[4], tx[6], rv[4], rv[6], sp, sn, poly[edges], tcoord[edges], tpoly[edges]); //back right edge edges += intersect(vo[5], vo[7], tx[5], tx[7], rv[5], rv[7], sp, sn, poly[edges], tcoord[edges], tpoly[edges]); //back top edge edges += intersect(vo[6], vo[7], tx[6], tx[7], rv[6], rv[7], sp, sn, poly[edges], tcoord[edges], tpoly[edges]); //left top edge edges += intersect(vo[2], vo[6], tx[2], tx[6], rv[2], rv[6], sp, sn, poly[edges], tcoord[edges], tpoly[edges]); //right top edge edges += intersect(vo[3], vo[7], tx[3], tx[7], rv[3], rv[7], sp, sn, poly[edges], tcoord[edges], tpoly[edges]); // B.M.E. Moret & H.D. Shapiro "P to NP" pp. 453 float dx, dy, tt ,theta, cen[2]; //tt= TempTheta cen[0] = cen[1] = 0.0; int next; //rather than swap 3 arrays, only one? int order[6] ={0,1,2,3,4,5}; // order[6] could be an extreemly inefficient way to do this for(j=0; j<edges; ++j){ //find the center of the points cen[0] += tpoly[j][0]; cen[1] += tpoly[j][1]; } //by averaging cen[0]/= edges; cen[1]/= edges; for(j=0; j<edges; ++j){ //for each vertex theta = -10; //find one with largest angle from center.. next = j; for (k= j; k<edges; ++k){ //... and check angle made between other edges dx = tpoly[order[k]][0] - cen[0]; dy = tpoly[order[k]][1] - cen[1]; if( (dx == 0) && (dy == 0)){ //same as center? next = k; cout << "what teh " << endl; break; //out of this for-loop } tt = dy/(ABS(dx) + ABS(dy)); //else compute theta [0-4] if( dx < 0.0 ) tt = (float)(2.0 - tt); //check quadrants 2&3 else if( dy < 0.0 ) tt = (float)(4.0 + tt); //quadrant 4 if( theta <= tt ){ //grab the max theta next = k; theta = tt; } } //end for(k) angle checking // i am using 'tt' as a temp // swap polygon vertex ( is this better than another branch?) // I am not sure wich is worse: swapping 3 vectors for every edge // or: using an array to index into another array??? hmmm.... // should have payed more attention in class int tmp = order[j]; order[j] = order[next]; order[next] = tmp; } //end for(j) edge /angle sort renderSlice(edges, tcoord, poly, order); //}//end else compute convex hull }// end for(i) each slice //now draw each slice view }
int32_t SearcherWorker::run() { const char *pureString = NULL; uint32_t pureSize = 0; char *resData = NULL; uint32_t resSize = 0; char *resDetailData = NULL; int32_t resDetailSize = 0; int32_t ret = 0; MemPool *memPool = NULL; int64_t *pNid = NULL; commdef::ClusterResult *pClusterResult = NULL; queryparser::QueryRewriterResult *pQRWResult = NULL; queryparser::QPResult *pQueryResult = NULL; SearchResult *pSearchResult = NULL; statistic::StatisticResult *pStatisticResult = NULL; sort_framework::SortResult *pSortResult = NULL; ResultSerializer resultSerial; FRAMEWORK::Context context; FILE *pOutput = NULL; //check session status FRAMEWORK::session_status_t status = _session.getStatus(); if (status == FRAMEWORK::ss_timeout) { handleTimeout(); return KS_SUCCESS; } //get query infomation FRAMEWORK::Query &query = _session.getQuery(); pureSize = query.getPureQuerySize(); pureString = query.getPureQueryData(); if (!pureString || pureSize == 0) { _session.setStatus(FRAMEWORK::ss_error); _session.response(); return KS_EFAILED; } //set LogInfo level _session._logInfo._eRole = FRAMEWORK::sr_simple; //get MemPool from factory memPool = _memFactory.make((uint64_t)(getOwner())); if (memPool == NULL) { TWARN("Make mem pool failed!"); return KS_EFAILED; } //create memory pool monitor MemMonitor memMonitor(memPool, _memLimit); memPool->setMonitor(&memMonitor); memMonitor.enableException(); //initialize context class context.setMemPool(memPool); //initialize format processor _formatProcessor.init(memPool); //Deal with search proccess do{ if(_session.isHttp()){ pQRWResult = NEW(memPool, queryparser::QueryRewriterResult)(); if (pQRWResult == NULL) { TWARN("SEARCHER: new Result no mem"); _session.setStatus(FRAMEWORK::ss_error); break; } } pQueryResult = NEW(memPool, queryparser::QPResult)(memPool); pSearchResult = NEW(memPool, SearchResult); pStatisticResult = NEW(memPool, statistic::StatisticResult); pSortResult = NEW(memPool, sort_framework::SortResult)(memPool); if(unlikely(!pQueryResult || !pSearchResult || !pStatisticResult || !pSortResult)) { TWARN("SEARCHER: new Result no mem"); _session.setStatus(FRAMEWORK::ss_error); break; } //add queryrewrite process if(_session.isHttp()){ ret = _qrewriter.doRewrite(&context, pureString, pureSize, pQRWResult); if (timeoutCheck && (_timeout > 0) && (_session.getLatencyTime() > _timeout)) { _session.setStatus(FRAMEWORK::ss_timeout); TWARN("SEARCHER: qrewriter.doRewrite function over time. query is %s", pureString); break; } if (unlikely(ret != KS_SUCCESS)) { _session.setStatus(FRAMEWORK::ss_error); TWARN("qrewriter.doRewrite function error. query is %s", pureString); break; } pureString = pQRWResult->getRewriteQuery(); } //end add ret = _qp.doParse(&context, pQueryResult, pureString); if (timeoutCheck && (_timeout > 0) && (_session.getLatencyTime() > _timeout)) { _session.setStatus(FRAMEWORK::ss_timeout); TWARN("SEARCHER: qp.doParse function over time. query is %s", pureString); break; } if (unlikely(ret != KS_SUCCESS)){ TWARN("SEARCHER: queryparser doParse function error. query is %s", pureString); _session.setStatus(FRAMEWORK::ss_error); break; } // cache命中情况下, mempool reset时调用CacheResult析构函数,释放命中的节点, // 否则sortResult对节点内存的引用失效,变为野指针(bug#118631) { ret = _is.doQuery(&context, pQueryResult, &_sort, pSearchResult); if (timeoutCheck && (_timeout > 0) && (_session.getLatencyTime() > _timeout)) { _session.setStatus(FRAMEWORK::ss_timeout); TWARN("SEARCHER: is.doQuery function over time. query is %s", pureString); break; } if (unlikely(ret != KS_SUCCESS)){ TWARN("SEARCHER: search doQuery function error. query is %s", pureString); _session.setStatus(FRAMEWORK::ss_error); break; } ret = _stat.doStatisticOnSearcher(&context, *(pQueryResult->getParam()), pSearchResult, pStatisticResult); if (timeoutCheck && (_timeout > 0) && (_session.getLatencyTime() > _timeout)) { _session.setStatus(FRAMEWORK::ss_timeout); TWARN("SEARCHER: doStatisticOnSearcher function over time. query is %s", pureString); break; } if (unlikely(ret != KS_SUCCESS)){ TWARN("SEARCHER: statistic doStatisticOnSearcher function error. query is %s", pureString); _session.setStatus(FRAMEWORK::ss_error); break; } ret = _sort.doProcess(context, *(pQueryResult->getParam()), *pSearchResult, *pSortResult); if (timeoutCheck && (_timeout > 0) && (_session.getLatencyTime() > _timeout)) { _session.setStatus(FRAMEWORK::ss_timeout); TWARN("SEARCHER: sort.doProcess function over time. query is %s", pureString); break; } if (unlikely(ret)) { TWARN("SEARCHER: sort doProcess function error. query is %s", pureString); _session.setStatus(FRAMEWORK::ss_error); break; } } pNid = NULL; //get docs return number int32_t num = pSortResult->getNidList(pNid); pClusterResult = NEW(memPool, commdef::ClusterResult)(); if ( NULL == pClusterResult ){ TWARN("SEARCHER: malloc from memPool failed "); _session.setStatus(FRAMEWORK::ss_error); break; } memset(pClusterResult, 0x0, sizeof(commdef::ClusterResult)); pClusterResult->_nDocsFound = pSortResult->getDocsFound();//pSearchResult->nDocFound; pClusterResult->_nEstimateDocsFound = pSortResult->getEstimateDocsFound();//pSearchResult->nEstimateDocFound; pClusterResult->_nDocsSearch = pSearchResult->nDocSearch; pClusterResult->_nDocsReturn = num; pClusterResult->_nDocsRestrict = pSearchResult->nEstimateDocFound;//pSearchResult->nDocFound; pClusterResult->_pStatisticResult = pStatisticResult; pClusterResult->_pSortResult = pSortResult; pClusterResult->_pQPResult = pQueryResult; pClusterResult->_ppDocuments = NULL; if(_session.isHttp() && _detail){ if(!pClusterResult->_nDocsReturn){ break; } char* pid = NULL; uint32_t pid_size = 0; ret = get_nid_str(pNid, num, memPool, &pid, &pid_size); if(KS_SUCCESS != ret){ _session.setStatus(FRAMEWORK::ss_error); break; } ret = getDetailInfo(pid, pid_size, pureString, &resDetailData, &resDetailSize); if(KS_SUCCESS != ret){ _session.setStatus(FRAMEWORK::ss_error); break; } if(timeoutCheck && _timeout>0 && _session.getLatencyTime()>_timeout){ _session.setStatus(FRAMEWORK::ss_timeout); break; } if (!translateV3(resDetailData, pClusterResult->_ppDocuments, (uint32_t &)pClusterResult->_nDocsReturn, memPool)) { _session.setStatus(FRAMEWORK::ss_error); break; } } } while (0); if(resDetailData)std::free(resDetailData); if(_session.isHttp() && _detail){ //fromat result get_outfmt_type(pureString, pureSize); result_container_t container; container.pClusterResult = pClusterResult; container.cost = _session.getLatencyTime(); if(_formatProcessor.frmt(_ofmt_type, container, &resData , &resSize) < 0){ TERR("FORMATRESULT: format_processor process error!"); _session.setStatus(FRAMEWORK::ss_error); } } else{ //serialize search result ret = resultSerial.serialClusterResult(pClusterResult, resData, resSize, "Z"); if (ret != KS_SUCCESS) { _session.setStatus(FRAMEWORK::ss_error); } } //recycle mem pool context.getMemPool()->reset(); _session.setResponseData(resData, resSize); _session.response(); return KS_SUCCESS; }