コード例 #1
0
def edgesFromSegs(edge, target_segs, direction):
    if len(target_segs)==0:
        return []
    
    # If the target segments are forked or otherwise complex,
    # return an empty list.
    try:
        (seg_list, node_list, winding) = skeletonsegment.segSequence( target_segs )
    except skeletonsegment.SequenceError:
        return []
    
    ordered_nodes = edge.get_nodes()

    if direction==MAP_UP:
        target_start = ordered_nodes[0].getParents()
    else: # direction==MAP_DOWN
        target_start = ordered_nodes[0].getChildren()
        # the problem is that target_start is not in the "target"

    if node_list[0] in target_start:
        pass
    elif node_list[-1] in target_start:
        seg_list.reverse()
        node_list.reverse()
    else:
        # In cases of boundaries that are loops, when no starting node
        # is passed in, segSequence makes an arbitrary choice for the
        # starting node that can be incorrect, but otherwise sequences
        # the boundary correctly.  In this case, we must re-sequence
        # the list.  The alternative is to pass in a target start to
        # segSequence and then handle the case where the target start
        # is not in the node list in there, but that seems more complicated.

        # calculate overlap between node_list and target_start 
        overlap = [node for node in node_list if node in target_start]
        
        if len(overlap): # elif node_list.intersection(target_start)
            try:
                (seg_list, node_list, winding) = skeletonsegment.segSequence( target_segs, overlap[0] )
            except skeletonsegment.SequenceError:
                return []

        else:
            raise ooferror.ErrPyProgrammingError(
                "Malformed segment sequence -- node counterpart not found.")
    
    target_list = []
    for (s, n)  in map(None, seg_list, node_list[:-1]):
        # if the node_list constitutes a loop, it will be longer than
        # needed, producing an extra item in the list returned by map.
        # We can ignore the extra item in this case.
        if s is None:
            pass
        elif s.nodes()[0]==n:
            target_list.append(skeletonsegment.SkeletonEdge(s,direction=1))
        else:
            target_list.append(skeletonsegment.SkeletonEdge(s,direction=-1))
        
    return target_list
コード例 #2
0
ファイル: skeletonboundary.py プロジェクト: anilkunwar/OOF2
def edgesFromSegs(edge, target_segs, direction):
    if len(target_segs)==0:
        return []
    
    # If the target segments are forked or otherwise complex,
    # return an empty list.
    try:
        (seg_list, node_list, winding) = skeletonsegment.segSequence( target_segs )
    except skeletonsegment.SequenceError:
        return []
    
    ordered_nodes = edge.get_nodes()

    if direction==MAP_UP:
        target_start = ordered_nodes[0].getParents()
    else: # direction==MAP_DOWN
        target_start = ordered_nodes[0].getChildren()
        # the problem is that target_start is not in the "target"

    if node_list[0] in target_start:
        pass
    elif node_list[-1] in target_start:
        seg_list.reverse()
        node_list.reverse()
    else:
        # In cases of boundaries that are loops, when no starting node
        # is passed in, segSequence makes an arbitrary choice for the
        # starting node that can be incorrect, but otherwise sequences
        # the boundary correctly.  In this case, we must re-sequence
        # the list.  The alternative is to pass in a target start to
        # segSequence and then handle the case where the target start
        # is not in the node list in there, but that seems more complicated.

        # calculate overlap between node_list and target_start 
        overlap = [node for node in node_list if node in target_start]
        
        if len(overlap): # elif node_list.intersection(target_start)
            try:
                (seg_list, node_list, winding) = skeletonsegment.segSequence( target_segs, overlap[0] )
            except skeletonsegment.SequenceError:
                return []

        else:
            raise ooferror.ErrPyProgrammingError(
                "Malformed segment sequence -- node counterpart not found.")
    
    target_list = []
    for (s, n)  in map(None, seg_list, node_list[:-1]):
        # if the node_list constitutes a loop, it will be longer than
        # needed, producing an extra item in the list returned by map.
        # We can ignore the extra item in this case.
        if s is None:
            pass
        elif s.nodes()[0]==n:
            target_list.append(skeletonsegment.SkeletonEdge(s,direction=1))
        else:
            target_list.append(skeletonsegment.SkeletonEdge(s,direction=-1))
        
    return target_list
コード例 #3
0
    def delete(self, segments):

        self.sequence()
        old_segments = [x.segment for x in self.edges]

        index_set = []
        for s in segments:
            try:
                index_set.append(old_segments.index(s))
            except ValueError:
                pass   # It's ok if s isn't in the boundary.  Just go on.

        dead_segments = [old_segments[idx] for idx in index_set]
        for d in dead_segments:
            old_segments.remove(d)

        #Interface branch
        if self._sequenceable==1:
            (seg_list, node_list, winding) = skeletonsegment.segSequence(old_segments)

        # If sequencing worked, then the modified boundary is
        # topologically OK.  It is permissible to modify our edges list.

        dead_edges = [self.edges[idx] for idx in index_set]
        for d in dead_edges:
            d.remove() # Remove yourself from the segment's list of edges.
            self.edges.remove(d)

        self.sequence() # Clean up.
コード例 #4
0
ファイル: skeletonboundary.py プロジェクト: anilkunwar/OOF2
    def delete(self, segments):

        self.sequence()
        old_segments = [x.segment for x in self.edges]

        index_set = []
        for s in segments:
            try:
                index_set.append(old_segments.index(s))
            except ValueError:
                pass   # It's ok if s isn't in the boundary.  Just go on.

        dead_segments = [old_segments[idx] for idx in index_set]
        for d in dead_segments:
            old_segments.remove(d)

        #Interface branch
        if self._sequenceable==1:
            (seg_list, node_list, winding) = skeletonsegment.segSequence(old_segments)

        # If sequencing worked, then the modified boundary is
        # topologically OK.  It is permissible to modify our edges list.

        dead_edges = [self.edges[idx] for idx in index_set]
        for d in dead_edges:
            d.remove() # Remove yourself from the segment's list of edges.
            self.edges.remove(d)

        self.sequence() # Clean up.
コード例 #5
0
def _loadEdgeBoundary(menuitem, skeleton, name, edges, exterior):
    ##    debug.fmsg()
    # "edges" is a list of pairs of integer indices into skeleton.nodes
    skelcontext = skeletoncontext.skeletonContexts[skeleton]
    skeleton = skelcontext.getObject()
    seglist = [
        skeleton.getSegment(*[skeleton.nodes[i] for i in e]) for e in edges
    ]
    #Interface branch
    try:
        (segs, nodes, winding) = skeletonsegment.segSequence(seglist)
        startnode = skeleton.nodes[edges[0][0]]
        skelcontext.createEdgeBoundary(name,
                                       seglist,
                                       startnode,
                                       exterior,
                                       autoselect=0)
    except skeletonsegment.SequenceError:
        directionlist = []
        for i in range(len(edges)):
            if seglist[i].get_nodes()[0] == skeleton.nodes[edges[i][0]]:
                directionlist.append(1)
            else:
                directionlist.append(-1)
        skelcontext.createNonsequenceableEdgeBoundary(name,
                                                      seglist,
                                                      directionlist,
                                                      exterior,
                                                      autoselect=0)
コード例 #6
0
    def try_append(self, new_segments):
        if len(self.edges)==0:
            return 0
        self.sequence()
        
        all_segments = new_segments.union([x.segment for x in self.edges])

        try:
            (seg_list, node_list, winding) = skeletonsegment.segSequence(all_segments)
            return 1
        except skeletonsegment.SequenceError:
            return 0
コード例 #7
0
ファイル: skeletonboundary.py プロジェクト: anilkunwar/OOF2
    def try_append(self, new_segments):
        if len(self.edges)==0:
            return 0
        self.sequence()
        
        all_segments = new_segments.union([x.segment for x in self.edges])

        try:
            (seg_list, node_list, winding) = skeletonsegment.segSequence(all_segments)
            return 1
        except skeletonsegment.SequenceError:
            return 0
コード例 #8
0
 def loop_check(self):
     seg_set = self.segmenter(self.skelcontext, self.aggwidget.get_value())
     try:
         (segs, nodes, winding) = skeletonsegment.segSequence(seg_set)
     except skeletonsegment.SequenceError:
         return -1
     else:
         if len(nodes) > 0:
             if nodes[0] == nodes[-1] and winding == [0, 0]:
                 return 1
             for partner in nodes[0].getPartners():
                 if partner == nodes[-1] and winding == [0, 0]:
                     return 1
             return 0
         return -1  # Zero-length list is also invalid.
コード例 #9
0
 def loop_check(self):
     seg_set = self.segmenter(self.skelcontext, self.aggwidget.get_value())
     try:
         (segs, nodes, winding) = skeletonsegment.segSequence(seg_set)
     except skeletonsegment.SequenceError:
         return -1
     else:
         if len(nodes) > 0:
             if nodes[0] == nodes[-1] and winding == [0, 0]:
                 return 1
             for partner in nodes[0].getPartners():
                 if partner == nodes[-1] and winding == [0, 0]:
                     return 1
             return 0
         return -1  # Zero-length list is also invalid.
コード例 #10
0
 def loop_check(self):
     # seg_set = self.segmenter(self.skelcontext, self.aggwidget.get_value())
     if self.interfacewidget.get_value() is None:
         return -2
     skelobj = self.skelcontext.getObject()
     (seg_set, direction_set) = skelobj.getInterfaceSegments(self.skelcontext, self.interfacewidget.get_value())
     try:
         (segs, nodes, winding) = skeletonsegment.segSequence(seg_set)
     except skeletonsegment.SequenceError:
         return -1
     else:
         if len(nodes) > 0:
             if nodes[0] == nodes[-1] and winding == [0, 0]:
                 return 1
             for partner in nodes[0].getPartners():
                 if partner == nodes[-1] and winding == [0, 0]:
                     return 1
             return 0
         return -1  # Zero-length list is also invalid.
コード例 #11
0
 def loop_check(self):
     #seg_set = self.segmenter(self.skelcontext, self.aggwidget.get_value())
     if self.interfacewidget.get_value() is None:
         return -2
     skelobj = self.skelcontext.getObject()
     (seg_set, direction_set) = skelobj.getInterfaceSegments(
         self.skelcontext, self.interfacewidget.get_value())
     try:
         (segs, nodes, winding) = skeletonsegment.segSequence(seg_set)
     except skeletonsegment.SequenceError:
         return -1
     else:
         if len(nodes) > 0:
             if nodes[0] == nodes[-1] and winding == [0, 0]:
                 return 1
             for partner in nodes[0].getPartners():
                 if partner == nodes[-1] and winding == [0, 0]:
                     return 1
             return 0
         return -1  # Zero-length list is also invalid.
コード例 #12
0
    def try_delete(self, segments):
        self.sequence()
        old_segments =  [x.segment for x in self.edges]

        index_set = []
        for s in segments:
            try:
                index_set.append(old_segments.index(s))
            except ValueError:
                pass   # It's ok if s isn't in the boundary.  Just go on.

        dead_segments = [old_segments[idx] for idx in index_set]
        for d in dead_segments:
            old_segments.remove(d)

        try:
            (seg_list, node_list, winding) = skeletonsegment.segSequence(old_segments)
            return 1
        except skeletonsegment.SequenceError:
            return 0
コード例 #13
0
ファイル: skeletonboundary.py プロジェクト: anilkunwar/OOF2
    def try_delete(self, segments):
        self.sequence()
        old_segments =  [x.segment for x in self.edges]

        index_set = []
        for s in segments:
            try:
                index_set.append(old_segments.index(s))
            except ValueError:
                pass   # It's ok if s isn't in the boundary.  Just go on.

        dead_segments = [old_segments[idx] for idx in index_set]
        for d in dead_segments:
            old_segments.remove(d)

        try:
            (seg_list, node_list, winding) = skeletonsegment.segSequence(old_segments)
            return 1
        except skeletonsegment.SequenceError:
            return 0
コード例 #14
0
ファイル: skeletonIO.py プロジェクト: anilkunwar/OOF2
def _loadEdgeBoundary(menuitem, skeleton, name, edges, exterior):
##    debug.fmsg()
    # "edges" is a list of pairs of integer indices into skeleton.nodes
    skelcontext = skeletoncontext.skeletonContexts[skeleton]
    skeleton = skelcontext.getObject()
    seglist = [skeleton.getSegment(
        *[skeleton.nodes[i] for i in e] )
               for e in edges]
    #Interface branch
    try:
        (segs, nodes, winding) = skeletonsegment.segSequence(seglist)
        startnode = skeleton.nodes[edges[0][0]]
        skelcontext.createEdgeBoundary(name, seglist, startnode,
                                       exterior, autoselect=0)
    except skeletonsegment.SequenceError:
        directionlist=[]
        for i in range(len(edges)):
            if seglist[i].get_nodes()[0]==skeleton.nodes[edges[i][0]]:
                directionlist.append(1)
            else:
                directionlist.append(-1)
        skelcontext.createNonsequenceableEdgeBoundary(name, seglist,
                                                      directionlist,
                                                      exterior, autoselect=0)
コード例 #15
0
ファイル: boundarybuilder.py プロジェクト: song2001/OOF2
def _segset2seglist(seg_set, direction, skel):

    if len(seg_set)==0:
        raise ooferror.ErrUserError(
            "Attempt to sequence null segment set.")
    
    (seg_list, node_list, winding_number) = skeletonsegment.segSequence(seg_set)
    
    # At this point, seg_list is an ordered list of adjacent
    # segments, and "node_list" is the corresponding set of nodes.
    # The path is a loop if node_list[0]==node_list[-1], otherwise
    # it's a simple path.

    # We may want to reverse this list, depending on the
    # setting of "direction".
    firstnode = node_list[0]
    lastnode = node_list[-1]
    
    startnode = firstnode
    # The winding number is used to handle the cases where the line
    # crosses a periodic boundary.
    if (firstnode != lastnode and firstnode not in lastnode.getPartners()) \
       or winding_number != [0,0]:
        # In case the first node and last node are partners, we set them
        # equal so that we can compare positions properly.
        if lastnode in firstnode.getPartners():
            lastnode = firstnode
        if direction == director.Director('Left to right'):
            if firstnode.position().x > \
               lastnode.position().x + winding_number[0]*skel.MS.size()[0]:
                seg_list.reverse()
                startnode = lastnode
        elif direction == director.Director('Right to left'):
            if firstnode.position().x < \
               lastnode.position().x + winding_number[0]*skel.MS.size()[0]:
                seg_list.reverse()
                startnode = lastnode
        elif direction == director.Director('Top to bottom'):
            if firstnode.position().y < \
               lastnode.position().y + winding_number[1]*skel.MS.size()[1]:
                seg_list.reverse()
                startnode = lastnode
        elif direction == director.Director('Bottom to top'):
            if firstnode.position().y > \
               lastnode.position().y + winding_number[1]*skel.MS.size()[1]:
                seg_list.reverse()
                startnode = lastnode
        else:
            # User specified clockwise or counterclockwise for a
            # non-loop segment set.  This is an error.
            raise ooferror.ErrUserError(
                "Clockwise or counterclockwise is for closed loops.")

    # Use the total area swept out by vectors from the origin to the
    # nodes along the path as we traverse the path in order to
    # determine if the existing sequence traces a clockwise or
    # counterclockwise path.  If two consecutive nodes in the
    # node_list are not the endpoints of a segment, we are crossing a
    # periodic boundary.  In this case, use the positions not to find
    # the area swept out, but to increment the position_adjustment
    # needed to unwrap the periodic boundary conditions.
    else: # firstnode==lastnode, loop case.
        startnode = None
        area = 0.0
        p0 = node_list[0].position()
        position_adjustment = primitives.Point(0,0)
        for i in range(1,len(node_list)):
            p1 = node_list[i].position() + position_adjustment
            if skel.findSegment(node_list[i],node_list[i-1]) is not None:
                area += p0.x * p1.y - p1.x * p0.y
                p0 = p1
            else:
                position_adjustment += p0 - p1
                # setting p0 = p1 here will be redundant as we
                # must now adjust positions by p0 - p1
            
        if direction == director.Director('Clockwise'):
            if area > 0.0:
                seg_list.reverse()
        elif direction == director.Director('Counterclockwise'):
            if area < 0.0:
                seg_list.reverse()
        else:
            # User specified an endpoint orientation on a loop.
            raise ooferror.ErrUserError(
                "Closed loops need clockwise or counterclockwise direction.")

    return (startnode, seg_list)
コード例 #16
0
ファイル: skeletonboundary.py プロジェクト: anilkunwar/OOF2
    def map(self, skeleton, new_skeleton,
            direction=MAP_DOWN, exterior=None, local=1):
        old_bdy = self.boundaryset[skeleton]
        
        if old_bdy._sequenceable==1: # TODO: use a boolean
            new_bdy = new_skeleton.makeEdgeBoundary(
                self.name, exterior=exterior)
        else:
            new_bdy = new_skeleton.makeNonsequenceableEdgeBoundary(
                self.name, exterior=exterior)

        if local:
            self.boundaryset[new_skeleton] = new_bdy

        #TODO: Interface branch. Should this be modified to handle
        #non-sequenceable segments? Gut feeling is it already does.
        
        # Deduce the corresponding edges in the new mesh.
        old_edges = old_bdy.edges[:]

        while len(old_edges) > 0:
            # Start from the back, so list removal is efficient.
            e = old_edges[-1]
            
            # HERE: With a too-small undo buffer, m.source is mangled here,
            # causing map_end to be null, causing boundaries not to be
            # propagated.
            ## TODO: Does the above comment refer to an existing
            ## problem which still needs to be fixed?
            if direction==MAP_DOWN:
                m = e.segment.map()
                map_start = m.source
                map_end = m.target
            else: # direction==MAP_UP
                if len(e.segment.getParents())==0:
                    del old_edges[-1]
                    continue
                m = e.segment.getParents()[0].map()
                map_start = m.target
                map_end = m.source
                

            if len(map_start)==1:
                # One-to-many case -- Sequence and edge-ify.
                new_eset = edgesFromSegs(e, map_end, direction)
                for new_edge in new_eset:
                    new_bdy.addEdge(new_edge)
                del old_edges[-1]
            else:
                # Many-to-one or many-to-many case.
                # First, find all the edges of this bdy in the parent part.
                source_eset = set(
                    [e] + [edg for seg in map_start for edg in seg.edges
                           if edg in old_edges])
                # Remove them from the old-edge list.
                # This assumes that the old edges are contiguous
                # at the end of the list, which is true if the
                # boundary is sequenceable.  TODO: is it always?
                del old_edges[-len(source_eset):]

                # Sequence the source edges -- this is the path the
                # original boundary takes through the source part
                # of the map.
                try:
                    (edge_seq, node_seq, winding) = skeletonsegment.segSequence(
                        source_eset)
                except skeletonsegment.SequenceError:
                    continue # Re-enter the while loop.
                
                # Direct the resulting edge-sequence correctly.  Edges
                # always return their nodes in order.
                if node_seq[0] != edge_seq[0].get_nodes()[0]:
                    edge_seq.reverse()
                    node_seq.reverse()
                    
                # Extract the subset of the target that has some
                # relation to the boundary part of the parent.
                sub_target = []
                for e in edge_seq:
                    if direction==MAP_DOWN:
                        for c in e.segment.getChildren():
                            if c not in sub_target:
                                sub_target.append(c)
                    else: # direction==MAP_UP:
                        for p in e.segment.getParents():
                            if p not in sub_target:
                                sub_target.append(p)

                # Exterior check -- for the exterior case, the only
                # valid target segments are those which have exactly one
                # element.
                if exterior:
                    narrow_target = []
                    for s in sub_target:
                        if s.nElements()==1:
                            narrow_target.append(s)
                    sub_target = narrow_target
                        
                # Find the counterparts of the endpoints of the path, if
                # they exist and are unique, otherwise fail.
                if direction==MAP_DOWN:
                    start_shadow = node_seq[0].getChildren()
                    end_shadow = node_seq[-1].getChildren()
                else:
                    start_shadow = node_seq[0].getParents()
                    end_shadow = node_seq[-1].getParents()

                if len(start_shadow)==1:
                    target_start = start_shadow[0]
                else:
                    continue


                if len(end_shadow)==1:
                    target_end = end_shadow[0]
                else:
                    continue

                # If the points are not distinct, fail.
                if target_start == target_end:
                    continue
                
                # Find the paths in the target subset segment set from
                # the start node to the end node.  The returned path
                # is sequenced.
                path_set = skeletonsegment.segPath(
                    target_start, target_end, sub_target)

                # If the path is not unique, fail.
                if len(path_set)!=1:
                    continue

                # Success!  We have a single unique sequenced set of
                # segments from child_start to child_end.  Convert
                # them to edges and add them to the boundary.
                n1 = target_start
                for seg in path_set[0]:
                    nodes = seg.get_nodes()
                    if nodes[0]==n1:
                        e = skeletonsegment.SkeletonEdge(seg, direction=1)
                        n2 = nodes[1]
                    else:
                        e = skeletonsegment.SkeletonEdge(seg, direction=-1)
                        n2 = nodes[0]
                    new_bdy.addEdge(e)
                    n1 = n2 # Reset n1 for next iteration.
コード例 #17
0
    def append(self, new_segments):

        if len(self.edges)==0:
            raise ooferror.ErrUserError(
                "Cannot append to an empty boundary.")
        
        self.sequence()  # Make sure we're in order, first.  
        all_segments = new_segments.union([x.segment for x in self.edges])

        (seg_list, node_list, winding) = skeletonsegment.segSequence(all_segments)

        # Explicitly check for the loop case -- if it occurs, the
        # seg_list needs to be "manually" brought into correspondence
        # with the current edge list, otherwise the following code can
        # be confused by the wrap-around and fail to add the new
        # segments.
        if node_list[0]==node_list[-1]:
            # First, check orientation -- only meaningful if there was
            # more than one edge to begin with.
            if len(self.edges)>1:
                s0_idx = seg_list.index(self.edges[0].segment)
                s1_idx = seg_list.index(self.edges[1].segment)
                # If s1 is the successor of s0, mod the length, it's OK.
                if ((s0_idx+1) % len(seg_list)) != s1_idx:
                    seg_list.reverse()
                    
            # Now rotate the seg_list so that self.edges[0].segment
            # is at the beginning.
            s0_idx = seg_list.index(self.edges[0].segment)
            seg_list = seg_list[s0_idx:]+seg_list[:s0_idx]

        # At this point, seg_list is topologically OK -- either it's a
        # loop starting from s0, or it's a line straight from the
        # sequencer.  In the latter case, it still might be backwards.
        s0 = self.edges[0].segment
        s1 = self.edges[-1].segment

        # If it is backwards, fix it.
        if seg_list.index(s0) > seg_list.index(s1):
            seg_list.reverse()

        first_original_edge = self.edges[0]
        last_original_edge = self.edges[-1]
        
        # Check the front.
        idx = seg_list.index(s0)
        if idx!=0: # There are edges to prepend to the front.
            contact_node = first_original_edge.get_nodes()[0]
            for jdx in range(idx-1,-1,-1): # Count down to zero.
                seg = seg_list[jdx]
                nodes = seg.get_nodes()
                if nodes[1]==contact_node:
                    self.addEdge(
                        skeletonsegment.SkeletonEdge(seg,direction=1))
                    contact_node = nodes[0]
                elif nodes[0]==contact_node:
                    self.addEdge(
                        skeletonsegment.SkeletonEdge(seg,direction=-1))
                    contact_node = nodes[1]
                else:
                    # If there's no place to put the segment, then
                    # something's gone badly wrong.
                    raise ooferror.ErrPyProgrammingError(
                        "No adjacent node for new segment in boundary!")

        # Now check the back.
        idx = seg_list.index(s1)
        if idx<len(seg_list):
            contact_node = last_original_edge.get_nodes()[1]
            for jdx in range(idx+1,len(seg_list)):
                seg = seg_list[jdx]
                nodes = seg.get_nodes()
                if nodes[0]==contact_node:
                    self.addEdge(
                        skeletonsegment.SkeletonEdge(seg,direction=1))
                    contact_node = nodes[1]
                elif nodes[1]==contact_node:
                    self.addEdge(
                        skeletonsegment.SkeletonEdge(seg,direction=-1))
                    contact_node = nodes[0]
                else:
                    raise ooferror.ErrPyProgrammingError(
                        "No adjacent node for new segment in boundary!")

        self.sequence() # Clean up.
コード例 #18
0
ファイル: skeletonboundary.py プロジェクト: anilkunwar/OOF2
    def append(self, new_segments):

        if len(self.edges)==0:
            raise ooferror.ErrUserError(
                "Cannot append to an empty boundary.")
        
        self.sequence()  # Make sure we're in order, first.  
        all_segments = new_segments.union([x.segment for x in self.edges])

        (seg_list, node_list, winding) = skeletonsegment.segSequence(all_segments)

        # Explicitly check for the loop case -- if it occurs, the
        # seg_list needs to be "manually" brought into correspondence
        # with the current edge list, otherwise the following code can
        # be confused by the wrap-around and fail to add the new
        # segments.
        if node_list[0]==node_list[-1]:
            # First, check orientation -- only meaningful if there was
            # more than one edge to begin with.
            if len(self.edges)>1:
                s0_idx = seg_list.index(self.edges[0].segment)
                s1_idx = seg_list.index(self.edges[1].segment)
                # If s1 is the successor of s0, mod the length, it's OK.
                if ((s0_idx+1) % len(seg_list)) != s1_idx:
                    seg_list.reverse()
                    
            # Now rotate the seg_list so that self.edges[0].segment
            # is at the beginning.
            s0_idx = seg_list.index(self.edges[0].segment)
            seg_list = seg_list[s0_idx:]+seg_list[:s0_idx]

        # At this point, seg_list is topologically OK -- either it's a
        # loop starting from s0, or it's a line straight from the
        # sequencer.  In the latter case, it still might be backwards.
        s0 = self.edges[0].segment
        s1 = self.edges[-1].segment

        # If it is backwards, fix it.
        if seg_list.index(s0) > seg_list.index(s1):
            seg_list.reverse()

        first_original_edge = self.edges[0]
        last_original_edge = self.edges[-1]
        
        # Check the front.
        idx = seg_list.index(s0)
        if idx!=0: # There are edges to prepend to the front.
            contact_node = first_original_edge.get_nodes()[0]
            for jdx in range(idx-1,-1,-1): # Count down to zero.
                seg = seg_list[jdx]
                nodes = seg.get_nodes()
                if nodes[1]==contact_node:
                    self.addEdge(
                        skeletonsegment.SkeletonEdge(seg,direction=1))
                    contact_node = nodes[0]
                elif nodes[0]==contact_node:
                    self.addEdge(
                        skeletonsegment.SkeletonEdge(seg,direction=-1))
                    contact_node = nodes[1]
                else:
                    # If there's no place to put the segment, then
                    # something's gone badly wrong.
                    raise ooferror.ErrPyProgrammingError(
                        "No adjacent node for new segment in boundary!")

        # Now check the back.
        idx = seg_list.index(s1)
        if idx<len(seg_list):
            contact_node = last_original_edge.get_nodes()[1]
            for jdx in range(idx+1,len(seg_list)):
                seg = seg_list[jdx]
                nodes = seg.get_nodes()
                if nodes[0]==contact_node:
                    self.addEdge(
                        skeletonsegment.SkeletonEdge(seg,direction=1))
                    contact_node = nodes[1]
                elif nodes[1]==contact_node:
                    self.addEdge(
                        skeletonsegment.SkeletonEdge(seg,direction=-1))
                    contact_node = nodes[0]
                else:
                    raise ooferror.ErrPyProgrammingError(
                        "No adjacent node for new segment in boundary!")

        self.sequence() # Clean up.
コード例 #19
0
    def map(self, skeleton, new_skeleton,
            direction=MAP_DOWN, exterior=None, local=1):

        old_bdy = self.boundaryset[skeleton]
        
        if old_bdy._sequenceable==1: # TODO: use a boolean
            new_bdy = new_skeleton.makeEdgeBoundary(
                self.name, exterior=exterior)
        else:
            new_bdy = new_skeleton.makeNonsequenceableEdgeBoundary(
                self.name, exterior=exterior)

        if local:
            self.boundaryset[new_skeleton] = new_bdy

        #TODO: Interface branch. Should this be modified to handle
        #non-sequenceable segments? Gut feeling is it already does.
        
        # Deduce the corresponding edges in the new mesh.
        old_edges = old_bdy.edges[:]

        while len(old_edges) > 0:
            # Start from the back, so list removal is efficient.
            e = old_edges[-1]
            
            # HERE: With a too-small undo buffer, m.source is mangled here,
            # causing map_end to be null, causing boundaries not to be
            # propagated.
            ## TODO: Does the above comment refer to an existing
            ## problem which still needs to be fixed?
            if direction==MAP_DOWN:
                m = e.segment.map()
                map_start = m.source
                map_end = m.target
            else: # direction==MAP_UP
                if len(e.segment.getParents())==0:
                    del old_edges[-1]
                    continue
                m = e.segment.getParents()[0].map()
                map_start = m.target
                map_end = m.source

            if len(map_start)==1:
                # One-to-many case -- Sequence and edge-ify.
                new_eset = edgesFromSegs(e, map_end, direction)
                for new_edge in new_eset:
                    new_bdy.addEdge(new_edge)
                del old_edges[-1]
            else:
                # Many-to-one or many-to-many case.
                # First, find all the edges of this bdy in the parent part.
                source_eset = set(
                    [e] + [edg for seg in map_start for edg in seg.edges
                           if edg in old_edges])
                # Remove them from the old-edge list.
                # This assumes that the old edges are contiguous
                # at the end of the list, which is true if the
                # boundary is sequenceable.  TODO: is it always?
                del old_edges[-len(source_eset):]

                # Sequence the source edges -- this is the path the
                # original boundary takes through the source part
                # of the map.
                try:
                    (edge_seq, node_seq, winding) = skeletonsegment.segSequence(
                        source_eset)
                except skeletonsegment.SequenceError:
                    continue # Re-enter the while loop.
                
                # Direct the resulting edge-sequence correctly.  Edges
                # always return their nodes in order.
                if node_seq[0] != edge_seq[0].get_nodes()[0]:
                    edge_seq.reverse()
                    node_seq.reverse()
                    
                # Extract the subset of the target that has some
                # relation to the boundary part of the parent.
                sub_target = []
                for e in edge_seq:
                    if direction==MAP_DOWN:
                        for c in e.segment.getChildren():
                            if c not in sub_target:
                                sub_target.append(c)
                    else: # direction==MAP_UP:
                        for p in e.segment.getParents():
                            if p not in sub_target:
                                sub_target.append(p)

                # Exterior check -- for the exterior case, the only
                # valid target segments are those which have exactly one
                # element.
                if exterior:
                    narrow_target = []
                    for s in sub_target:
                        if s.nElements()==1:
                            narrow_target.append(s)
                    sub_target = narrow_target
                        
                # Find the counterparts of the endpoints of the path, if
                # they exist and are unique, otherwise fail.
                if direction==MAP_DOWN:
                    start_shadow = node_seq[0].getChildren()
                    end_shadow = node_seq[-1].getChildren()
                else:
                    start_shadow = node_seq[0].getParents()
                    end_shadow = node_seq[-1].getParents()

                if len(start_shadow)==1:
                    target_start = start_shadow[0]
                else:
                    continue


                if len(end_shadow)==1:
                    target_end = end_shadow[0]
                else:
                    continue

                # If the points are not distinct, fail.
                if target_start == target_end:
                    continue
                
                # Find the paths in the target subset segment set from
                # the start node to the end node.  The returned path
                # is sequenced.
                path_set = skeletonsegment.segPath(
                    target_start, target_end, sub_target)

                # If the path is not unique, fail.
                if len(path_set)!=1:
                    continue

                # Success!  We have a single unique sequenced set of
                # segments from child_start to child_end.  Convert
                # them to edges and add them to the boundary.
                n1 = target_start
                for seg in path_set[0]:
                    nodes = seg.get_nodes()
                    if nodes[0]==n1:
                        e = skeletonsegment.SkeletonEdge(seg, direction=1)
                        n2 = nodes[1]
                    else:
                        e = skeletonsegment.SkeletonEdge(seg, direction=-1)
                        n2 = nodes[0]
                    new_bdy.addEdge(e)
                    n1 = n2 # Reset n1 for next iteration.