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))
Exemple #3
0
    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)