My Project  0.0.16
QUCS Mapping
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
ellipsearc.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  ellipsearc.cpp
3  ----------------
4  begin : Thu Sep 9 2004
5  copyright : (C) 2004 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 "ellipsearc.h"
19 #include "filldialog.h"
20 #include "main.h"
21 
22 #include <qpushbutton.h>
23 #include <qlineedit.h>
24 #include <qcombobox.h>
25 
26 #include <math.h>
27 
28 
30 {
31  Name = "EArc ";
32  isSelected = false;
33  Pen = QPen(QColor());
34  cx = cy = x1 = x2 = y1 = y2 = Angle = ArcLen = 0;
35 }
36 
38 {
39 }
40 
41 // --------------------------------------------------------------------------
43 {
44  if(isSelected) {
45  p->Painter->setPen(QPen(QPen::darkGray,Pen.width()+5));
46  p->drawArc(cx, cy, x2, y2, Angle, ArcLen);
47  p->Painter->setPen(QPen(QPen::white, Pen.width(), Pen.style()));
48  p->drawArc(cx, cy, x2, y2, Angle, ArcLen);
49 
50  p->Painter->setPen(QPen(QPen::darkRed,2));
51  p->drawResizeRect(cx, cy+y2); // markers for changing the size
52  p->drawResizeRect(cx, cy);
53  p->drawResizeRect(cx+x2, cy+y2);
54  p->drawResizeRect(cx+x2, cy);
55  return;
56  }
57  p->Painter->setPen(Pen);
58  p->drawArc(cx, cy, x2, y2, Angle, ArcLen);
59 }
60 
61 // --------------------------------------------------------------------------
62 void EllipseArc::paintScheme(QPainter *p)
63 {
64  p->drawArc(cx, cy, x2, y2, Angle, ArcLen);
65 }
66 
67 // --------------------------------------------------------------------------
68 void EllipseArc::getCenter(int& x, int &y)
69 {
70  x = cx+(x2>>1);
71  y = cy+(y2>>1);
72 }
73 
74 // --------------------------------------------------------------------------
75 // Sets the center of the painting to x/y.
76 void EllipseArc::setCenter(int x, int y, bool relative)
77 {
78  if(relative) { cx += x; cy += y; }
79  else { cx = x-(x2>>1); cy = y-(y2>>1); }
80 }
81 
82 // --------------------------------------------------------------------------
84 {
85  return new EllipseArc();
86 }
87 
88 // --------------------------------------------------------------------------
89 Element* EllipseArc::info(QString& Name, char* &BitmapFile, bool getNewOne)
90 {
91  Name = QObject::tr("Elliptic Arc");
92  BitmapFile = (char *) "ellipsearc";
93 
94  if(getNewOne) return new EllipseArc();
95  return 0;
96 }
97 
98 // --------------------------------------------------------------------------
99 bool EllipseArc::load(const QString& s)
100 {
101  bool ok;
102  QString n;
103 
104  n = s.section(' ',1,1); // cx
105  cx = n.toInt(&ok);
106  if(!ok) return false;
107 
108  n = s.section(' ',2,2); // cy
109  cy = n.toInt(&ok);
110  if(!ok) return false;
111 
112  n = s.section(' ',3,3); // x2
113  x2 = n.toInt(&ok);
114  if(!ok) return false;
115 
116  n = s.section(' ',4,4); // y2
117  y2 = n.toInt(&ok);
118  if(!ok) return false;
119 
120  n = s.section(' ',5,5); // start angle
121  Angle = n.toInt(&ok);
122  if(!ok) return false;
123 
124  n = s.section(' ',6,6); // arc length
125  ArcLen = n.toInt(&ok);
126  if(!ok) return false;
127 
128  n = s.section(' ',7,7); // color
129  QColor co;
130  co.setNamedColor(n);
131  Pen.setColor(co);
132  if(!Pen.color().isValid()) return false;
133 
134  n = s.section(' ',8,8); // thickness
135  Pen.setWidth(n.toInt(&ok));
136  if(!ok) return false;
137 
138  n = s.section(' ',9,9); // line style
139  Pen.setStyle((Qt::PenStyle)n.toInt(&ok));
140  if(!ok) return false;
141 
142  return true;
143 }
144 
145 // --------------------------------------------------------------------------
147 {
148  QString s = Name +
149  QString::number(cx) + " " + QString::number(cy) + " " +
150  QString::number(x2) + " " + QString::number(y2) + " " +
151  QString::number(Angle) + " " + QString::number(ArcLen) + " " +
152  Pen.color().name() + " " + QString::number(Pen.width()) + " " +
153  QString::number(Pen.style());
154  return s;
155 }
156 
157 // --------------------------------------------------------------------------
159 {
160  QString s =
161  QString ("new Arc (%1, %2, %3, %4, %5, %6, "
162  "QPen (QColor (\"%7\"), %8, %8))").
163  arg(cx).arg(cy).arg(x2).arg(y2).arg(Angle).arg(ArcLen).
164  arg(Pen.color().name()).arg(Pen.width()).arg(toPenString(Pen.style()));
165  s = "Arcs.append (" + s + ");";
166  return s;
167 }
168 
169 // --------------------------------------------------------------------------
170 // Checks if the resize area was clicked.
171 bool EllipseArc::resizeTouched(float fX, float fY, float len)
172 {
173  float fCX = float(cx), fCY = float(cy);
174  float fX2 = float(cx+x2), fY2 = float(cy+y2);
175 
176  State = -1;
177  if(fX < fCX-len) return false;
178  if(fY < fCY-len) return false;
179  if(fX > fX2+len) return false;
180  if(fY > fY2+len) return false;
181 
182  State = 0;
183  if(fX < fCX+len) State = 1;
184  else if(fX <= fX2-len) { State = -1; return false; }
185  if(fY < fCY+len) State |= 2;
186  else if(fY <= fY2-len) { State = -1; return false; }
187 
188  return true;
189 }
190 
191 // --------------------------------------------------------------------------
192 // Mouse move action during resize.
193 void EllipseArc::MouseResizeMoving(int x, int y, QPainter *p)
194 {
195  paintScheme(p); // erase old painting
196  switch(State) {
197  case 0: x2 = x-cx; y2 = y-cy; // lower right corner
198  break;
199  case 1: x2 -= x-cx; cx = x; y2 = y-cy; // lower left corner
200  break;
201  case 2: x2 = x-cx; y2 -= y-cy; cy = y; // upper right corner
202  break;
203  case 3: x2 -= x-cx; cx = x; y2 -= y-cy; cy = y; // upper left corner
204  break;
205  }
206  if(x2 < 0) { State ^= 1; x2 *= -1; cx -= x2; }
207  if(y2 < 0) { State ^= 2; y2 *= -1; cy -= y2; }
208 
209  paintScheme(p); // paint new painting
210 }
211 
212 // --------------------------------------------------------------------------
213 // fx/fy are the precise coordinates, gx/gy are the coordinates set on grid.
214 // x/y are coordinates without scaling.
216  QPainter *paintScale, int fx, int fy, int gx, int gy,
217  QPainter *p, int x, int y, bool drawn)
218 {
219  switch(State) {
220  case 0 :
221  x2 = gx;
222  y2 = gy;
223  break;
224  case 1 :
225  State++;
226  x2 = gx - cx;
227  y2 = gy - cy;
228  paintScale->drawArc(cx, cy, x2, y2, 0, 16*360); // paint new painting
229  break;
230  case 2 :
231  paintScale->drawArc(cx, cy, x2, y2, 0, 16*360); // erase old painting
232  x2 = gx - cx;
233  y2 = gy - cy;
234  paintScale->drawArc(cx, cy, x2, y2, 0, 16*360); // paint new painting
235  break;
236  case 3 :
237  State++;
238  paintScale->drawArc(cx, cy, x2, y2, 0, 16*360); // erase old painting
239  if(x2 < 0) { cx += x2; x2 *= -1; }
240  if(y2 < 0) { cy += y2; y2 *= -1; }
241 
242  Angle = int(16.0*180.0/M_PI
243  * atan2(double(x2*(cy+(y2>>1) - fy)),
244  double(y2*(fx - cx-(x2>>1)))));
245  if(Angle < 0) Angle += 16*360;
246  paintScale->drawArc(cx, cy, x2, y2, Angle, 16*180); // new painting
247  break;
248  case 4 :
249  paintScale->drawArc(cx, cy, x2, y2, Angle, 16*180);// erase old painting
250  Angle = int(16.0*180.0/M_PI
251  * atan2(double(x2*(cy+(y2>>1) - fy)),
252  double(y2*(fx - cx-(x2>>1)))));
253  if(Angle < 0) Angle += 16*360;
254  paintScale->drawArc(cx, cy, x2, y2, Angle, 16*180);// paint new painting
255  break;
256  case 5 :
257  State++;
258  paintScale->drawArc(cx, cy, x2, y2, Angle, 16*180);// erase old painting
259  ArcLen = int(16.0*180.0/M_PI
260  * atan2(double(x2*(cy+(y2>>1) - fy)),
261  double(y2*(fx - cx-(x2>>1)))));
262  ArcLen -= Angle;
263  while(ArcLen < 0) ArcLen += 16*360;
264  paintScale->drawArc(cx, cy, x2, y2, Angle, ArcLen);// paint new painting
265  break;
266  case 6 :
267  paintScale->drawArc(cx, cy, x2, y2, Angle, ArcLen);// erase old painting
268  ArcLen = int(16.0*180.0/M_PI
269  * atan2(double(x2*(cy+(y2>>1) - fy)),
270  double(y2*(fx - cx-(x2>>1)))));
271  ArcLen -= Angle;
272  while(ArcLen <= 32) ArcLen += 16*360;
273  paintScale->drawArc(cx, cy, x2, y2, Angle, ArcLen);// paint new painting
274  break;
275  }
276 
277 
278  p->setPen(Qt::SolidLine);
279  if(drawn)
280  p->drawArc(x1+13, y1, 18, 12, 16*45, 16*200); // erase old cursor symbol
281 
282  x1 = x;
283  y1 = y;
284  p->drawArc(x1+13, y1, 18, 12, 16*45, 16*200); // paint new cursor symbol
285 }
286 
287 // --------------------------------------------------------------------------
289 {
290  State++;
291  switch(State) {
292  case 1 :
293  cx = x2;
294  cy = y2; // first corner is determined
295  x2 = y2 = Angle = ArcLen = 0;
296  break;
297  case 7 :
298  State = 0;
299  return true; // painting is ready
300  }
301  return false;
302 }
303 
304 // --------------------------------------------------------------------------
305 // Checks if the coordinates x/y point to the painting.
306 bool EllipseArc::getSelected(float fX, float fY, float w)
307 {
308  float fX2 = float(x2)/2.0;
309  float fY2 = float(y2)/2.0;
310  fX -= float(cx) + fX2;
311  fY -= float(cy) + fY2;
312 
313  int Phase =
314  int(16.0*180.0/M_PI *
315  atan2(-double(x2)*double(fY), double(y2)*double(fX)));
316  Phase -= Angle;
317  while(Phase < 0) Phase += 16*360;
318 
319  if(Phase > ArcLen)
320  return false;
321 
322  float a1 = fX / (fX2 - w); a1 *= a1;
323  float a2 = fX / (fX2 + w); a2 *= a2;
324  float b1 = fY / (fY2 - w); b1 *= b1;
325  float b2 = fY / (fY2 + w); b2 *= b2;
326 
327  if(a1+b1 < 1.0) return false;
328  if(a2+b2 > 1.0) return false;
329 
330  return true;
331 }
332 
333 // --------------------------------------------------------------------------
334 // Rotates around the center.
336 {
337  cy += (y2-x2) >> 1;
338  cx += (x2-y2) >> 1;
339  int tmp = x2;
340  x2 = y2;
341  y2 = tmp;
342 
343  Angle += 16*90;
344  if(Angle >= 16*360) Angle -= 16*360;
345 }
346 
347 // --------------------------------------------------------------------------
348 // Mirrors about center line.
350 {
351  Angle += ArcLen;
352  if(Angle >= 16*360) Angle -= 16*360;
353 
354  if(Angle != 0) Angle = 16*360 - Angle;
355 }
356 
357 // --------------------------------------------------------------------------
358 // Mirrors about center line.
360 {
361  Angle += ArcLen;
362  if(Angle >= 16*360) Angle -= 16*360;
363 
364  if(Angle <= 16*180) Angle = 16*180 - Angle;
365  else Angle = 16*540 - Angle;
366 }
367 
368 // --------------------------------------------------------------------------
369 // Calls the property dialog for the painting and changes them accordingly.
370 // If there were changes, it returns 'true'.
372 {
373  bool changed = false;
374 
375  FillDialog *d = new FillDialog(QObject::tr("Edit Arc Properties"), false);
376  d->ColorButt->setPaletteBackgroundColor(Pen.color());
377  d->LineWidth->setText(QString::number(Pen.width()));
378  d->StyleBox->setCurrentItem(Pen.style()-1);
379 
380  if(d->exec() == QDialog::Rejected) {
381  delete d;
382  return false;
383  }
384 
385  if(Pen.color() != d->ColorButt->paletteBackgroundColor()) {
386  Pen.setColor(d->ColorButt->paletteBackgroundColor());
387  changed = true;
388  }
389  if(Pen.width() != d->LineWidth->text().toUInt()) {
390  Pen.setWidth(d->LineWidth->text().toUInt());
391  changed = true;
392  }
393  if(Pen.style() != (Qt::PenStyle)(d->StyleBox->currentItem()+1)) {
394  Pen.setStyle((Qt::PenStyle)(d->StyleBox->currentItem()+1));
395  changed = true;
396  }
397 
398  delete d;
399  return changed;
400 }