[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [17106] branches/etch-a-ton/source/blender /src/editarmature_sketch.c: Self intersection detection for gestures.

Martin Poirier theeth at yahoo.com
Sun Oct 19 05:33:53 CEST 2008


Revision: 17106
          http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=17106
Author:   theeth
Date:     2008-10-19 05:33:53 +0200 (Sun, 19 Oct 2008)

Log Message:
-----------
Self intersection detection for gestures.

Two new gestures:

- Merge: remove cuts on a stroke (gesture is a circle around the cuts to remove). The encircled points are changed to continuous points.
- Convert: convert selected strokes to bones (gesture is a stroke that loops back on itself once).

Note that all those different gestures are experimental. First, to get a good hang on recognition. Second, to try different things.

Modified Paths:
--------------
    branches/etch-a-ton/source/blender/src/editarmature_sketch.c

Modified: branches/etch-a-ton/source/blender/src/editarmature_sketch.c
===================================================================
--- branches/etch-a-ton/source/blender/src/editarmature_sketch.c	2008-10-19 00:35:00 UTC (rev 17105)
+++ branches/etch-a-ton/source/blender/src/editarmature_sketch.c	2008-10-19 03:33:53 UTC (rev 17106)
@@ -1370,6 +1370,56 @@
 }
 /******************* GESTURE *************************/
 
+
+/* returns the number of self intersections */
+int sk_getSelfIntersections(ListBase *list, SK_Stroke *gesture)
+{
+	int added = 0;
+	int s_i;
+
+	for (s_i = 0; s_i < gesture->nb_points - 1; s_i++)
+	{
+		float s_p1[3] = {0, 0, 0};
+		float s_p2[3] = {0, 0, 0};
+		int g_i;
+		
+		project_float(gesture->points[s_i].p, s_p1);
+		project_float(gesture->points[s_i + 1].p, s_p2);
+
+		/* start checking from second next, because two consecutive cannot intersect */
+		for (g_i = s_i + 2; g_i < gesture->nb_points - 1; g_i++)
+		{
+			float g_p1[3] = {0, 0, 0};
+			float g_p2[3] = {0, 0, 0};
+			float vi[3];
+			float lambda;
+			
+			project_float(gesture->points[g_i].p, g_p1);
+			project_float(gesture->points[g_i + 1].p, g_p2);
+			
+			if (LineIntersectLineStrict(s_p1, s_p2, g_p1, g_p2, vi, &lambda))
+			{
+				SK_Intersection *isect = MEM_callocN(sizeof(SK_Intersection), "Intersection");
+				
+				isect->start = s_i;
+				isect->end = g_i + 1;
+				isect->stroke = gesture;
+				
+				VecSubf(isect->p, gesture->points[s_i + 1].p, gesture->points[s_i].p);
+				VecMulf(isect->p, lambda);
+				VecAddf(isect->p, isect->p, gesture->points[s_i].p);
+				
+				BLI_addtail(list, isect);
+
+				added++;
+			}
+		}
+	}
+	
+	return added;
+}
+
+
 /* returns the maximum number of intersections per stroke */
 int sk_getIntersections(ListBase *list, SK_Sketch *sketch, SK_Stroke *gesture)
 {
@@ -1572,14 +1622,96 @@
 	}
 }
 
+int sk_detectMergeGesture(SK_Sketch *sketch, SK_Stroke *gesture, ListBase *list, SK_Stroke *segments)
+{
+	short start_val[2], end_val[2];
+	short dist;
+	
+	project_short_noclip(gesture->points[0].p, start_val);
+	project_short_noclip(gesture->points[gesture->nb_points - 1].p, end_val);
+	
+	dist = MAX2(ABS(start_val[0] - end_val[0]), ABS(start_val[1] - end_val[1]));
+	
+	/* if gesture is a circle */
+	if ( dist <= 20 )
+	{
+		SK_Intersection *isect;
+		
+		/* check if it circled around an exact point */
+		for (isect = list->first; isect; isect = isect->next)
+		{
+			/* only delete strokes that are crossed twice */
+			if (isect->next && isect->next->stroke == isect->stroke)
+			{
+				int start_index, end_index;
+				int i;
+				
+				start_index = MIN2(isect->end, isect->next->end);
+				end_index = MAX2(isect->start, isect->next->start);
+
+				for (i = start_index; i <= end_index; i++)
+				{
+					if (isect->stroke->points[i].type == PT_EXACT)
+					{
+						return 1; /* at least one exact point found, stop detect here */
+					}
+				}
+
+				/* skip next */				
+				isect = isect->next;
+			}
+		}
+			
+		return 0;
+	}
+	else
+	{
+		return 0;
+	}
+}
+
+void sk_applyMergeGesture(SK_Sketch *sketch, SK_Stroke *gesture, ListBase *list, SK_Stroke *segments)
+{
+	SK_Intersection *isect;
+	
+	/* check if it circled around an exact point */
+	for (isect = list->first; isect; isect = isect->next)
+	{
+		/* only delete strokes that are crossed twice */
+		if (isect->next && isect->next->stroke == isect->stroke)
+		{
+			int start_index, end_index;
+			int i;
+			
+			start_index = MIN2(isect->end, isect->next->end);
+			end_index = MAX2(isect->start, isect->next->start);
+
+			for (i = start_index; i <= end_index; i++)
+			{
+				/* if exact, switch to continuous */
+				if (isect->stroke->points[i].type == PT_EXACT)
+				{
+					isect->stroke->points[i].type = PT_CONTINUOUS;
+				}
+			}
+
+			/* skip next */				
+			isect = isect->next;
+		}
+	}
+}
+
 void sk_applyGesture(SK_Sketch *sketch)
 {
 	ListBase intersections;
+	ListBase self_intersections;
 	SK_Stroke *segments = sk_createStroke();
-	int nb_intersections, nb_segments;
+	int nb_self_intersections, nb_intersections, nb_segments;
 	
 	intersections.first = intersections.last = NULL;
+	self_intersections.first = self_intersections.last = NULL;
 	
+	nb_self_intersections = sk_getSelfIntersections(&self_intersections, sketch->gesture);
 	nb_intersections = sk_getIntersections(&intersections, sketch, sketch->gesture);
 	nb_segments = sk_getSegments(segments, sketch->gesture);
 	
@@ -1596,9 +1728,18 @@
 	{
 		sk_applyDeleteGesture(sketch, sketch->gesture, &intersections, segments);
 	}
+	else if (nb_segments > 2 && nb_intersections == 2 && sk_detectMergeGesture(sketch, sketch->gesture, &intersections, segments))
+	{
+		sk_applyMergeGesture(sketch, sketch->gesture, &intersections, segments);
+	}
+	else if (nb_segments > 2 && nb_self_intersections == 1)
+	{
+		sk_convert(sketch);
+	}
 	
 	sk_freeStroke(segments);
 	BLI_freelistN(&intersections);
+	BLI_freelistN(&self_intersections);
 }
 
 /********************************************/





More information about the Bf-blender-cvs mailing list