diff options
Diffstat (limited to 'stsci')
| -rw-r--r-- | stsci/sphere/graph.py | 103 | 
1 files changed, 56 insertions, 47 deletions
| diff --git a/stsci/sphere/graph.py b/stsci/sphere/graph.py index 928abba..934222e 100644 --- a/stsci/sphere/graph.py +++ b/stsci/sphere/graph.py @@ -46,6 +46,7 @@ import numpy as np  # LOCAL  from . import great_circle_arc +from . import math_util  from . import vector  # Set to True to enable some sanity checks @@ -84,27 +85,6 @@ class Graph:          def __repr__(self):              return "Node(%s %d)" % (str(self._point), len(self._edges)) -        def follow(self, edge): -            """ -            Follows from one edge to another across this node. - -            Parameters -            ---------- -            edge : `~Graph.Edge` instance -                The edge to follow away from. - -            Returns -            ------- -            other : `~Graph.Edge` instance -                The other edge. -            """ -            edges = list(self._edges) -            assert len(edges) == 2 -            try: -                return edges[not edges.index(edge)] -            except IndexError: -                raise ValueError("Following from disconnected edge") -          def equals(self, other, thres=2e-8):              """              Returns `True` if the location of this and the *other* @@ -200,6 +180,16 @@ class Graph:          self.add_polygons(polygons) +    def __repr__(self): +        buf = [] +        for node in self._nodes: +            buf.append(repr(node)) +        for edge in self._edges: +            buf.append(repr(edge)) +        for poly in self._source_polygons: +            buf.append(repr(poly)) +        return "\n".join(buf) + "\n" +      def add_polygons(self, polygons):          """          Add more polygons to the graph. @@ -772,29 +762,22 @@ class Graph:          self._remove_orphaned_nodes() -    def _remove_3ary_edges(self, large_first=False): +    def _remove_3ary_edges(self):          """ -        Remove edges between pairs of nodes that have 3 or more edges. -        This removes triangles that can't be traced. +        Remove edges between pairs of nodes that have odd numbers of +        edges.  This removes triangles that can't be traced.          """ -        if large_first: -            max_ary = 0 -            for node in self._nodes: -                max_ary = max(len(node._edges), max_ary) -            order = list(range(max_ary + 1, 2, -1)) -        else: -            order = [3] - -        for i in order: -            removals = [] -            for edge in list(self._edges): -                if (len(edge._nodes[0]._edges) >= i and -                    len(edge._nodes[1]._edges) >= i): -                    removals.append(edge) - -            for edge in removals: -                if edge in self._edges: -                    self.remove_edge(edge) +        removals = [] +        for edge in list(self._edges): +            nedges_a = len(edge._nodes[0]._edges) +            nedges_b = len(edge._nodes[1]._edges) +            if (nedges_a % 2 == 1 and nedges_a >= 3 and +                nedges_b % 2 == 1 and nedges_b >= 3): +                removals.append(edge) + +        for edge in removals: +            if edge in self._edges: +                self._remove_edge(edge)      def _remove_orphaned_nodes(self):          """ @@ -820,6 +803,36 @@ class Graph:          """          from . import polygon as mpolygon +        def pick_next_edge(node, last_edge): +            # Pick the next edge when arriving at a node from +            # last_edge.  If there's only one other edge, the choice +            # is obvious.  If there's more than one, disfavor an edge +            # with the same normal as the previous edge, in order to +            # trace 4-connected nodes into separate distinct shapes +            # and avoid edge crossings. +            candidates = [] +            for edge in node._edges: +                if not edge._followed: +                    candidates.append(edge) +            if len(candidates) == 0: +                raise ValueError("No more edges to follow") +            elif len(candidates) == 1: +                return candidates[0] + +            for edge in candidates: +                last_edge_cross = math_util.cross( +                    last_edge._nodes[0]._point, last_edge._nodes[1]._point) +                if (not +                    np.all(math_util.cross( +                        edge._nodes[0]._point, edge._nodes[1]._point) == +                           last_edge_cross) or +                    np.all(math_util.cross( +                        edge._nodes[0]._point, edge._nodes[1]._point) == +                           last_edge_cross)): +                    return edge + +            return candidates[0] +          polygons = []          edges = set(self._edges)  # copy          for edge in self._edges: @@ -836,11 +849,7 @@ class Graph:                          points.append(node._point)                  else:                      points.append(node._point) -                for edge in node._edges: -                    if edge._followed is False: -                        break -                else: -                    raise ValueError("No more edges to follow") +                edge = pick_next_edge(node, edge)                  edge._followed = True                  edges.discard(edge)                  node = edge.follow(node) | 
