Ejemplo n.º 1
0
void FEdgeXDetector::ProcessCreaseEdge(WXEdge *iEdge)
{
    // CREASE ?
    //---------
    if(iEdge->nature() & Nature::BORDER)
        return;
    WXFace * fA = (WXFace *)iEdge->GetaOEdge()->GetaFace();
    WXFace * fB = (WXFace *)iEdge->GetaOEdge()->GetbFace();

    WVertex * aVertex = iEdge->GetaVertex();
    if((fA->GetVertexNormal(aVertex) * fB->GetVertexNormal(aVertex)) <= 0.7) // angle of 140 degrees
        iEdge->AddNature(Nature::CREASE);
}
Ejemplo n.º 2
0
void FEdgeXDetector::ProcessSilhouetteEdge(WXEdge *iEdge, bool meshSilhouettes)
{
    if(iEdge->nature() & Nature::BORDER)
        return;
    // SILHOUETTE ?
    //-------------
    WXFace * fA = (WXFace *)iEdge->GetaOEdge()->GetaFace();
    WXFace * fB = (WXFace *)iEdge->GetaOEdge()->GetbFace();

    if((fA->front(_useConsistency))^(fB->front(_useConsistency))){ // fA->visible XOR fB->visible (true if one is 0 and the other is 1)
        // Freestyle is using a hack here to determine if these faces are "smooth" or "sharp."  Specifically,
        // if the normals disagree at a vertex, then it must be "sharp."  This hack broke with the bunny triangle mesh that had planar
        // faces in one version.  New hack includes more tests...

        if(!meshSilhouettes &&
                fA->GetVertexNormal(iEdge->GetaVertex()) == fB->GetVertexNormal(iEdge->GetaVertex()) &&
                fA->GetVertexNormal(iEdge->GetbVertex()) == fB->GetVertexNormal(iEdge->GetbVertex()) &&
                fA->GetVertexNormal(iEdge->GetaVertex()) != fA->GetVertexNormal(iEdge->GetbVertex()))
            // Aaron: added second and third conditions
        {
            //	Vec3r Aa = fA->GetVertexNormal(iEdge->GetaVertex());
            //	Vec3r Ba = fB->GetVertexNormal(iEdge->GetaVertex());
            //	Vec3r Ab = fA->GetVertexNormal(iEdge->GetbVertex());
            //	Vec3r Bb = fB->GetVertexNormal(iEdge->GetbVertex());

            //	printf("Non-silhouette detected\n");
            //	printf("%f %f %f,   %f %f %f\n", Aa[0], Aa[1], Aa[2], Ba[0], Ba[1], Ba[2]);
            //	printf("%f %f %f,   %f %f %f\n", Ab[0], Ab[1], Ab[2], Bb[0], Bb[1], Bb[2]);
            return;
        }

        iEdge->AddNature(Nature::SILHOUETTE);
        if(fB->front(_useConsistency))
            iEdge->SetOrder(1);
        else
            iEdge->SetOrder(-1);
    }
}
Ejemplo n.º 3
0
void FEdgeXDetector::ProcessSilhouetteEdge(WXEdge *iEdge)
{
	if (iEdge->nature() & Nature::BORDER)
		return;
	// SILHOUETTE ?
	//-------------
	WXFace *fA = (WXFace *)iEdge->GetaOEdge()->GetaFace();
	WXFace *fB = (WXFace *)iEdge->GetaOEdge()->GetbFace();

	if ((fA->front()) ^ (fB->front())) { // fA->visible XOR fB->visible (true if one is 0 and the other is 1)
		// The only edges we want to set as silhouette edges in this way are the ones with 2 different normals
		// for 1 vertex for these two faces
		//--------------------
		// In reality we only test the normals for 1 of the 2 vertices.
		if (fA->GetVertexNormal(iEdge->GetaVertex()) == fB->GetVertexNormal(iEdge->GetaVertex()))
			return;
		iEdge->AddNature(Nature::SILHOUETTE);
		if (fB->front())
			iEdge->setOrder(1);
		else
			iEdge->setOrder(-1);
	}
}
Ejemplo n.º 4
0
void FEdgeXDetector::postProcessSuggestiveContourFace(WXFace *iFace) {

    // Compute the derivative of the radial curvature in the radial direction,
    // at the two extremities of the smooth edge.
    // If the derivative is smaller than a given threshold _kr_derivative_epsilon,
    // discard the edge.

    // Find the suggestive contour layer of the face (zero or one edge).
    vector<WXFaceLayer*> sc_layers;
    iFace->retrieveSmoothEdgesLayers(Nature::SUGGESTIVE_CONTOUR, sc_layers);
    if(sc_layers.empty())
        return;

    WXFaceLayer *sc_layer;
    sc_layer = sc_layers[0];

    // Compute the derivative value at each vertex of the face, and add it in a vector.
    vector<real> kr_derivatives;

    unsigned vertices_nb = iFace->numberOfVertices();
    WXVertex *v, *opposite_vertex_a, *opposite_vertex_b;
    WXFace *wxf;
    WOEdge *opposite_edge;
    Vec3r opposite_edge_vec, normal_vec, radial_normal_vec, er_vec, v_vec, inter, inter1, inter2, tmp_vec;
    GeomUtils::intersection_test res;
    real kr(0), kr1(0), kr2(0), t;

    for (unsigned i = 0; i < vertices_nb; ++i) {
        v = (WXVertex*)(iFace->GetVertex(i));

        // v is a singular vertex, skip it.
        if (v->isBoundary()) {
            kr_derivatives.push_back(0);
            continue;
        }

        v_vec = v->GetVertex();
        er_vec = v->curvatures()->er;

        // For each vertex, iterate on its adjacent faces.
        for (WVertex::face_iterator fit = v->faces_begin(), fitend = v->faces_end();
             fit != fitend;
             ++fit) {
            wxf = dynamic_cast<WXFace*>(*fit);
            if(!(wxf->getOppositeEdge(v, opposite_edge)))
                continue;

            opposite_vertex_a = (WXVertex*)opposite_edge->GetaVertex();
            opposite_vertex_b = (WXVertex*)opposite_edge->GetbVertex();
            opposite_edge_vec = opposite_vertex_b->GetVertex() - opposite_vertex_a->GetVertex();
            normal_vec = wxf->GetVertexNormal(v); // FIXME: what about e1 ^ e2 ?
            radial_normal_vec = er_vec ^ normal_vec;

            // Test wether the radial plan intersects with the edge at the opposite of v.
            res = GeomUtils::intersectRayPlane(opposite_vertex_a->GetVertex(), opposite_edge_vec,
                                               radial_normal_vec, -(v_vec * radial_normal_vec),
                                               t,
                                               1.e-06);

            // If there is an intersection, compute the value of the derivative ath that point.
            if ((res == GeomUtils::DO_INTERSECT) && (t >= 0) && (t <= 1)) {
                kr = t * opposite_vertex_a->curvatures()->Kr + (1 - t) * opposite_vertex_b->curvatures()->Kr;
                inter = opposite_vertex_a->GetVertex() + t * opposite_edge_vec;
                tmp_vec = inter - v->GetVertex();
                // Is it kr1 or kr2?
                if (tmp_vec * er_vec > 0) {
                    kr2 = kr;
                    inter2 = inter;
                } else {
                    kr1 = kr;
                    inter1 = inter;
                }
            }
        }

        // Now we have kr1 and kr2 along the radial direction, for one vertex of iFace.
        // We have to compute the derivative of kr for that vertex, equal to:
        // (kr2 - kr1) / dist(inter1, inter2).
        // Then we add it to the vector of derivatives.
        v->curvatures()->dKr = (kr2 - kr1) / (inter2 - inter1).norm();
        kr_derivatives.push_back(v->curvatures()->dKr);
    }

    // At that point, we have the derivatives for each vertex of iFace.
    // All we have to do now is to use linear interpolation to compute the values at
    // the extremities of the smooth edge.
    WXSmoothEdge *sc_edge = sc_layer->getSmoothEdge();
    WOEdge *sc_oedge = sc_edge->woea();
    t = sc_edge->ta();
    if (t * kr_derivatives[iFace->GetIndex(sc_oedge->GetaVertex())] +
            (1 - t) * kr_derivatives[iFace->GetIndex(sc_oedge->GetbVertex())] < _kr_derivative_epsilon) {
        sc_layer->removeSmoothEdge();
        return;
    }
    sc_oedge = sc_edge->woeb();
    t = sc_edge->tb();
    if (t * kr_derivatives[iFace->GetIndex(sc_oedge->GetaVertex())] +
            (1 - t) * kr_derivatives[iFace->GetIndex(sc_oedge->GetbVertex())] < _kr_derivative_epsilon)
        sc_layer->removeSmoothEdge();
}
Ejemplo n.º 5
0
void FEdgeXDetector::processShapes(WingedEdge& we) {
    bool progressBarDisplay = false;
    Vec3r Min, Max;
    vector<WShape*> wshapes = we.getWShapes();
    WXShape * wxs;

    if(_pProgressBar != NULL) {
        _pProgressBar->reset();
        _pProgressBar->setLabelText("Detecting feature lines");
        _pProgressBar->setTotalSteps(wshapes.size() * 3);
        _pProgressBar->setProgress(0);
        progressBarDisplay = true;
    }

    for(vector<WShape*>::const_iterator it = wshapes.begin();
        it != wshapes.end();
        it++){
        wxs = dynamic_cast<WXShape*>(*it);
        //printf("\n\nmesh silhouette = %d\n\n",wxs->MeshSilhouettes());
        wxs->bbox(Min, Max);
        _bbox_diagonal = (Max-Min).norm();
        if(_changes){
            vector<WFace*>& wfaces = wxs->GetFaceList();
            for(vector<WFace*>::iterator wf=wfaces.begin(), wfend=wfaces.end();
                wf!=wfend;
                ++wf){
                WXFace* wxf = dynamic_cast<WXFace*>(*wf);
                wxf->Clear();
            }
            _computeViewIndependant = true;
        } else if (!(wxs)->getComputeViewIndependantFlag()) {
            wxs->Reset();
            _computeViewIndependant = false;
        } else {
            _computeViewIndependant = true;
        }
        preProcessShape(wxs);
        if (progressBarDisplay)
            _pProgressBar->setProgress(_pProgressBar->getProgress() + 1);
        processBorderShape(wxs);

        // skipping crease detection:
        //    processCreaseShape(wxs);

        if(_computeRidgesAndValleys)
            processRidgesAndValleysShape(wxs);
        if(_computeSuggestiveContours)
            processSuggestiveContourShape(wxs);
        processSilhouetteShape(wxs);
        if (progressBarDisplay)
            _pProgressBar->setProgress(_pProgressBar->getProgress() + 1);

        // build smooth edges:
        buildSmoothEdges(wxs);

        // Post processing for suggestive contours
        if(_computeSuggestiveContours)
            postProcessSuggestiveContourShape(wxs);
        if (progressBarDisplay)
            _pProgressBar->setProgress(_pProgressBar->getProgress() + 1);

        wxs->setComputeViewIndependantFlag(false);
        _computeViewIndependant = false;
        _changes = false;

        // reset user data
        (*it)->ResetUserData();
    }
}
Ejemplo n.º 6
0
void FEdgeXDetector::ProcessRidgeFace(WXFace *iFace)
{
	// RIDGE LAYER
	// Compute the RidgeFunction, that is the derivative of the ppal curvature along e1 at each vertex of the face
	WVertex *v;
	Vec3r v1v2;
	real t;
	vector<WXFaceLayer*> SmoothLayers;
	WXFaceLayer *faceLayer;
	Face_Curvature_Info *layer_info;
	real K1_a(0), K1_b(0);
	Vec3r Inter_a, Inter_b;

	// find the ridge layer of the face
	iFace->retrieveSmoothLayers(Nature::RIDGE, SmoothLayers);
	if ( SmoothLayers.size()!=1 )
		return;
	faceLayer = SmoothLayers[0];
	// retrieve the curvature info of this layer
	layer_info = (Face_Curvature_Info *)faceLayer->userdata;

	int numVertices = iFace->numberOfVertices();
	for (int i = 0; i < numVertices; i++) {
		v = iFace->GetVertex(i);
		// vec_curvature_info[i] contains the curvature info of this vertex
		Vec3r e2 = layer_info->vec_curvature_info[i]->K2*layer_info->vec_curvature_info[i]->e2;
		Vec3r e1 = layer_info->vec_curvature_info[i]->K1*layer_info->vec_curvature_info[i]->e1;
		e2.normalize();

		WVertex::face_iterator fit = v->faces_begin();
		WVertex::face_iterator fitend = v->faces_end();
		for (; fit != fitend; ++fit) {
			WXFace *wxf = dynamic_cast<WXFace*>(*fit);
			WOEdge *oppositeEdge;
			if (!(wxf->getOppositeEdge(v, oppositeEdge)))
				continue;
			v1v2 = oppositeEdge->GetbVertex()->GetVertex() - oppositeEdge->GetaVertex()->GetVertex();
			GeomUtils::intersection_test res;
			res = GeomUtils::intersectRayPlane(oppositeEdge->GetaVertex()->GetVertex(), v1v2, e2, -(v->GetVertex()*e2),
			                                   t, 1.0e-06);
			if ((res == GeomUtils::DO_INTERSECT) && (t >= 0.0) && (t <= 1.0)) {
				vector<WXFaceLayer*> second_ridge_layer;
				wxf->retrieveSmoothLayers(Nature::RIDGE, second_ridge_layer);
				if (second_ridge_layer.size() != 1)
					continue;
				Face_Curvature_Info *second_layer_info = (Face_Curvature_Info*)second_ridge_layer[0]->userdata;

				unsigned index1 = wxf->GetIndex(oppositeEdge->GetaVertex());
				unsigned index2 = wxf->GetIndex(oppositeEdge->GetbVertex());
				real K1_1 = second_layer_info->vec_curvature_info[index1]->K1;
				real K1_2 = second_layer_info->vec_curvature_info[index2]->K1;
				real K1 = (1.0 - t) * K1_1 + t * K1_2;
				Vec3r inter((1.0 - t) * oppositeEdge->GetaVertex()->GetVertex() +
				            t * oppositeEdge->GetbVertex()->GetVertex());
				Vec3r vtmp(inter - v->GetVertex());
				// is it K1_a or K1_b ?
				if (vtmp * e1 > 0) {
					K1_b = K1;
					Inter_b = inter;
				}
				else {
					K1_a = K1;
					Inter_a = inter;
				}
			}
		}
		// Once we have K1 along the ppal direction compute the derivative : K1b - K1a put it in DotP
		//real d = fabs(K1_b) - fabs(K1_a);
		real d = 0;
		real threshold = _meanK1 + (_maxK1 - _meanK1) / 7.0;
		//real threshold = _meanK1;
		//if ((fabs(K1_b) > threshold) || ((fabs(K1_a) > threshold)))
		d = (K1_b) - (K1_a) / (Inter_b - Inter_a).norm();
		faceLayer->PushDotP(d);
		//faceLayer->PushDotP(layer_info->vec_curvature_info[i]->K1);
	}

	// Make the values relevant by checking whether all principal directions have the "same" direction:
	Vec3r e0((layer_info->vec_curvature_info[0]->K1 * layer_info->vec_curvature_info[0]->e1));
	e0.normalize();
	Vec3r e1((layer_info->vec_curvature_info[1]->K1 * layer_info->vec_curvature_info[1]->e1));
	e1.normalize();
	Vec3r e2((layer_info->vec_curvature_info[2]->K1 * layer_info->vec_curvature_info[2]->e1));
	e2.normalize();
	if (e0 * e1 < 0)
		// invert dotP[1]
		faceLayer->ReplaceDotP(1, -faceLayer->dotP(1));
	if (e0 * e2 < 0)
		// invert dotP[2]
		faceLayer->ReplaceDotP(2, -faceLayer->dotP(2));

#if 0 // remove the weakest values;
	real minDiff = (_maxK1 - _minK1) / 10.0;
	real minDiff = _meanK1;
	if ((faceLayer->dotP(0) < minDiff) && (faceLayer->dotP(1) < minDiff) && (faceLayer->dotP(2) < minDiff)) {
		faceLayer->ReplaceDotP(0, 0);
		faceLayer->ReplaceDotP(1, 0);
		faceLayer->ReplaceDotP(2, 0);
	}
#endif
}
void ViewEdgeXBuilder::BuildViewEdges(WXShape *iWShape, ViewShape *oVShape, vector<ViewEdge*>& ioVEdges,
                                      vector<ViewVertex*>& ioVVertices, vector<FEdge*>& ioFEdges,
                                      vector<SVertex*>& ioSVertices)
{
	// Reinit structures
	Init(oVShape);

	/* ViewEdge *vedge; */ /* UNUSED */
	// Let us build the smooth stuff
	//----------------------------------------
	// We parse all faces to find the ones that contain smooth edges
	vector<WFace*>& wfaces = iWShape->GetFaceList();
	vector<WFace*>::iterator wf, wfend;
	WXFace *wxf;
	for (wf = wfaces.begin(), wfend = wfaces.end(); wf != wfend; wf++) {
		wxf = dynamic_cast<WXFace*>(*wf);
		if (false == ((wxf))->hasSmoothEdges()) // does it contain at least one smooth edge ?
			continue;
		// parse all smooth layers:
		vector<WXFaceLayer*>& smoothLayers = wxf->getSmoothLayers();
		for (vector<WXFaceLayer*>::iterator sl = smoothLayers.begin(), slend = smoothLayers.end(); sl != slend; ++sl) {
			if (!(*sl)->hasSmoothEdge())
				continue;
			if (stopSmoothViewEdge((*sl))) // has it been parsed already ?
				continue;
			// here we know that we're dealing with a face layer that has not been processed yet and that contains
			// a smooth edge.
			/* vedge =*/ /* UNUSED */ BuildSmoothViewEdge(OWXFaceLayer(*sl, true));
		}
	}

	// Now let's build sharp view edges:
	//----------------------------------
	// Reset all userdata for WXEdge structure
	//----------------------------------------
	//iWShape->ResetUserData();

	WXEdge *wxe;
	vector<WEdge*>& wedges = iWShape->getEdgeList();
	//------------------------------
	for (vector<WEdge*>::iterator we = wedges.begin(), weend = wedges.end(); we != weend; we++) {
		wxe = dynamic_cast<WXEdge*>(*we);
		if (Nature::NO_FEATURE == wxe->nature())
			continue;

		if (!stopSharpViewEdge(wxe)) {
			bool b = true;
			if (wxe->order() == -1)
				b = false;
			BuildSharpViewEdge(OWXEdge(wxe, b));
		}
	}

	// Reset all userdata for WXEdge structure
	//----------------------------------------
	iWShape->ResetUserData();

	// Add all these new edges to the scene's feature edges list:
	//-----------------------------------------------------------
	vector<FEdge*>& newedges = _pCurrentSShape->getEdgeList();
	vector<SVertex*>& newVertices = _pCurrentSShape->getVertexList();
	vector<ViewVertex*>& newVVertices = _pCurrentVShape->vertices();
	vector<ViewEdge*>& newVEdges = _pCurrentVShape->edges();

	// inserts in ioFEdges, at its end, all the edges of newedges
	ioFEdges.insert(ioFEdges.end(), newedges.begin(), newedges.end());
	ioSVertices.insert(ioSVertices.end(), newVertices.begin(), newVertices.end());
	ioVVertices.insert(ioVVertices.end(), newVVertices.begin(), newVVertices.end());
	ioVEdges.insert(ioVEdges.end(), newVEdges.begin(), newVEdges.end());
}
OWXFaceLayer ViewEdgeXBuilder::FindPreviousFaceLayer(const OWXFaceLayer& iFaceLayer)
{
	WXFace *previousFace = NULL;
	WOEdge *woebegin;
	real tend;
	if (iFaceLayer.order) {
		woebegin = iFaceLayer.fl->getSmoothEdge()->woea();
		tend = iFaceLayer.fl->getSmoothEdge()->ta();
	}
	else {
		woebegin = iFaceLayer.fl->getSmoothEdge()->woeb();
		tend = iFaceLayer.fl->getSmoothEdge()->tb();
	}

	// special case of EDGE_VERTEX config:
	if ((tend == 0.0) || (tend == 1.0)) {
		WVertex *previousVertex;
		if (tend == 0.0)
			previousVertex = woebegin->GetaVertex();
		else
			previousVertex = woebegin->GetbVertex();
		if (previousVertex->isBoundary()) // if it's a non-manifold vertex -> ignore
			return OWXFaceLayer(NULL, true);
		bool found = false;
		WVertex::face_iterator f = previousVertex->faces_begin();
		WVertex::face_iterator fend = previousVertex->faces_end();
		for (; (!found) && (f != fend); ++f) {
			previousFace = dynamic_cast<WXFace*>(*f);
			if ((0 != previousFace) && (previousFace != iFaceLayer.fl->getFace())) {
				vector<WXFaceLayer*> sameNatureLayers;
				previousFace->retrieveSmoothEdgesLayers(iFaceLayer.fl->nature(), sameNatureLayers);
				// don't know... Maybe should test whether this face has also a vertex_edge configuration
				if (sameNatureLayers.size() == 1) {
					WXFaceLayer *winner = sameNatureLayers[0];
					// check face mark continuity
					if (winner->getFace()->GetMark() != iFaceLayer.fl->getFace()->GetMark())
						return OWXFaceLayer(NULL, true);
					if (woebegin == winner->getSmoothEdge()->woeb()->twin())
						return OWXFaceLayer(winner, true);
					else
						return OWXFaceLayer(winner, false);
				}
			}
		}
	}
	else {
		previousFace = dynamic_cast<WXFace*>(iFaceLayer.fl->getFace()->GetBordingFace(woebegin));
		if (0 == previousFace)
			return OWXFaceLayer(NULL, true);
		// if the next face layer has either no smooth edge or no smooth edge of same nature, no next face
		if (!previousFace->hasSmoothEdges())
			return OWXFaceLayer(NULL, true);
		vector<WXFaceLayer*> sameNatureLayers;
		previousFace->retrieveSmoothEdgesLayers(iFaceLayer.fl->nature(), sameNatureLayers);
		// don't know how to deal with several edges of same nature on a single face
		if ((sameNatureLayers.empty()) || (sameNatureLayers.size() != 1)) {
			return OWXFaceLayer(NULL, true);
		}
		else {
			WXFaceLayer *winner = sameNatureLayers[0];
			// check face mark continuity
			if (winner->getFace()->GetMark() != iFaceLayer.fl->getFace()->GetMark())
				return OWXFaceLayer(NULL, true);
			if (woebegin == winner->getSmoothEdge()->woeb()->twin())
				return OWXFaceLayer(winner, true);
			else
				return OWXFaceLayer(winner, false);
		}
	}
	return OWXFaceLayer(NULL, true);
}