def _isSingleStrokeArrow(stroke): "Input: Single stroke for evaluation. Returns a tuple of points (tip, tail) if the stroke is an arrow, (None, None) otherwise" logger.debug("stroke len %d", stroke.length() ) if len(stroke.Points) < 10: return (None, None)# too small to be arrow norm_len = len(stroke.Points) points = GeomUtils.strokeNormalizeSpacing( stroke, numpoints=norm_len).Points points.reverse() # start from end # find the first 90 degree turn in the stroke orilist = GeomUtils.strokeLineSegOrientations( Stroke(points) ) logger.debug("stroke ori %s", str(orilist) ) prev = None i = 0 for i,ori in enumerate(orilist): if prev is None: prev = ori continue if GeomUtils.angleDiff(ori,prev)>90: break # found the first turn at index i first_corner = i # now we know the scale of the arrow head if there is one # if the first corner is more than 1/4 of the way from the end of the stroke if first_corner > norm_len/5: return (None, None) # scale is wrong for an arrowhead tail = stroke.Points[0] # first of the original points tip = points[i] # reverse point # create a list of the monoticity of all substrokes from the first corner to some dist after m_list = [ GeomUtils.strokeMonotonicity(Stroke(points[first_corner:x])) for x in range(first_corner+2,first_corner*3) ] if len(m_list) == 0: return (None, None) m_min = min(m_list) logger.debug("stroke mon (%f)", m_min ) if m_min>0.65: return (None, None)# too monotonic after the first corner, need to double back return (tip, tail)
def _isSingleStrokeArrow(stroke): "Input: Single stroke for evaluation. Returns a tuple of points (tip, tail) if the stroke is an arrow, (None, None) otherwise" if len(stroke.Points) < 10: logger.debug("Not a single-stroke arrow: stroke too short") return (None, None)# too small to be arrow """ #Starting code for line curvature classification #points = GeomUtils.strokeNormalizeSpacing( stroke, numpoints=50).Points for gran in range(1, 10): norm_len = max(len(stroke.Points) / gran, 5) points = GeomUtils.strokeNormalizeSpacing( stroke, numpoints=norm_len).Points points.reverse() # start from end # find the first 90 degree turn in the stroke curvatures = GeomUtils.strokeGetPointsCurvature( Stroke(points) ) gran = 0.1 for idx, ori in enumerate(curvatures): print "%s:\t|" % (idx), quantity = ori while quantity > 0: quantity -= gran print "X", print "\t\t%s" % (ori) print "_______________________________" print "Max:%s, Avg%s" % (max(curvatures), sum(curvatures)/float(len(curvatures))) print "_______________________________" #/EndCurvature classification """ norm_len = max(len(stroke.Points) / 10, 15) points = GeomUtils.strokeNormalizeSpacing( stroke, numpoints=norm_len).Points orilist = GeomUtils.strokeLineSegOrientations( Stroke(points) ) #logger.debug("stroke ori %s", str(orilist) ) prev = None i = 0 for i,ori in enumerate(orilist): if prev is None: prev = ori continue if GeomUtils.angleDiff(ori,prev)>90: break # found the first turn at index i first_corner = i # now we know the scale of the arrow head if there is one # if the first corner is more than 1/4 of the way from the end of the stroke if first_corner > norm_len/5: logger.debug("Not a ss arrow: First right angle too far from endpoint") return (None, None) # scale is wrong for an arrowhead tail = stroke.Points[0] # first of the original points tip = points[i] # reverse point # create a list of the monoticity of all substrokes from the first corner to some dist after m_list = [ GeomUtils.strokeMonotonicity(Stroke(points[first_corner:x])) for x in range(first_corner+2,first_corner*3) ] if len(m_list) == 0: logger.debug("Not a ss arrow: Stroke monotonicity list zero length") return (None, None) m_min = min(m_list) #logger.debug("stroke mon (%f)", m_min ) if m_min>0.65: logger.debug("Not a ss arrow: Stroke too monotonic") return (None, None)# too monotonic after the first corner, need to double back logger.debug("Single Stroke Arrow found!") return (tip, tail)