real SVertex::GetIsophoteDistance(real isovalue, int maxDistance) const { if (_sourceVertex == NULL && _sourceEdge == NULL) return -1; // not handling the case of intersection SVertices yet if (!(getNature() & Nature::SILHOUETTE)) // only handle silhouette curves return -1; Vec3r startPoint = _Point3D; set<pair<WFace*,int> > possibleStartEdges; real currentNdotV; // if (!(getNature() & Nature::SURFACE_INTERSECTION)) // printf("Isophote search Nature: %d\n", getNature()); if (_sourceVertex != NULL) { currentNdotV = _sourceVertex->GetSurfaceNdotV(); // printf("Starting at vertex with n dot v = %f\n", currentNdotV); for(vector<WEdge*>::iterator it = _sourceVertex->GetEdges().begin(); it != _sourceVertex->GetEdges().end(); ++it) { WFace * aface = (*it)->GetaFace(); WFace * bface = (*it)->GetbFace(); if (aface != NULL) possibleStartEdges.insert( pair<WFace*,int>(aface, (aface->GetIndex(_sourceVertex)+1)%3)); if (bface != NULL) possibleStartEdges.insert(pair<WFace*,int>(bface, (bface->GetIndex(_sourceVertex)+1)%3)); } } else { currentNdotV = ComputeSurfaceNdotV(_sourceEdge, startPoint); WFace * faces[2] = { _sourceEdge->GetaFace(), _sourceEdge->GetbFace() }; for(int i=0;i<2;i++) if (faces[i] != NULL) { int v; for(v=0;v<3;v++) if (faces[i]->GetOEdge(v)->GetOwner() == _sourceEdge) break; assert(v<3); possibleStartEdges.insert(pair<WFace*,int>(faces[i], (v+1)%3)); possibleStartEdges.insert(pair<WFace*,int>(faces[i], (v+2)%3)); } } if (currentNdotV > isovalue) return 0; if (currentNdotV < -0.001) return 0; Vec3r currentPoint; WEdge * currentEdge = NULL; WFace * currentFace = NULL; Vec3r lastPoint = startPoint; real lastNdotV = currentNdotV; for(set<pair<WFace*,int> >::iterator it = possibleStartEdges.begin(); it != possibleStartEdges.end(); ++it) { WFace * face = (*it).first; int e = (*it).second; if (AdvanceToEdge( face, startPoint, e, currentPoint)) { currentNdotV = ComputeSurfaceNdotV(face->GetOEdge(e)->GetOwner(), currentPoint); // printf("\tlastNdotV = %f, currentNdotV = %f\n", lastNdotV, currentNdotV); if (currentNdotV < lastNdotV) continue; currentEdge = face->GetOEdge(e)->GetOwner(); currentFace = face->GetBordingFace(e); assert(GeomUtils::distPointSegment<Vec3r>( currentPoint, currentEdge->GetaVertex()->GetVertex(), currentEdge->GetbVertex()->GetVertex()) < 0.01); break; } } if (currentEdge == NULL) return -1; // march over the surface int numSteps = 0; while (currentNdotV < isovalue && currentNdotV > -0.001 && numSteps < 100 && currentFace != NULL && ImageSpaceDistance(startPoint, currentPoint) < maxDistance) { numSteps ++; lastPoint = currentPoint; lastNdotV = currentNdotV; // printf("advancing, current NdotV = %f\n", currentNdotV); bool result = false; int e; Vec3r nextPoint; for(e=0;e<3;e++) { if (currentFace->GetOEdge(e)->GetOwner() == currentEdge) continue; result = AdvanceToEdge(currentFace, currentPoint, e, nextPoint); // printf("\t advance result = %s\n", result ? "true" : "false"); if (result) break; } assert(result); currentPoint = nextPoint; currentEdge = currentFace->GetOEdge(e)->GetOwner(); currentNdotV = ComputeSurfaceNdotV(currentEdge, currentPoint); currentFace = currentFace->GetBordingFace(e); } Vec3r endpoint; if (currentNdotV > isovalue) { real t = (isovalue - lastNdotV)/(currentNdotV - lastNdotV); endpoint = (1-t) * lastPoint + t * currentPoint; } else if (currentNdotV < -0.001) { real t = -lastNdotV/(currentNdotV - lastNdotV); // endpoint is the zero-crossing endpoint = (1-t)*lastPoint + t * currentPoint; } else endpoint = currentPoint; ViewMap * vm = ViewMap::getInstance(); vm->addDebugPoint(DebugPoint::ISOPHOTE, endpoint, startPoint); real dist = ImageSpaceDistance(startPoint, endpoint); // printf("\t result: dist = %f, lastNdotV = %f, currentNdotV = %f, numSteps = %d, currentFace = %08X\n", dist, lastNdotV, currentNdotV, numSteps, currentFace); return dist; }