Tulip
4.6.0
Better Visualization Through Research
|
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 }