My Project  0.0.16
QUCS Mapping
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
graph.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  graph.cpp - description
3  -------------------
4  begin : Thu Oct 2 2003
5  copyright : (C) 2003 by Michael Margraf
6  email : michael.margraf@alumni.tu-berlin.de
7  ***************************************************************************/
8 
9 /***************************************************************************
10  * *
11  * This program is free software; you can redistribute it and/or modify *
12  * it under the terms of the GNU General Public License as published by *
13  * the Free Software Foundation; either version 2 of the License, or *
14  * (at your option) any later version. *
15  * *
16  ***************************************************************************/
17 
18 #include "graph.h"
19 
20 #include <math.h>
21 #include <stdlib.h>
22 
23 
24 Graph::Graph(const QString& _Line)
25 {
26  Type = isGraph;
27 
28  Var = _Line;
29  countY = 0; // no points in graph
30  Thick = numMode = 0;
31  Color = 0x0000ff; // blue
32  Style = 0; // solid line
33  Precision = 3;
34  isSelected = false;
35  yAxisNo = 0; // left y axis
36 
37  ScrPoints = 0;
38  cPointsY = 0;
39 
40  Markers.setAutoDelete(true);
41  cPointsX.setAutoDelete(true);
42 }
43 
45 {
46  if(ScrPoints != 0)
47  free(ScrPoints);
48  if(cPointsY != 0)
49  delete[] cPointsY;
50 }
51 
52 // ---------------------------------------------------------------------
53 void Graph::paint(ViewPainter *p, int x0, int y0)
54 {
55  if(ScrPoints == 0)
56  return;
57 
58  if(isSelected) {
59  p->Painter->setPen(QPen(QPen::darkGray,Thick*p->PrintScale+4));
60  paintLines(p, x0, y0);
61 
62  p->Painter->setPen(QPen(QPen::white, Thick*p->PrintScale, Qt::SolidLine));
63  paintLines(p, x0, y0);
64  return;
65  }
66 
67  // **** not selected ****
68  p->Painter->setPen(QPen(QColor(Color), Thick*p->PrintScale, Qt::SolidLine));
69  paintLines(p, x0, y0);
70 }
71 
72 // ---------------------------------------------------------------------
73 void Graph::paintLines(ViewPainter *p, int x0, int y0)
74 {
75  switch(Style) {
76  case GRAPHSTYLE_STAR:
77  p->drawStarSymbols(x0, y0, ScrPoints);
78  break;
79  case GRAPHSTYLE_CIRCLE:
80  p->drawCircleSymbols(x0, y0, ScrPoints);
81  break;
82  case GRAPHSTYLE_ARROW:
83  p->drawArrowSymbols(x0, y0, ScrPoints);
84  break;
85  default:
86  p->drawLines(x0, y0, ScrPoints);
87  }
88 }
89 
90 // ---------------------------------------------------------------------
91 QString Graph::save()
92 {
93  QString s = "\t<\""+Var+"\" "+Color.name()+
94  " "+QString::number(Thick)+" "+QString::number(Precision)+
95  " "+QString::number(numMode)+" "+QString::number(Style)+
96  " "+QString::number(yAxisNo)+">";
97 
98  for(Marker *pm=Markers.first(); pm != 0; pm=Markers.next())
99  s += "\n\t "+pm->save();
100 
101  return s;
102 }
103 
104 // ---------------------------------------------------------------------
105 bool Graph::load(const QString& _s)
106 {
107  bool ok;
108  QString s = _s;
109 
110  if(s.at(0) != '<') return false;
111  if(s.at(s.length()-1) != '>') return false;
112  s = s.mid(1, s.length()-2); // cut off start and end character
113 
114  Var = s.section('"',1,1); // Var
115 
116  QString n;
117  n = s.section(' ',1,1); // Color
118  Color.setNamedColor(n);
119  if(!Color.isValid()) return false;
120 
121  n = s.section(' ',2,2); // Thick
122  Thick = n.toInt(&ok);
123  if(!ok) return false;
124 
125  n = s.section(' ',3,3); // Precision
126  Precision = n.toInt(&ok);
127  if(!ok) return false;
128 
129  n = s.section(' ',4,4); // numMode
130  numMode = n.toInt(&ok);
131  if(!ok) return false;
132 
133  n = s.section(' ',5,5); // Style
134  Style = n.toInt(&ok);
135  if(!ok) return false;
136 
137  n = s.section(' ',6,6); // yAxisNo
138  if(n.isEmpty()) return true; // backward compatible
139  yAxisNo = n.toInt(&ok);
140  if(!ok) return false;
141 
142  return true;
143 }
144 
145 // -----------------------------------------------------------------------
146 // Checks if the coordinates x/y point to the graph. x/y are relative to
147 // diagram cx/cy. 5 is the precision the user must point onto the graph.
148 int Graph::getSelected(int x, int y)
149 {
150  float *pp = ScrPoints;
151  if(pp == 0) return -1;
152 
153  int A, z=0;
154  int dx, dx2, x1;
155  int dy, dy2, y1;
156 
157  int countX = cPointsX.getFirst()->count;
158  if(*pp <= STROKEEND) {
159  if(*pp <= BRANCHEND) z++;
160  pp++;
161  if(*pp <= BRANCHEND) {
162  if(*pp <= GRAPHEND) return -1; // not even one point ?
163  z++;
164  pp++;
165  if(*pp < BRANCHEND) return -1; // not even one point ?
166  }
167  }
168 
169  if(Style >= GRAPHSTYLE_STAR) {
170  // for graph symbols
171  while(*pp > GRAPHEND) {
172  if(*pp > STROKEEND) {
173  dx = x - int(*(pp++));
174  dy = y - int(*(pp++));
175 
176  if(dx < -5) continue;
177  if(dx > 5) continue;
178  if(dy < -5) continue;
179  if(dy > 5) continue;
180  return z*countX; // points on graph symbol
181  }
182  else {
183  z++; // next branch
184  pp++;
185  }
186  }
187  return -1;
188  }
189 
190  // for graph lines
191  while(*pp > GRAPHEND) {
192  while(*pp >= STROKEEND) {
193  x1 = int(*(pp++));
194  y1 = int(*(pp++));
195  dx = x - x1;
196  dy = y - y1;
197 
198  dx2 = int(*pp);
199  if(dx2 <= STROKEEND) { // end of stroke ?
200  if(dx2 <= BRANCHEND) break;
201  pp++;
202  dx2 = int(*pp); // go on as graph can also be selected between strokes
203  if(dx2 <= BRANCHEND) break;
204  }
205  if(dx < -5) { if(x < dx2-5) continue; } // point between x coordinates ?
206  else { if(x > 5) if(x > dx2+5) continue; }
207 
208  dy2 = int(*(pp+1));
209  if(dy < -5) { if(y < dy2-5) continue; } // point between y coordinates ?
210  else { if(y > 5) if(y > dy2+5) continue; }
211 
212  dx2 -= x1;
213  dy2 -= y1;
214 
215  A = dx2*dy - dx*dy2; // calculate the rectangle area spanned
216  A *= A; // avoid the need for square root
217  A -= 25*(dx2*dx2 + dy2*dy2); // substract selectable area
218 
219  if(A <= 0) return z*countX; // lies x/y onto the graph line ?
220  }
221  pp++;
222  z++;
223  }
224 
225  return -1;
226 }
227 
228 // -----------------------------------------------------------------------
229 // Creates a new graph and copies all the properties into it.
231 {
232  Graph *pg = new Graph(Var);
233 
234  pg->Color = Color;
235  pg->Thick = Thick;
236  pg->Style = Style;
237 
238  pg->Precision = Precision;
239  pg->numMode = numMode;
240  pg->yAxisNo = yAxisNo;
241 
242  for(Marker *pm = Markers.first(); pm != 0; pm = Markers.next())
243  pg->Markers.append(pm->sameNewOne(pg));
244 
245  return pg;
246 }