QElectroTech  0.70
conductorsegment.cpp
Go to the documentation of this file.
1 /*
2  Copyright 2006-2019 The QElectroTech Team
3  This file is part of QElectroTech.
4 
5  QElectroTech is free software: you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation, either version 2 of the License, or
8  (at your option) any later version.
9 
10  QElectroTech is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  GNU General Public License for more details.
14 
15  You should have received a copy of the GNU General Public License
16  along with QElectroTech. If not, see <http://www.gnu.org/licenses/>.
17 */
18 #include "conductorsegment.h"
19 #include <QDebug>
20 
29  const QPointF &p1,
30  const QPointF &p2,
31  ConductorSegment *cs1,
32  ConductorSegment *cs2
33 ) :
34  point1(p1),
35  point2(p2)
36 {
37  setPreviousSegment(cs1);
38  setNextSegment(cs2);
39 }
40 
47 }
48 
57 bool ConductorSegment::canMove1stPointX(const qreal &asked_dx, qreal &possible_dx) const {
58 
59  Q_ASSERT_X(isVertical(), "ConductorSegment::canMove1stPointX", "segment non vertical");
60 
62  if (isStatic()) {
63  possible_dx = 0.0;
64  return(false);
65  }
66  // a ce stade, on a forcement un segment precedent
67 
70  possible_dx = asked_dx;
71  return(true);
72  }
73  // a ce stade, le segment precedent est forcement statique
74 
77  if (previous_segment -> isVertical()) {
78  possible_dx = asked_dx;
79  return(true);
80  }
81  // a ce stade, le segment precedent est forcement horizontal
82 
83  // recupere quelques donnees
84  qreal prev_segment_first_x = previous_segment -> point1.x();
85  qreal first_x = point1.x();
86 
89  if (previous_segment -> length() > 0.0) {
90  if (first_x + asked_dx < prev_segment_first_x + 12.0) {
91  possible_dx = -first_x + prev_segment_first_x + 12.0;
92  return(false);
93  } else {
94  possible_dx = asked_dx;
95  return(true);
96  }
97  } else {
98  if (first_x + asked_dx >= prev_segment_first_x - 12.0) {
99  possible_dx = prev_segment_first_x - 12.0 - first_x;
100  return(false);
101  } else {
102  possible_dx = asked_dx;
103  return(true);
104  }
105  }
106 }
107 
116 bool ConductorSegment::canMove2ndPointX(const qreal &asked_dx, qreal &possible_dx) const {
117 
118  Q_ASSERT_X(isVertical(), "ConductorSegment::canMove2ndPointX", "segment non vertical");
119 
121  if (isStatic()) {
122  possible_dx = 0.0;
123  return(false);
124  }
125  // a ce stade, on a forcement un segment suivant
126 
128  if (next_segment -> hasNextSegment()) {
129  possible_dx = asked_dx;
130  return(true);
131  }
132  // a ce stade, le segment suivant est forcement statique
133 
136  if (next_segment -> isVertical()) {
137  possible_dx = asked_dx;
138  return(true);
139  }
140  // a ce stade, le segment suivant est forcement horizontal
141 
142  // recupere quelques donnees
143  qreal next_segment_second_x = next_segment -> point2.x();
144  qreal second_x = point2.x();
145 
148  if (next_segment -> length() < 0.0) {
149  if (second_x + asked_dx < next_segment_second_x + 12.0) {
150  possible_dx = -second_x + next_segment_second_x + 12.0;
151  return(false);
152  } else {
153  possible_dx = asked_dx;
154  return(true);
155  }
156  } else {
157  if (second_x + asked_dx >= next_segment_second_x - 12.0) {
158  possible_dx = next_segment_second_x - 12.0 - second_x;
159  return(false);
160  } else {
161  possible_dx = asked_dx;
162  return(true);
163  }
164  }
165 }
166 
175 bool ConductorSegment::canMove1stPointY(const qreal &asked_dy, qreal &possible_dy) const {
176 
177  Q_ASSERT_X(isHorizontal(), "ConductorSegment::canMove1stPointY", "segment non horizontal");
178 
180  if (isStatic()) {
181  possible_dy = 0.0;
182  return(false);
183  }
184  // a ce stade, on a forcement un segment precedent
185 
188  possible_dy = asked_dy;
189  return(true);
190  }
191  // a ce stade, le segment precedent est forcement statique
192 
195  if (previous_segment -> isHorizontal()) {
196  possible_dy = asked_dy;
197  return(true);
198  }
199  // a ce stade, le segment precedent est forcement vertical
200 
201  // recupere quelques donnees
202  qreal prev_segment_first_y = previous_segment -> point1.y();
203  qreal first_y = point1.y();
204 
207  if (previous_segment -> length() > 0.0) {
208  if (first_y + asked_dy < prev_segment_first_y + 12.0) {
209  possible_dy = -first_y + prev_segment_first_y + 12.0;
210  return(false);
211  } else {
212  possible_dy = asked_dy;
213  return(true);
214  }
215  } else {
216  if (first_y + asked_dy >= prev_segment_first_y - 12.0) {
217  possible_dy = prev_segment_first_y - 12.0 - first_y;
218  return(false);
219  } else {
220  possible_dy = asked_dy;
221  return(true);
222  }
223  }
224 }
225 
234 bool ConductorSegment::canMove2ndPointY(const qreal &asked_dy, qreal &possible_dy) const {
235 
236  Q_ASSERT_X(isHorizontal(), "ConductorSegment::canMove2ndPointY", "segment non horizontal");
237 
239  if (isStatic()) {
240  possible_dy = 0.0;
241  return(false);
242  }
243  // a ce stade, on a forcement un segment suivant
244 
246  if (next_segment -> hasNextSegment()) {
247  possible_dy = asked_dy;
248  return(true);
249  }
250  // a ce stade, le segment suivant est forcement statique
251 
254  if (next_segment -> isHorizontal()) {
255  possible_dy = asked_dy;
256  return(true);
257  }
258  // a ce stade, le segment suivant est forcement vertical
259 
260  // recupere quelques donnees
261  qreal next_segment_second_y = next_segment -> point2.y();
262  qreal second_y = point2.y();
263 
266  if (next_segment -> length() < 0.0) {
267  if (second_y + asked_dy < next_segment_second_y + 12.0) {
268  possible_dy = -second_y + next_segment_second_y + 12.0;
269  return(false);
270  } else {
271  possible_dy = asked_dy;
272  return(true);
273  }
274  } else {
275  if (second_y + asked_dy >= next_segment_second_y - 12.0) {
276  possible_dy = next_segment_second_y - 12.0 - second_y;
277  return(false);
278  } else {
279  possible_dy = asked_dy;
280  return(true);
281  }
282  }
283 }
284 
289 void ConductorSegment::moveX(const qreal &dx) {
290  if (isHorizontal()) return;
291  Q_ASSERT_X(isVertical(), "ConductorSegment::moveX", "segment non vertical");
292 
293  bool has_prev_segment = hasPreviousSegment();
294  bool has_next_segment = hasNextSegment();
295 
296  if (isStatic()) return;
297 
298  // determine si le mouvement demande doit etre limite et, le cas echeant, a quelle valeur il faut le limiter
299  qreal real_dx_for_1st_point = 0.0;
300  qreal real_dx_for_2nd_point = 0.0;
301  canMove1stPointX(dx, real_dx_for_1st_point);
302  canMove2ndPointX(dx, real_dx_for_2nd_point);
303 
304  qreal final_movement = (dx <= 0.0) ? qMax(real_dx_for_1st_point, real_dx_for_2nd_point) : qMin(real_dx_for_1st_point, real_dx_for_2nd_point);
305 
306  // applique le mouvement au premier point
307  if (has_prev_segment) {
308  point1.rx() += final_movement;
309  if (previous_segment -> isFirstSegment()) {
310  new ConductorSegment(
312  point1,
314  this
315  );
317  }
318 
319  // applique le mouvement au second point
320  if (has_next_segment) {
321  point2.rx() += final_movement;
322  if (next_segment -> isLastSegment()) {
323  new ConductorSegment(
324  point2,
325  next_segment -> point1,
326  this,
328  );
329  } else next_segment -> setFirstPoint(point2);
330  }
331 }
332 
337 void ConductorSegment::moveY(const qreal &dy) {
338  if (isVertical()) return;
339  Q_ASSERT_X(isHorizontal(), "ConductorSegment::moveY", "segment non horizontal");
340 
341  bool has_prev_segment = hasPreviousSegment();
342  bool has_next_segment = hasNextSegment();
343 
344  if (isStatic()) return;
345 
346  // determine si le mouvement demande doit etre limite et, le cas echeant, a quelle valeur il faut le limiter
347  qreal real_dy_for_1st_point = 0.0;
348  qreal real_dy_for_2nd_point = 0.0;
349  canMove1stPointY(dy, real_dy_for_1st_point);
350  canMove2ndPointY(dy, real_dy_for_2nd_point);
351 
352  qreal final_movement = (dy <= 0.0) ? qMax(real_dy_for_1st_point, real_dy_for_2nd_point) : qMin(real_dy_for_1st_point, real_dy_for_2nd_point);
353 
354  // applique le mouvement au premier point
355  if (has_prev_segment) {
356  point1.ry() += final_movement;
357  if (previous_segment -> isFirstSegment()) {
358  new ConductorSegment(
360  point1,
362  this
363  );
365  }
366 
367  // applique le mouvement au second point
368  if (has_next_segment) {
369  point2.ry() += final_movement;
370  if (next_segment -> isLastSegment()) {
371  new ConductorSegment(
372  point2,
373  next_segment -> point1,
374  this,
376  );
377  } else next_segment -> setFirstPoint(point2);
378  }
379 }
380 
386  previous_segment = ps;
387  if (hasPreviousSegment()) {
388  if (previousSegment() -> nextSegment() != this) previousSegment() -> setNextSegment(this);
389  }
390 }
391 
397  next_segment = ns;
398  if (hasNextSegment()) {
399  if (nextSegment() -> previousSegment() != this) nextSegment() -> setPreviousSegment(this);
400  }
401 }
402 
405  return(isFirstSegment() || isLastSegment());
406 }
407 
410  return(!hasPreviousSegment());
411 }
412 
415  return(!hasNextSegment());
416 }
417 
422  return(previous_segment);
423 }
424 
429  return(next_segment);
430 }
431 
436  return(point1.x() == point2.x());
437 }
438 
443  return(point1.y() == point2.y());
444 }
445 
450  return(point1);
451 }
452 
457  return(point2);
458 }
459 
464 void ConductorSegment::setFirstPoint(const QPointF &p) {
465  point1 = p;
466 }
467 
472 void ConductorSegment::setSecondPoint(const QPointF &p) {
473  point2 = p;
474 }
475 
480  return(previous_segment != nullptr);
481 }
482 
487  return(next_segment != nullptr);
488 }
489 
493 QPointF ConductorSegment::middle() const {
494  return(
495  QPointF(
496  (point1.x()+ point2.x()) / 2.0,
497  (point1.y()+ point2.y()) / 2.0
498  )
499  );
500 }
501 
506  if (isHorizontal()) {
507  return(secondPoint().x() - firstPoint().x());
508  } else {
509  return(secondPoint().y() - firstPoint().y());
510  }
511 }
512 
516 }
517 
520  return(point1 == point2);
521 }
bool canMove1stPointY(const qreal &, qreal &) const
QPointF middle() const
QPointF firstPoint() const
void setSecondPoint(const QPointF &)
virtual ~ConductorSegment()
ConductorSegment * previousSegment() const
void setFirstPoint(const QPointF &)
bool isHorizontal() const
bool hasPreviousSegment() const
bool hasNextSegment() const
void setPreviousSegment(ConductorSegment *)
bool canMove1stPointX(const qreal &, qreal &) const
ConductorSegmentType
Known kinds of conductor segments.
Definition: qet.h:86
bool canMove2ndPointX(const qreal &, qreal &) const
qreal length() const
bool isVertical() const
bool canMove2ndPointY(const qreal &, qreal &) const
bool isFirstSegment() const
void setNextSegment(ConductorSegment *)
ConductorSegment * previous_segment
Vertical segment.
Definition: qet.h:88
ConductorSegment(const QPointF &, const QPointF &, ConductorSegment *=nullptr, ConductorSegment *=nullptr)
void moveY(const qreal &)
ConductorSegment * nextSegment() const
void moveX(const qreal &)
ConductorSegment * next_segment
QET::ConductorSegmentType type() const
Horizontal segment.
Definition: qet.h:87
bool isLastSegment() const
QPointF secondPoint() const