Commits

Janto Dreijer  committed 151783a

optimise line estimate error

  • Participants
  • Parent commits 10abcd8

Comments (0)

Files changed (1)

File linetools.py

 	import psyco
 	psyco.full()
 except ImportError:
-	pass
+	class Psyco(object):
+		def proxy(self, e):
+			return e
+	psyco = Psyco()
 
 __all__ += ["Point"]
 class Point(object):
 	def __add__(self, other):
 		return Point(self.x+other.x, self.y+other.y, self.time+other.time)
 
+	def __mul__(self, k):
+		"""
+			>>> Point(1,2,100)*3
+			<Point(3,6)@100.0s>
+		"""
+		return Point(self.x*k, self.y*k, self.time)
+
 	def __radd__(self, other):
 		if other == 0:
 			return self
 		return complex(self.x, self.y)
 
 	def __str__(self):
-		return "<Point(%s,%s)@%ss>" % (self.x, self.y, self.time)
+		return "<Point(%s,%s)@%ss>" % (self.x, self.y, round(self.time, 1))
 
 	def __repr__(self):
 		return str(self)
 
 @export
 def points_features(points):
+	#~ times = [clock()]
 	features = []
 	## deviation from line, line-ness
 	other_points = points[:]
 	stop = other_points.pop(-1)
 	error_from_line = 0
 	len_of_estimated_line = start.distance_to(stop) or 1
+	v = (stop - start)
 	for point in other_points:
 		u = start.distance_to(point) / len_of_estimated_line
-		x = start.x + u*(stop - start).x
-		y = start.y + u*(stop - start).y
-		error_from_line += Point(x, y).distance_to(point)
+		p = start + v*u
+		error_from_line += p.distance_to(point)
 	if other_points:
 		error_from_line /= len(other_points)
+	#~ times.append(clock())
 	features.append(min(error_from_line / len_of_estimated_line, 2)) # normalize + upper bound
 	## segment
+	#~ times.append(clock())
 	features.append(min(Corner(points).error / len_of_estimated_line, 0.5)) # normalize + upper bound
 	## deviation from arc, arc-ness
+	#~ times.append(clock())
 	arc = points_to_arc(points)
+	#~ times.append(clock())
 	#~ features.append(arc.error)
 	## mean distance from primitive midpoint, circle-ness
 	features.append(mean(abs(arc.z.distance_to(p)-arc.r) for p in points) / arc.r) # normalize against radius
 	#~ features.append(curvature_len / len_of_estimated_line)
 	#~ print curvature_len / len_of_estimated_line,
 	#~ variations.append(curvature_len / len_of_estimated_line)
+	#~ times.append(clock())
+	#~ print [a-b for a, b in zip(times[1:], times[:-1])]
+	#~ print [t-times[0] for t in times]
 	return features
 
 def quick_hist(seq):
 		if not len_of_estimated_line: # zero length
 			bad_quality = True
 		else:
+			v = (stop - start)
 			for point in points:
 				u = start.distance_to(point) / start.distance_to(stop)
-				x = start.x + u*(stop - start).x
-				y = start.y + u*(stop - start).y
-				error += Point(x, y).distance_to(point)
+				p = start + v*u
+				error += p.distance_to(point)
 			if points:
 				error /= len(points)
 			if error > 10:
 	def snap_points(self):
 		"""
 			>>> Line(points=[Point(0,0,0), Point(5,5,0)]).snap_points()
-			[<Point(0,0)@0s>, <Point(2.5,2.5)@0.0s>, <Point(5,5)@0s>]
+			[<Point(0,0)@0.0s>, <Point(2.5,2.5)@0.0s>, <Point(5,5)@0.0s>]
 
 		"""
 		start = self.points[0]
 class Corner(Primitive):
 	def __init__(self, points):
 		if len(points) > 4:
-			error, x, line1, line2 = min(two_line_segment(points, x) for x in range(2, len(points)-2))
-			#~ print
-			#~ print 1 - abs(x - len(points)//2) / x,
+			#~ times = [clock()]
+			#~ print len(points)
+			#~ [x, two_line_segment(points, x)[0] for x in range(2, len(points)-2)]
+			error, x, line1, line2 = min(two_line_segment(points, x) for x in range(2, len(points)-2)) #XXX binary search needed
+			times.append(clock())
 			bad_quality = line1.bad_quality or line2.bad_quality \
 				or line1.intersection_with(line2).type not in ["V", "L"] \
 				or not (0.2 <= line1.curvature_len() / line2.curvature_len() <= 5)
 			points = line1.points + line2.points
 			self.line1 = line1
 			self.line2 = line2
+			#~ times.append(clock())
+			#~ print "c", [t-times[0] for t in times]
 		else:
 			error = Line(points).error
 			bad_quality = True
 	if full_circle:
 		result = Circle(points=new_points, bad_quality=bad_quality, error=normalized_avg_sqrd_residual)
 	else:
+		if Primitive(points).curvature_len() < 23: #XXX small arcs are more likely lines
+			bad_quality = True
 		result = Crescent(points=new_points, bad_quality=bad_quality, error=normalized_avg_sqrd_residual)
 	result.r = r
 	result.z = Point(z.real, z.imag)
 @export
 def symbol_midpoint(primitives):
 	"""
-		>>> symbol_midpoint([Line(points=[Point(0,0,0), Point(5,6,0)])])
-		<Point(2.5,3.0)@0.0s>
+		>>> symbol_midpoint([Line(points=[Point(0,0,0), Point(5,6,10)])])
+		<Point(2.5,3.0)@5.0s>
 
 	"""
 	points = []
 	logging.root.setLevel(logging.INFO)
 	logging.basicConfig()
 	#~ System.host = "tablet"
-	primitive_recognition_accuracy()
+	#~ primitive_recognition_accuracy()
 	#~ draw_unrecognised_primitives()
-	save_primitive_examples_size()
+	#~ save_primitive_examples_size()
+	import profile
+	c = None
+	def f():
+		#~ print c
+		return 1
+	profile.run("f()")