Tulip  4.6.0
Better Visualization Through Research
library/tulip-core/include/tulip/cxx/minmaxproperty.cxx
00001 /*
00002  *
00003  * This file is part of Tulip (www.tulip-software.org)
00004  *
00005  * Authors: David Auber and the Tulip development Team
00006  * from LaBRI, University of Bordeaux
00007  *
00008  * Tulip is free software; you can redistribute it and/or modify
00009  * it under the terms of the GNU Lesser General Public License
00010  * as published by the Free Software Foundation, either version 3
00011  * of the License, or (at your option) any later version.
00012  *
00013  * Tulip is distributed in the hope that it will be useful,
00014  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
00016  * See the GNU General Public License for more details.
00017  *
00018  */
00019 #include <tulip/Graph.h>
00020 #include <tulip/Coord.h>
00021 
00022 template<typename nodeType, typename edgeType, typename propType>
00023 tlp::MinMaxProperty<nodeType, edgeType, propType>::MinMaxProperty(tlp::Graph* graph, const std::string& name, typename nodeType::RealType NodeMin,
00024     typename nodeType::RealType NodeMax, typename edgeType::RealType EdgeMin, typename edgeType::RealType EdgeMax)
00025   : AbstractProperty<nodeType, edgeType, propType>(graph, name), _nodeMin(NodeMin), _nodeMax(NodeMax), _edgeMin(EdgeMin), _edgeMax(EdgeMax), needGraphListener(false) {
00026 }
00027 
00028 template<typename nodeType, typename edgeType, typename propType>
00029 typename nodeType::RealType tlp::MinMaxProperty<nodeType, edgeType, propType>::getNodeMin(tlp::Graph* graph) {
00030   if(!graph) {
00031     graph = this->propType::graph;
00032   }
00033 
00034   unsigned int graphID = graph->getId();
00035   MINMAX_MAP(nodeType)::const_iterator it = minMaxNode.find(graphID);
00036 
00037   if (it == minMaxNode.end())
00038     return computeMinMaxNode(graph).first;
00039 
00040   return it->second.first;
00041 }
00042 
00043 template<typename nodeType, typename edgeType, typename propType>
00044 typename nodeType::RealType tlp::MinMaxProperty<nodeType, edgeType, propType>::getNodeMax(tlp::Graph* graph) {
00045   if(!graph) {
00046     graph = this->propType::graph;
00047   }
00048 
00049   unsigned int graphID = graph->getId();
00050   MINMAX_MAP(nodeType)::const_iterator it = minMaxNode.find(graphID);
00051 
00052   if (it == minMaxNode.end())
00053     return computeMinMaxNode(graph).second;
00054 
00055   return it->second.second;
00056 }
00057 
00058 template<typename nodeType, typename edgeType, typename propType>
00059 typename edgeType::RealType tlp::MinMaxProperty<nodeType, edgeType, propType>::getEdgeMin(tlp::Graph* graph) {
00060   if(!graph) {
00061     graph = this->propType::graph;
00062   }
00063 
00064   unsigned int graphID = graph->getId();
00065   MINMAX_MAP(edgeType)::const_iterator it = minMaxEdge.find(graphID);
00066 
00067   if (it == minMaxEdge.end())
00068     return computeMinMaxEdge(graph).first;
00069 
00070   return it->second.first;
00071 }
00072 
00073 template<typename nodeType, typename edgeType, typename propType>
00074 typename edgeType::RealType tlp::MinMaxProperty<nodeType, edgeType, propType>::getEdgeMax(tlp::Graph* graph) {
00075   if(!graph) {
00076     graph = this->propType::graph;
00077   }
00078 
00079   unsigned int graphID = graph->getId();
00080   MINMAX_MAP(edgeType)::const_iterator it = minMaxEdge.find(graphID);
00081 
00082   if (it == minMaxEdge.end())
00083     return computeMinMaxEdge(graph).second;
00084 
00085   return it->second.second;
00086 }
00087 
00088 template<typename nodeType, typename edgeType, typename propType>
00089 MINMAX_PAIR(nodeType) tlp::MinMaxProperty<nodeType, edgeType, propType>::computeMinMaxNode(Graph* graph) {
00090   if(!graph) {
00091     graph = this->propType::graph;
00092   }
00093 
00094   typename nodeType::RealType maxN2 = _nodeMin, minN2 = _nodeMax;
00095 
00096   if (AbstractProperty<nodeType,edgeType,propType>::numberOfNonDefaultValuatedNodes() == 0)
00097     maxN2 = minN2 = AbstractProperty<nodeType,edgeType,propType>::nodeDefaultValue;
00098   else {
00099     Iterator<node>* nodeIterator = graph->getNodes();
00100 
00101     while (nodeIterator->hasNext()) {
00102       node n=nodeIterator->next();
00103       typename nodeType::RealType tmp = this->getNodeValue(n);
00104 
00105       if (tmp > maxN2) {
00106         maxN2 = tmp;
00107       }
00108 
00109       if (tmp < minN2) {
00110         minN2 = tmp;
00111       }
00112     }
00113 
00114     delete nodeIterator;
00115 
00116     // be careful to empty graph
00117     if (maxN2 < minN2)
00118       minN2 = maxN2;
00119   }
00120 
00121   unsigned int sgi = graph->getId();
00122 
00123   // graph observation is now delayed
00124   // until we need to do some minmax computation
00125   // this will minimize the graph loading
00126   if (minMaxNode.find(sgi) == minMaxNode.end() &&
00127       minMaxEdge.find(sgi) == minMaxEdge.end()) {
00128     // launch graph hierarchy observation
00129     graph->addListener(this);
00130   }
00131 
00132   MINMAX_PAIR(nodeType) minmax(minN2, maxN2);
00133   return minMaxNode[sgi] = minmax;
00134 }
00135 
00136 template<typename nodeType, typename edgeType, typename propType>
00137 MINMAX_PAIR(edgeType) tlp::MinMaxProperty<nodeType, edgeType, propType>::computeMinMaxEdge(Graph* graph) {
00138   typename edgeType::RealType maxE2 = _edgeMin, minE2 = _edgeMax;
00139 
00140   if (AbstractProperty<nodeType,edgeType,propType>::numberOfNonDefaultValuatedEdges() == 0)
00141     maxE2 = minE2 = AbstractProperty<nodeType,edgeType,propType>::edgeDefaultValue;
00142   else {
00143     Iterator<edge>* edgeIterator = graph->getEdges();
00144 
00145     while (edgeIterator->hasNext()) {
00146       edge ite=edgeIterator->next();
00147       typename edgeType::RealType tmp = this->getEdgeValue(ite);
00148 
00149       if (tmp>maxE2)
00150         maxE2 = tmp;
00151 
00152       if (tmp<minE2)
00153         minE2 = tmp;
00154     }
00155 
00156     delete edgeIterator;
00157 
00158     // be careful to no edges graph
00159     if (maxE2 < minE2)
00160       minE2 = maxE2;
00161   }
00162 
00163   unsigned int sgi = graph->getId();
00164 
00165   // graph observation is now delayed
00166   // until we need to do some minmax computation
00167   // this will minimize the graph loading time
00168   if (minMaxNode.find(sgi) == minMaxNode.end() &&
00169       minMaxEdge.find(sgi) == minMaxEdge.end()) {
00170     // launch graph hierarchy observation
00171     graph->addListener(this);
00172   }
00173 
00174   MINMAX_PAIR(edgeType) minmax(minE2, maxE2);
00175   return minMaxEdge[sgi] = minmax;
00176 }
00177 
00178 template<typename nodeType, typename edgeType, typename propType>
00179 void tlp::MinMaxProperty<nodeType, edgeType, propType>::removeListenersAndClearNodeMap() {
00180   // we need to clear one of our map
00181   // this will invalidate some minmax computations
00182   // so the graphs corresponding to these cleared minmax computations
00183   // may not have to be longer observed if they have no validated
00184   // minmax computation in the other map
00185 
00186   // loop to remove unneeded graph observation
00187   // it is the case if minmax computation
00188   //
00189   MINMAX_MAP(nodeType)::const_iterator it = minMaxNode.begin();
00190   MINMAX_MAP(nodeType)::const_iterator ite = minMaxNode.end();
00191 
00192   for(; it != ite; ++it) {
00193     unsigned int gi = it->first;
00194     MINMAX_MAP(edgeType)::const_iterator itg = minMaxEdge.find(gi);
00195 
00196     if (itg == minMaxEdge.end()) {
00197       // no computation in the other map
00198       // we can stop observing the current graph
00199       Graph* g =
00200         (propType::graph->getId() == gi) ?
00201         (needGraphListener ? NULL : propType::graph) :
00202           propType::graph->getDescendantGraph(gi);
00203 
00204       if (g)
00205         g->removeListener(this);
00206     }
00207   }
00208 
00209   // finally clear the map
00210   minMaxNode.clear();
00211 }
00212 
00213 template<typename nodeType, typename edgeType, typename propType>
00214 void tlp::MinMaxProperty<nodeType, edgeType, propType>::removeListenersAndClearEdgeMap() {
00215   // we need to clear one of our map
00216   // this will invalidate some minmax computations
00217   // so the graphs corresponding to these cleared minmax computations
00218   // may not have to be longer observed if they have no validated
00219   // minmax computation in the other map
00220 
00221   // loop to remove unneeded graph observation
00222   // it is the case if minmax computation
00223   //
00224   MINMAX_MAP(edgeType)::const_iterator it = minMaxEdge.begin();
00225   MINMAX_MAP(edgeType)::const_iterator ite = minMaxEdge.end();
00226 
00227   for(; it != ite; ++it) {
00228     unsigned int gi = it->first;
00229     MINMAX_MAP(nodeType)::const_iterator itg = minMaxNode.find(gi);
00230 
00231     if (itg == minMaxNode.end()) {
00232       // no computation in the other map
00233       // we can stop observing the current graph
00234       Graph* g =
00235         (propType::graph->getId() == gi) ?
00236         (needGraphListener ? NULL : propType::graph) :
00237           propType::graph->getDescendantGraph(gi);
00238 
00239       if (g)
00240         g->removeListener(this);
00241     }
00242   }
00243 
00244   // finally clear the map
00245   minMaxEdge.clear();
00246 }
00247 
00248 template<typename nodeType, typename edgeType, typename propType>
00249 void tlp::MinMaxProperty<nodeType, edgeType, propType>::updateNodeValue(tlp::node n, typename nodeType::RealType newValue) {
00250   MINMAX_MAP(nodeType)::const_iterator it = minMaxNode.begin();
00251 
00252   if (it != minMaxNode.end()) {
00253     typename nodeType::RealType oldV = this->getNodeValue(n);
00254 
00255     if (newValue != oldV) {
00256       // loop on subgraph min/max
00257       for(; it != minMaxNode.end(); ++it) {
00258         // if min/max is ok for the current subgraph
00259         // check if min or max has to be updated
00260         typename nodeType::RealType minV = it->second.first;
00261         typename nodeType::RealType maxV = it->second.second;
00262 
00263         // check if min or max has to be updated
00264         if ((newValue < minV) || (newValue > maxV) || (oldV == minV) || (oldV == maxV)) {
00265           removeListenersAndClearNodeMap();
00266           break;
00267         }
00268       }
00269     }
00270   }
00271 }
00272 
00273 template<typename nodeType, typename edgeType, typename propType>
00274 void tlp::MinMaxProperty<nodeType, edgeType, propType>::updateEdgeValue(tlp::edge e, typename edgeType::RealType newValue) {
00275   MINMAX_MAP(edgeType)::const_iterator it = minMaxEdge.begin();
00276 
00277   if (it != minMaxEdge.end()) {
00278     typename edgeType::RealType oldV = this->getEdgeValue(e);
00279 
00280     if (newValue != oldV) {
00281       // loop on subgraph min/max
00282       for(; it != minMaxEdge.end(); ++it) {
00283         // if min/max is ok for the current subgraph
00284         // check if min or max has to be updated
00285         typename edgeType::RealType minV = it->second.first;
00286         typename edgeType::RealType maxV = it->second.second;
00287 
00288         // check if min or max has to be updated
00289         if ((newValue < minV) || (newValue > maxV) || (oldV == minV) || (oldV == maxV)) {
00290           removeListenersAndClearEdgeMap();
00291           break;
00292         }
00293       }
00294     }
00295   }
00296 }
00297 
00298 template<typename nodeType, typename edgeType, typename propType>
00299 void tlp::MinMaxProperty<nodeType, edgeType, propType>::updateAllNodesValues(typename nodeType::RealType newValue) {
00300   MINMAX_MAP(nodeType)::const_iterator it = minMaxNode.begin();
00301   // loop on subgraph min/max
00302   MINMAX_PAIR(nodeType) minmax(newValue, newValue);
00303 
00304   for(; it != minMaxNode.end(); ++it) {
00305     unsigned int gid = it->first;
00306     minMaxNode[gid] = minmax;
00307   }
00308 }
00309 
00310 template<typename nodeType, typename edgeType, typename propType>
00311 void tlp::MinMaxProperty<nodeType, edgeType, propType>::updateAllEdgesValues(typename edgeType::RealType newValue) {
00312   MINMAX_MAP(edgeType)::const_iterator it = minMaxEdge.begin();
00313   // loop on subgraph min/max
00314   MINMAX_PAIR(edgeType) minmax(newValue, newValue);
00315 
00316   for(; it != minMaxEdge.end(); ++it) {
00317     unsigned int gid = it->first;
00318     minMaxEdge[gid] = minmax;
00319   }
00320 }
00321 
00322 template<typename nodeType, typename edgeType, typename propType>
00323 void tlp::MinMaxProperty<nodeType, edgeType, propType>::treatEvent(const tlp::Event& ev) {
00324   const GraphEvent* graphEvent = dynamic_cast<const tlp::GraphEvent*>(&ev);
00325 
00326   if (graphEvent) {
00327     tlp::Graph* graph = graphEvent->getGraph();
00328 
00329     switch(graphEvent->getType()) {
00330     case GraphEvent::TLP_ADD_NODE:
00331       removeListenersAndClearNodeMap();
00332       break;
00333 
00334     case GraphEvent::TLP_DEL_NODE: {
00335       unsigned int sgi = graph->getId();
00336       MINMAX_MAP(nodeType)::iterator it = minMaxNode.find(sgi);
00337 
00338       if (it != minMaxNode.end()) {
00339         typename nodeType::RealType oldV =
00340           this->getNodeValue(graphEvent->getNode());
00341 
00342         // check if min or max has to be updated
00343         if ((oldV == it->second.first) || (oldV == it->second.second)) {
00344           minMaxNode.erase(it);
00345 
00346           if ((minMaxEdge.find(sgi) == minMaxEdge.end()) &&
00347               (!needGraphListener || (graph != propType::graph)))
00348             // graph observation is no longer needed
00349             graph->removeListener(this);
00350         }
00351       }
00352 
00353       break;
00354     }
00355 
00356     case GraphEvent::TLP_ADD_EDGE:
00357       removeListenersAndClearEdgeMap();
00358       break;
00359 
00360     case GraphEvent::TLP_DEL_EDGE: {
00361       unsigned int sgi = graph->getId();
00362       MINMAX_MAP(edgeType)::iterator it = minMaxEdge.find(sgi);
00363 
00364       if (it != minMaxEdge.end()) {
00365         typename edgeType::RealType oldV =
00366           this->getEdgeValue(graphEvent->getEdge());
00367 
00368         // check if min or max has to be updated
00369         if ((oldV == it->second.first) || (oldV == it->second.second)) {
00370           minMaxEdge.erase(it);
00371 
00372           if ((minMaxNode.find(sgi) == minMaxNode.end()) &&
00373               (!needGraphListener || (graph != propType::graph)))
00374             // graph observation is no longer needed
00375             graph->removeListener(this);
00376         }
00377       }
00378 
00379       break;
00380     }
00381 
00382     default:
00383       // we don't care about the rest
00384       break;
00385     }
00386   }
00387 }
 All Classes Files Functions Variables Enumerations Enumerator Properties