Unverified Commit 3ad71c1d authored by Jesse Mapel's avatar Jesse Mapel Committed by GitHub
Browse files

Merge pull request #312 from kberryUSGS/ipceCnetHealth

addEdge(), removeEdge(), and documentation added to ControlNet
parents da0d3267 172e5b63
Loading
Loading
Loading
Loading
+63 −79
Original line number Diff line number Diff line
@@ -418,25 +418,67 @@ namespace Isis {
          ControlMeasure *cm = measures[j];
          if (!cm->IsIgnored()) {
            QString sn = cm->GetCubeSerialNumber();
            addEdge(serial, sn);
          }
        }
      }
    }
    emit newPoint(point);
  }


  /**
   * In the ControlNet graph: adds an edge between the verticies associated with the two serial 
   * numbers provided. Or, if the edge already exists, increments the strength of the edge.  
   * 
   * @param sourceSerial The first serial to be connected by the edge
   * @param targetSerial The second serial number to be connected by the edge
   *  
   * @return bool true if a new edge was added, false otherwise.  
  */
  bool ControlNet::addEdge(QString sourceSerial, QString targetSerial) {
    // If the edge doesn't already exist, this adds and returns the edge.
    // If the edge already exists, this just returns it. (The use of a set
    // forces the edges to be unique.)
    ImageConnection connection;
    bool edgeAdded;
            boost::tie(connection, edgeAdded) = boost::add_edge(m_vertexMap[serial],
                                                       m_vertexMap[sn],

    boost::tie(connection, edgeAdded) = boost::add_edge(m_vertexMap[sourceSerial],
                                                        m_vertexMap[targetSerial],
                                                        m_controlGraph); 
    m_controlGraph[connection].strength++;

            if (edgeAdded) {
              emit networkModified(GraphModified);
            }
          }
    return edgeAdded; 
  }


  /**
   * In the ControlNet graph, decrements the strength on the edge between the two serial numbers. 
   * This is called when the ControlMeasures that connect these images are deleted or ignored. 
   * If it is the last measure connecting two verticies (serial numbers) the edge is removed.  
   * 
   * @param sourceSerial The first serial number defining the end of the edge to have its strength 
   *                     decremented or be removed.
   * @param targetSerial The second serial number defining the other end of the edge to have its 
   *                     strength decremented or be removed.
   * @return bool true if the edge is removed, otherwise false
   */
  bool ControlNet::removeEdge(QString sourceSerial, QString targetSerial) {
    ImageConnection connection;
    bool edgeExists;
    boost::tie(connection, edgeExists) = boost::edge(m_vertexMap[sourceSerial],
                                                     m_vertexMap[targetSerial],
                                                     m_controlGraph);
    if (edgeExists) {
      m_controlGraph[connection].strength--;
      if (m_controlGraph[connection].strength <= 0) {
        boost::remove_edge(m_vertexMap[sourceSerial],
                           m_vertexMap[targetSerial],
                           m_controlGraph);

        return true;
      }
    }
    emit newPoint(point);
    return false;
  }


@@ -570,16 +612,7 @@ namespace Isis {


          if (QString::compare(sn, serial) != 0) {
            // If the edge doesn't already exist, this adds and returns the edge.
            // If the edge already exists, this just returns it. (The use of a set
            // forces the edges to be unique.)
            ImageConnection connection;
            bool edgeAdded;
            boost::tie(connection, edgeAdded) = boost::add_edge(m_vertexMap[serial],
                                                       m_vertexMap[sn],
                                                       m_controlGraph);
            m_controlGraph[connection].strength++;

            bool edgeAdded = addEdge(serial, sn);
            if (edgeAdded) {
              emit networkModified(GraphModified);
            }
@@ -624,20 +657,7 @@ namespace Isis {
          msg += targetSerial + "]";
          throw IException(IException::Programmer, msg, _FILEINFO_);
        }

        // If the edge doesn't already exist, this adds and returns the edge.
        // If the edge already exists, this just returns it. (The use of a set
        // forces the edges to be unique.)
        ImageConnection connection;
        bool edgeAdded;
        boost::tie(connection, edgeAdded) = boost::add_edge(m_vertexMap[sourceSerial],
                                                   m_vertexMap[targetSerial],
                                                   m_controlGraph);
        m_controlGraph[connection].strength++;

        if (edgeAdded) {
          emit networkModified(GraphModified);
        }
        addEdge(sourceSerial, targetSerial); 
      }
    }
  }
@@ -697,15 +717,7 @@ namespace Isis {
          QString sn = cm->GetCubeSerialNumber();

          if (QString::compare(sn, serial) != 0) {
            // If the edge doesn't already exist, this adds and returns the edge.
            // If the edge already exists, this just returns it. (The use of a set
            // forces the edges to be unique.)
            ImageConnection connection;
            bool edgeAdded;
            boost::tie(connection, edgeAdded) = boost::add_edge(m_vertexMap[serial],
                                                       m_vertexMap[sn],
                                                       m_controlGraph);
            m_controlGraph[connection].strength++;
            bool edgeAdded = addEdge(serial, sn); 

            if (edgeAdded) {
              emit networkModified(GraphModified);
@@ -792,25 +804,13 @@ namespace Isis {
          msg += targetSerial + "]";
          throw IException(IException::Programmer, msg, _FILEINFO_);
        }

        std::pair<ImageConnection, bool> result = boost::edge(m_vertexMap[sourceSerial],
                                                              m_vertexMap[targetSerial],
                                                              m_controlGraph);
        if (result.second) {
          ImageConnection connection = result.first;
          m_controlGraph[connection].strength--;
          if (m_controlGraph[connection].strength <= 0) {
            boost::remove_edge(m_vertexMap[sourceSerial],
                               m_vertexMap[targetSerial],
                               m_controlGraph);
            emit networkModified(GraphModified);
          }
        }
        removeEdge(sourceSerial, targetSerial);
      }
    }
  }



  /**
   * Updates the edges in the ControlNet graph to reflect the ignored
   * measure. If this was the last measure connecting one node to another,
@@ -846,29 +846,13 @@ namespace Isis {
      QString sn = adjacentMeasure->GetCubeSerialNumber();
      if (!adjacentMeasure->IsIgnored() && m_vertexMap.contains(sn)) {
        if (QString::compare(serial, sn) !=0) {

          // We need to check if the edge still exists.
          // boost doesn't add separate edges for A -> B and B -> A like the old graph.
          // result.first is the ImageConnection, if found
          // result.second is true if the edge exists; otherwise false.
          std::pair<ImageConnection, bool> result = boost::edge(m_vertexMap[serial],
                                                                m_vertexMap[sn],
                                                                m_controlGraph);
          if (result.second) {
            ImageConnection connection = result.first;
            m_controlGraph[connection].strength--;
            if (m_controlGraph[connection].strength <= 0) {
              boost::remove_edge(m_vertexMap[serial],
                                 m_vertexMap[sn],
                                 m_controlGraph);
          if( removeEdge(serial, sn) ) {
            emit networkModified(GraphModified);
          }
        }
      }
    }
  }
  }



  /**
+30 −14
Original line number Diff line number Diff line
@@ -250,8 +250,11 @@ namespace Isis {
   *                           the p_cameraValidMeasuresMap.
   *   @history 2018-06-25 Jesse Mapel - Fixed the incorrect signal being called when adding and
   *                           removing measures. References #5435.
   *   @history 2018-06-29 Kristin Berry - Added addEdge() and removeEdge() functions to make
   *                           code cleaner. 
   *   @history 2018-06-25 Jesse Mapel - Fixed ignoring measures with ignored adjacent measures
   *                           incorrectly modifying the edge between the two image vertices.

   */
  class ControlNet : public QObject {
      Q_OBJECT
@@ -390,6 +393,8 @@ namespace Isis {
      void emitMeasureModified(ControlMeasure *measure, ControlMeasure::ModType type, QVariant oldValue, QVariant newValue);
      void emitPointModified(ControlPoint *point, ControlPoint::ModType type, QVariant oldValue, QVariant newValue);
      void pointAdded(ControlPoint *point);
      bool addEdge(QString sourceSerial, QString targetSerial); 
      bool removeEdge(QString sourceSerial, QString targetSerial); 

    private: // graphing functions
      /**
@@ -420,31 +425,42 @@ namespace Isis {
      //! hash ControlPoints by ControlPoint Id
      QHash< QString, ControlPoint * > * points;

      // structs and typedefs for the boost graph
      //! Used to define the verticies of the graph
      struct Image {
        QString serial;
        QString serial; //! The serial number associated with the image 
        //! The measures on the image, hashed by pointers to their parent ControlPoints
        QHash< ControlPoint *, ControlMeasure * > measures; 
      };

      //! Used to define the edges of the graph. 
      struct Connection {
        int strength;
        Connection() : strength(0) {}
      };

      //! Defines the graph type as an undirected graph that uses Images for verticies, 
      //! and Connections for edges. It is defined as an adjacency list with the edge list 
      //! represented by a set, the and vertex list represented by a list. 
      typedef boost::adjacency_list<boost::setS,
                                    boost::listS,
                                    boost::undirectedS,
                                    Image,
                                    Connection> Network; 
      typedef Network::vertex_descriptor ImageVertex;
      typedef Network::edge_descriptor ImageConnection;

      typedef Network::vertex_descriptor ImageVertex; //! Reprents the verticies of the graph
      typedef Network::edge_descriptor ImageConnection; //! Represents the edges of the graph

      //! A map between an ImageVertex and its index
      typedef std::map<ImageVertex, size_t> VertexIndexMap; 

      //! Converts VertexIndexMap into the appropriate form to be used by boost
      typedef boost::associative_property_map<VertexIndexMap> VertexIndexMapAdaptor; 
      typedef Network::out_edge_iterator ConnectionIterator;

      //! Iterates over adjacent verticies
      typedef boost::graph_traits<Network>::adjacency_iterator AdjacencyIterator; 

      QHash<QString, ImageVertex> m_vertexMap; //!< The SN -> vertex hash for the boost graph
      Network m_controlGraph; //!< The boost graph
      QHash<QString, ImageVertex> m_vertexMap; //! The serial number -> vertex hash used by the graph
      Network m_controlGraph; //! The ControlNet graph
      QStringList *pointIds; 
      QMutex *m_mutex;