Пример #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
    def set_boundaries(self):
        global _rank
        # point boundaries
        pbInfo = {'names':[], 'nodes':[], 'exterior':[]}
        for pbname, pb in self.dummy.pointboundaries.items():
            nodes = []
            for nd in pb.nodes:
                if _rank in nd.owners():
                    nodes.append(self.indexMap[(_rank, nd.getIndex())])
            #if nodes:  # something in it
            if 1: #RCL: admit boundaries without any nodes touching them.
                pbInfo['names'].append(pbname)
                pbInfo['nodes'].append(nodes)
                pbInfo['exterior'].append(pb.exterior())

        # edge boundaries
        ebInfo = {'names':[], 'edges':[], 'exterior':[]}
        for ebname, eb in self.dummy.edgeboundaries.items():
            edges = []
            for ed in eb.edges:
                nd0, nd1 = ed.get_nodes()
                if _rank in nd0.owners() and _rank in nd1.owners():
                    edges.append([self.indexMap[(_rank, nd0.getIndex())],
                                  self.indexMap[(_rank, nd1.getIndex())]])
            #if edges:  # something in it
            if 1: #RCL: admit boundaries without any nodes touching them.
                ebInfo['names'].append(ebname)
                ebInfo['edges'].append(edges)
                ebInfo['exterior'].append(eb.exterior())

        # point boundaries
        for name, nodes, exterior in zip(pbInfo['names'],
                                         pbInfo['nodes'],
                                         pbInfo['exterior']):
            pb = self.skeleton.getPointBoundary(name, exterior=exterior)
            for nd in nodes:
                pb.addNode(self.skeleton.getNodeWithIndex(nd))
        # edge boundaries
        for name, edges, exterior in zip(ebInfo['names'],
                                         ebInfo['edges'],
                                         ebInfo['exterior']):
            eb = self.skeleton.getEdgeBoundary(name, exterior=exterior)
            for ed in edges:
                seg = self.skeleton.findSegment(
                    self.skeleton.getNodeWithIndex(ed[0]),
                    self.skeleton.getNodeWithIndex(ed[1]))
                direction = (seg.nodeIndices() == ed)
                edge = skeletonsegment.SkeletonEdge(seg, direction=direction)
                eb.addEdge(edge)
Пример #3
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.
Пример #4
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.