[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [15573] branches/harmonic-skeleton/source/ blender/src/reeb.c: First draft of subgraph joining

Martin Poirier theeth at yahoo.com
Mon Jul 14 21:05:31 CEST 2008


Revision: 15573
          http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=15573
Author:   theeth
Date:     2008-07-14 21:05:25 +0200 (Mon, 14 Jul 2008)

Log Message:
-----------
First draft of subgraph joining

Modified Paths:
--------------
    branches/harmonic-skeleton/source/blender/src/reeb.c

Modified: branches/harmonic-skeleton/source/blender/src/reeb.c
===================================================================
--- branches/harmonic-skeleton/source/blender/src/reeb.c	2008-07-14 18:42:53 UTC (rev 15572)
+++ branches/harmonic-skeleton/source/blender/src/reeb.c	2008-07-14 19:05:25 UTC (rev 15573)
@@ -103,7 +103,9 @@
 void REEB_RadialSymmetry(BNode* root_node, RadialArc* ring, int count);
 void REEB_AxialSymmetry(BNode* root_node, BNode* node1, BNode* node2, struct BArc* barc1, BArc* barc2);
 
+void flipArcBuckets(ReebArc *arc);
 
+
 /***************************************** UTILS **********************************************/
 
 void REEB_freeArc(BArc *barc)
@@ -355,6 +357,16 @@
 	}
 }
 
+void flipArc(ReebArc *arc)
+{
+	ReebNode *tmp;
+	tmp = arc->head;
+	arc->head = arc->tail;
+	arc->tail = tmp;
+	
+	flipArcBuckets(arc);
+}
+
 #ifdef DEBUG_REEB_NODE
 void NodeDegreeDecrement(ReebGraph *rg, ReebNode *node)
 {
@@ -585,8 +597,8 @@
 void allocArcBuckets(ReebArc *arc)
 {
 	int i;
-	float start = ceil(((ReebNode*)arc->head)->weight);
-	arc->bcount = (int)(floor(((ReebNode*)arc->tail)->weight) - start) + 1;
+	float start = ceil(arc->head->weight);
+	arc->bcount = (int)(floor(arc->tail->weight) - start) + 1;
 	
 	if (arc->bcount > 0)
 	{
@@ -641,6 +653,86 @@
 	}
 }
 
+void reweightBuckets(ReebArc *arc)
+{
+	int i;
+	float start = ceil((arc->head)->weight);
+	
+	if (arc->bcount > 0)
+	{
+		for(i = 0; i < arc->bcount; i++)
+		{
+			arc->buckets[i].val = start + i;
+		}
+	}
+}
+
+static void interpolateBuckets(ReebArc *arc, float *start_p, float *end_p, int start_index, int end_index)
+{
+	int total;
+	int j;
+	
+	total = end_index - start_index + 2;
+	
+	for (j = start_index; j <= end_index; j++)
+	{
+		EmbedBucket *empty = arc->buckets + j;
+		empty->nv = 1;
+		VecLerpf(empty->p, start_p, end_p, (float)(j - start_index + 1) / total);
+	}
+}
+
+void fillArcEmptyBuckets(ReebArc *arc)
+{
+	float *start_p, *end_p;
+	int start_index, end_index;
+	int missing = 0;
+	int i;
+	
+	start_p = arc->head->p;
+	
+	for(i = 0; i < arc->bcount; i++)
+	{
+		EmbedBucket *bucket = arc->buckets + i;
+		
+		if (missing)
+		{
+			if (bucket->nv > 0)
+			{
+				missing = 0;
+				
+				end_p = bucket->p;
+				end_index = i - 1;
+				
+				interpolateBuckets(arc, start_p, end_p, start_index, end_index);
+			}
+		}
+		else
+		{
+			if (bucket->nv == 0)
+			{
+				missing = 1;
+				
+				if (i > 0)
+				{
+					start_p = arc->buckets[i - 1].p;
+				}
+				start_index = i;
+			}
+		}
+	}
+	
+	if (missing)
+	{
+		end_p = arc->tail->p;
+		end_index = arc->bcount - 1;
+		
+		interpolateBuckets(arc, start_p, end_p, start_index, end_index);
+	}
+}
+
+/**************************************** LENGTH CALCULATIONS ****************************************/
+
 void calculateArcLength(ReebArc *arc)
 {
 	ReebArcIterator iter;
@@ -966,7 +1058,121 @@
 {
 	BLI_sortlist(&rg->arcs, compareArcsWeight);
 }
+/******************************************* JOINING ***************************************************/
 
+void reweightArc(ReebArc *arc, ReebNode *start_node, float start_weight)
+{
+	float delta_weight = arc->tail->weight - arc->head->weight;
+	
+	if (arc->tail == start_node)
+	{
+		flipArc(arc);
+	}
+	
+	arc->head->weight = start_weight;
+	arc->tail->weight = start_weight + delta_weight;
+	
+	reweightBuckets(arc);
+	
+	/* recurse here */
+} 
+
+void reweightSubgraph(ReebGraph *rg, ReebNode *start_node, float start_weight)
+{
+	ReebArc *arc;
+	
+	arc = start_node->arcs[0];
+	
+	reweightArc(arc, start_node, start_weight);
+}
+
+int joinSubgraphsEnds(ReebGraph *rg, float threshold, int nb_subgraphs)
+{
+	int joined = 0;
+	int subgraph;
+	
+	for (subgraph = 1; subgraph <= nb_subgraphs; subgraph++)
+	{
+		ReebNode *start_node, *end_node;
+		
+		for (start_node = rg->nodes.first; start_node; start_node = start_node->next)
+		{
+			if (start_node->flag == subgraph && start_node->degree == 1)
+			{
+				for (end_node = rg->nodes.first; end_node; end_node = end_node->next)
+				{
+					if (end_node->flag != subgraph && end_node->degree == 1 && VecLenf(start_node->p, end_node->p) < threshold)
+					{
+						break;
+					}
+				}
+				
+				if (end_node)
+				{
+					ReebArc *start_arc, *end_arc;
+					int merging = 0;
+					
+					start_arc = start_node->arcs[0];
+					end_arc = end_node->arcs[0];
+					
+					if (start_arc->tail == start_node)
+					{
+						reweightSubgraph(rg, end_node, start_node->weight);
+						
+						end_arc->head = start_node;
+						
+						merging = 1;
+					}
+					else if (start_arc->head == start_node)
+					{
+						reweightSubgraph(rg, start_node, end_node->weight);
+
+						end_arc->tail = start_node;
+
+						merging = 1;
+					}
+					
+
+					if (merging)
+					{					
+						resizeArcBuckets(end_arc);
+						fillArcEmptyBuckets(end_arc);
+						
+						NodeDegreeIncrement(rg, start_node);
+						
+						BLI_removeNode((BGraph*)rg, (BNode*)end_node);
+					}
+					
+					joined = 1;
+					break;
+				}
+			}
+		}
+	}
+	
+	return joined;
+}
+
+int joinSubgraphs(ReebGraph *rg, float threshold)
+{
+	int nb_subgraphs;
+	int joined = 0;
+	
+	BLI_rebuildAdjacencyList((BGraph*)rg);
+	
+	nb_subgraphs = BLI_FlagSubgraphs((BGraph*)rg);
+	
+	joined |= joinSubgraphsEnds(rg, threshold, nb_subgraphs);
+	
+	if (joined)
+	{
+		removeNormalNodes(rg);
+		BLI_rebuildAdjacencyList((BGraph*)rg);
+	}
+	
+	return joined;
+}
+
 /****************************************** FILTERING **************************************************/
 
 float lengthArc(ReebArc *arc)
@@ -1055,12 +1261,7 @@
 				/* flip arcs that flipped, can happen on diamond shapes, mostly on null arcs */
 				if (arc->head->weight > arc->tail->weight)
 				{
-					ReebNode *tmp;
-					tmp = arc->head;
-					arc->head = arc->tail;
-					arc->tail = tmp;
-					
-					flipArcBuckets(arc);
+					flipArc(arc);
 				}
 				//newNode->degree++; // incrementing degree since we're adding an arc
 				NodeDegreeIncrement(rg, newNode);
@@ -2956,6 +3157,8 @@
 	/* Filtering might have created degree 2 nodes, so remove them */
 	removeNormalNodes(rg);
 	
+	joinSubgraphs(rg, 1.5);
+	
 	BLI_rebuildAdjacencyList((BGraph*)rg);
 	
 	/* calc length before copy, so we have same length on all levels */





More information about the Bf-blender-cvs mailing list