File: GraphRenderer.h

package info (click to toggle)
mysql-query-browser 1.2.5beta-3
  • links: PTS
  • area: main
  • in suites: etch, etch-m68k
  • size: 63,792 kB
  • ctags: 46,485
  • sloc: pascal: 249,299; ansic: 80,111; cpp: 72,467; sh: 25,271; objc: 20,015; yacc: 10,755; java: 9,917; xml: 4,580; php: 2,806; python: 1,566; sql: 1,563; makefile: 1,452; perl: 3
file content (224 lines) | stat: -rw-r--r-- 6,442 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
#ifndef __GRAPHRENDERER_H__
#define __GRAPHRENDERER_H__

#include <math.h>
#include <list>
#include <algorithm>
#include <set>
#include <functional>

class GraphNode
{
  double _left, _top, _width, _height;
  double _newleft, _newtop;
  bool _visited, _focus, _movable;

public:

  enum Coord { CX, CY };

  GraphNode(const GraphNode& n) : _left(n._left), _top(n._top), _width(n._width), _height(n._height), 
    _newleft(n._newleft), _newtop(n._newtop), _visited(n._visited), _focus(n._focus), _movable(n._movable) {}
  GraphNode(double l, double t, double w = 50., double h = 50.) : _left(l), _top(t), _width(w), _height(h), _newleft(l), _newtop(t),
    _visited(false), _focus(false), _movable(true) {}

  double centerx() const { return _left + _width/2.; }
  double centery() const { return _top + _height/2.; }

  double left() const { return _left; }
  double top() const { return _top; }
  double width() const { return _width; }
  double height() const { return _height; }

  void setnewleft(double l) { _newleft = l; }
  void setnewtop(double t) { _newtop = t; }

  double newleft() const { return _newleft; }
  double newtop() const { return _newtop; }

  double coord(Coord c) const { return c == CX ? _left : _top; }
  
  void apply() { _left= _newleft; _top= _newtop; }

  void set_visited(bool v) { _visited= v; }
  bool is_visisted() const { return _visited; }

  void set_focus(bool f) { _focus= f; }
  bool is_focus() const { return _focus; }

  void set_movable(bool m) { _movable= m; }
  bool is_movable() const { return _movable; }

  friend bool operator == (const GraphNode& n1, const GraphNode& n2);
  static double distance(const GraphNode& n1, const GraphNode& n2);
};

class GraphEdge
{
  GraphNode& _n1;
  GraphNode& _n2;
  bool _special;  // flag to show that the node was added to concatenate graph parts

public:

  GraphEdge(GraphNode& n1, GraphNode &n2) : _n1(n1), _n2(n2), _special(false) {}
  GraphEdge(GraphNode& n1, GraphNode &n2, bool special) : _n1(n1), _n2(n2), _special(special) {}

  GraphEdge& operator = (const GraphEdge& other) { this->_n1= other._n1; this->_n2= other._n2; this->_special= other._special; return *this; }

  bool contains(const GraphNode& n) const { return (n == _n1) || (n == _n2); }
  GraphNode& get_first() const { return _n1; }
  GraphNode& get_second() const { return _n2; }
  GraphNode& get_other(const GraphNode& n) const { return (n == _n1) ? _n2 : _n1; }
  double get_length() const { return sqrt(_n1.centerx()*_n2.centerx() + _n1.centery()*_n2.centery()); }

  bool is_special() const { return _special; }
};

template<class V, int N= 10, int M= 10>
class SequenceStats
{
  int _count;
  V _seq[N+M];

public:
  SequenceStats();
  ~SequenceStats() {}

  void add(V v);
  bool is_steady() const;  // do the last N values fit into the range formed by previous M values
                           // in other words - did the sequence become steady
};

template<class V, int N, int M> SequenceStats<V, N, M>::SequenceStats()
{
  _count= 0;
  for(int i = 0; i < N+M; i++) 
  {
    _seq[i]= 0;
  }
}

template<class V, int N, int M> void SequenceStats<V, N, M>::add(V v)
{
  for(int i = 1; i < (N+M); i++) 
  {
    _seq[i-1]= _seq[i];
  }
  _seq[N+M-1]= v;
  _count++;
}

template<class V, int N, int M> bool SequenceStats<V, N, M>::is_steady() const
{
  if(_count < (N+M))
  {
    return false;
  }
  
  V lo= _seq[0], hi= _seq[0];

  for(int i = 1; i < N; i++) 
  {
    if(_seq[i] < lo)
    {
      lo= _seq[i];
    }
    else if(_seq[i] > hi)
    {
      hi= _seq[i];
    }
  }

  for(int i= N; i < M; i++)
  {
    if(_seq[i] < lo)
    {
      return false;
    }
    if(_seq[i] > hi)
    {
      return false;
    }
  }

  return true;
}

class GraphRenderer
{
public:
  
  typedef std::list<GraphNode *> GraphNodeRefList;
  typedef std::list<GraphEdge> GraphEdgeList;

private:
 
  typedef std::pair<double, double> CoordPair;
  typedef std::set<CoordPair> CoordSet;
  typedef SequenceStats<double, 100, 200> LengthStats;
  typedef SequenceStats<double, 2, 100> LocStats;

  static const int K1F = 3;
  static const int K1N = 1;
  static const int K2 = 1000;
  static const int K3 = 1000;

  bool focus_recalced;
  double _density_ratio;
  
  double _length;                       // zero-resistance edge length
  double _margin, _maxw, _maxh;         // workspace edge margin, max width and height
  double _left, _top, _right, _bottom;  // enclosing rect
  double _avg_force;
  GraphEdgeList _alledges;
  GraphNodeRefList _allnodes;

  //double get_delta(const GraphNode& node, GraphNode::Coord coord);
  void get_delta(const GraphNode& node, double *xdelta, double *ydelta);

  bool has_nonmovable_nodes() const;
  bool is_focus_node(const GraphNode& node) const;
  // special edge is an edge that is not present on the model
  // but added only to connect standalone nodes
  void add_special_edge(GraphNode *n1, GraphNode *n2);  
  void mark_reachable(GraphNode& node);
  void mark_neighbours(const GraphNode& node);
  void concat_graph(GraphNode& node);

  void shorten_lengths();
  void recalc_length();
  void recalc_positions();
  void recalc_outer_rect();
  void rotate_point(double *x, double *y, double angle);
  void recalc_focus_nodes();
  void shift_to_origin();
  void scale_up();
  void scale_down();
  void scale(double xfactor, double yfactor);

public:
  GraphRenderer(double margin, double maxwidth, double maxheight);
  ~GraphRenderer();

  GraphNode* add_node(double left, double top, double right, double bottom);
  void add_edge(GraphNode *, GraphNode *);

  const GraphNodeRefList& get_all_nodes() const { return _allnodes; }
  GraphNodeRefList& get_all_nodes() { return _allnodes; }
  const GraphEdgeList& get_all_edges() const { return _alledges; }

  void move(double dx, double dy);
  void recalc();
  void rotate();
  void get_outer_rect(double *left, double *top, double *right, double *bottom);
  bool is_steady() const { return (_avg_force < 2) && (_avg_force >= 0) && !has_intersections(); }
  bool has_intersections() const;

  // stats
  double get_density_ratio() const { return _density_ratio; }
  double get_length() const { return _length; }
  double get_avg_force() const { return _avg_force; }
};

#endif