def drawAnno( self, a ): right_color = "#CF0000" left_color = "#0000C0" for wall in a.rightwalls: #Strokes rtv_logger.debug("Drawing right wall") wall = GeomUtils.strokeSmooth(wall, width = 6, preserveEnds = True) SketchGUI.drawStroke(wall, width = 2, color = right_color) for wall in a.leftwalls: #Strokes rtv_logger.debug("Drawing left wall") SketchGUI.drawStroke(wall, width = 2, color = left_color)
def tagBox(self, stroke): endPointDistPct = 0.10 #How close (as % of length) the points have to be to each other boxApproxThresh = 50000 #The DTW distance between the stroke and how it best fits a box stkLen = GeomUtils.strokeLength(stroke) ep1, ep2 = stroke.Points[0], stroke.Points[-1] epDistSqr = GeomUtils.pointDistanceSquared(ep1.X, ep1.Y, ep2.X, ep2.Y) if epDistSqr > (endPointDistPct * stkLen) ** 2: print "Endpoints aren't close enough to be a box" return overshoot = max(1, len(stroke.Points)/10) norm_stroke = GeomUtils.strokeSmooth(GeomUtils.strokeNormalizeSpacing(Stroke(stroke.Points + stroke.Points[0:overshoot]), numpoints = 70)) #D.strokeCurvatureHistogram(norm_stroke) curvatures = GeomUtils.strokeGetPointsCurvature(norm_stroke) corners = set([]) curvatures_cpy = list(curvatures) while len(corners) < 4: crnr_idx = curvatures_cpy.index(max(curvatures_cpy)) crnr = curvatures_cpy[crnr_idx] * 57.295 for nBor in range(crnr_idx -2, crnr_idx + 3): if nBor < len(curvatures_cpy) and nBor > 0: curvatures_cpy[nBor] = 0 if crnr > 0: #30 and crnr < 150: #Have a curvature, and we haven't already classified its immed neighbors as a corner corners.add(crnr_idx) else: break if len(corners) != 4: return else: c_list = [norm_stroke.Points[c_idx] for c_idx in sorted(list(corners))] cornerStroke = Stroke(c_list + c_list[:2]) boxStroke = GeomUtils.strokeNormalizeSpacing(Stroke(c_list + [c_list[0]])) origStroke = GeomUtils.strokeNormalizeSpacing(Stroke(stroke.Points + [stroke.Points[0]])) approxAcc = GeomUtils.strokeDTWDist(boxStroke, origStroke) print "Box approximates original with %s accuracy" % (approxAcc) if approxAcc < boxApproxThresh: self.getBoard().AnnotateStrokes([stroke], BoxAnnotation(c_list))
def onStrokeAdded( self, stroke ): "Watches for Strokes that look like an arrow to Annotate" smoothedStroke = GeomUtils.strokeSmooth(stroke) ep1 = stroke.Points[0] ep2 = stroke.Points[-1] #ep1 = smoothedStroke.Points[0] #ep2 = smoothedStroke.Points[-1] isArrowHead = False #GeomUtils.ellipseAxisRatio(stroke) #Match single-stroke arrows #DISABLED logger.debug("**Warning: Single-stroke arrows disabled**") tip, tail = None, None tip, tail = _isSingleStrokeArrow(smoothedStroke) #if tip is None or tail is None: #revpts = list(smoothedStroke.Points) #revpts.reverse() #tip, tail = _isSingleStrokeArrow(Stroke(revpts)) if tip is not None and tail is not None: isArrowHead = False anno = ArrowAnnotation( tip, tail, headstroke= stroke, tailstroke = stroke ) self.getBoard().AnnotateStrokes( [stroke], anno) #/DISABLED else: if _isArrowHead(smoothedStroke, self.arrowHeadMatcher): logger.debug(" ARROWHEAD") #head = smoothedStroke head = stroke isArrowHead = True # * (tip-point) # o o # o o # o o # o o #Get the endpoints/tip point as max curvature strokeNorm = GeomUtils.strokeNormalizeSpacing(smoothedStroke, numpoints = 7) curvatures = GeomUtils.strokeGetPointsCurvature(strokeNorm) ptIdx = curvatures.index(max(curvatures)) tip = strokeNorm.Points[ptIdx] #Middle is the point of max curvature #Match it to any tails we have matchedTails = self._matchHeadtoTail(head = stroke, point = tip) for headpoint, tail in matchedTails: #Orient the tail correctly if tail.Points[0] == headpoint: endpoint = tail.Points[-1] direction = 'head2tail' elif tail.Points[-1] == headpoint: endpoint = tail.Points[0] direction = 'tail2head' logger.debug("Stroke is head of arrow, drawn %s" % (direction)) anno = ArrowAnnotation(tip, endpoint, headstroke = stroke, tailstroke = tail, direction = direction) self.getBoard().AnnotateStrokes([head, tail],anno) #Match it like a tail even if we think it's an arrowhead. Oh ambiguity! matchedHeads = self._matchHeadtoTail(tail = stroke, point = ep1) tail = stroke for tip, head in matchedHeads: logger.debug("Stroke is tail of arrow, drawn head2tail") anno = ArrowAnnotation(tip, ep2, headstroke = head, tailstroke = tail, direction='head2tail') #Arrow is from the back endpoint to the tip of the arrowhead self.getBoard().AnnotateStrokes([head, tail],anno) matchedHeads = self._matchHeadtoTail(tail = stroke, point = ep2) for tip, head in matchedHeads: logger.debug("Stroke is tail of arrow, drawn tail2head") anno = ArrowAnnotation(tip, ep1, headstroke = head, tailstroke =tail, direction='tail2head') self.getBoard().AnnotateStrokes([head, tail],anno) #Add this stroke to the pool for future evaluation sNorm = GeomUtils.strokeNormalizeSpacing(stroke, numpoints = max(GeomUtils.strokeLength(stroke) / 3, 1)) self._endpoints.append( (ep1, stroke, sNorm) ) self._endpoints.append( (ep2, stroke, sNorm) ) if isArrowHead: self._arrowHeads.append( (tip, stroke, sNorm) )
def drawAnno( self, a ): edge_label_size = 15 tape_label_size = 20 active_color = "#BF5252" active_width = 7.0 state_graph = a.state_graph_anno for from_node, connection_list in state_graph.connectMap.items(): if from_node is not None: nodeColor = "#FFFFFF" if from_node == a.active_state: nodeColor = active_color x, y = ( from_node.center.X, from_node.center.Y ) self.getBoard().getGUI().drawCircle (x, y, radius=(from_node.radius / 2.0), color=nodeColor, width=3.0) #GeomUtils.strokeSmooth(edge.tailstroke, width = len(edge.tailstroke.Points) / 3).drawMyself() for edge, to_node in connection_list: if edge == a.leading_edge['edge']: edgeColor = active_color else: edgeColor = "#FFFFFF" if to_node is not None: nodeColor = "#FFFFFF" nodeWidth = 3.0 if to_node == a.active_state: nodeColor = active_color nodeWidth = active_width x, y = ( to_node.center.X, to_node.center.Y ) self.getBoard().getGUI().drawCircle (x, y, radius=(to_node.radius / 2.0), color=nodeColor, fill="", width=nodeWidth) #Draw the smoothed tail if from_node is not None: if edge.direction == "tail2head": #Connect the tail more closely to the edge smooth_tail = Stroke([from_node.center] + edge.tailstroke.Points + [edge.tip]) else: smooth_tail = Stroke([edge.tip] + edge.tailstroke.Points + [from_node.center]) else: smooth_tail = edge.tailstroke smooth_tail = GeomUtils.strokeSmooth(smooth_tail, width = len(edge.tailstroke.Points) / 3, preserveEnds = True) smooth_tail.drawMyself(color=edgeColor) #Draw the smoothed head ep1, ep2 = ( edge.headstroke.Points[0], edge.headstroke.Points[-1] ) smooth_head = Stroke([ep1, edge.tip, ep2]) smooth_head.drawMyself(color = edgeColor) if edge in a.edge2labels_map: #Determine label offset for label in a.edge2labels_map[edge]: textColor = "#FFFFFF" if label == a.leading_edge['label']: tm_logger.debug("Drawing leading label: %s" % (label.text)) textColor = active_color tl, br = GeomUtils.strokelistBoundingBox(label.Strokes) label_point = Point ((tl.X + br.X) / 2.0, br.Y) label_point.X -= edge_label_size label_point.Y -= edge_label_size #label_point = smooth_tail.Points[len(smooth_tail.Points)/2] self.getBoard().getGUI().drawText (label_point.X, label_point.Y, InText=label.text, size=edge_label_size, color=textColor) #endfor #endif #end for edge #end for from_node #Draw the tape string tl, br = GeomUtils.strokelistBoundingBox(a.Strokes) tape_label_pt = Point( \ ((tl.X + br.X) / 2.0) - (len(a.tape_string) + 2) * tape_label_size / 2.0 , \ br.Y - tape_label_size) for curIdx, tapeChar in enumerate(['-'] + a.tape_string + ['-']): curPt = Point(tape_label_pt.X + curIdx * tape_label_size, tape_label_pt.Y) charColor = "#FFFFFF" if curIdx - 1== a.tape_idx: charColor = active_color self.getBoard().getGUI().drawText (curPt.X, curPt.Y, InText=tapeChar, size=tape_label_size, color=charColor)