2006-10-27 15:47:22 +00:00
|
|
|
|
#include <QtDebug>
|
2007-01-29 20:32:38 +00:00
|
|
|
|
#include "conducer.h"
|
2007-02-14 01:08:29 +00:00
|
|
|
|
#include "conducersegment.h"
|
2006-10-27 15:47:22 +00:00
|
|
|
|
#include "element.h"
|
|
|
|
|
|
2007-01-29 20:32:38 +00:00
|
|
|
|
bool Conducer::pen_and_brush_initialized = false;
|
|
|
|
|
QPen Conducer::conducer_pen = QPen();
|
|
|
|
|
QBrush Conducer::conducer_brush = QBrush();
|
2007-01-05 14:29:08 +00:00
|
|
|
|
|
2006-10-27 15:47:22 +00:00
|
|
|
|
/**
|
|
|
|
|
Constructeur
|
|
|
|
|
@param p1 Premiere Borne auquel le conducteur est lie
|
|
|
|
|
@param p2 Seconde Borne auquel le conducteur est lie
|
|
|
|
|
@param parent Element parent du conducteur (0 par defaut)
|
|
|
|
|
@param scene QGraphicsScene auquelle appartient le conducteur
|
|
|
|
|
*/
|
2007-01-29 20:32:38 +00:00
|
|
|
|
Conducer::Conducer(Terminal *p1, Terminal* p2, Element *parent, QGraphicsScene *scene) : QGraphicsPathItem(parent, scene) {
|
2006-10-27 15:47:22 +00:00
|
|
|
|
// bornes que le conducteur relie
|
2007-01-29 20:14:26 +00:00
|
|
|
|
terminal1 = p1;
|
|
|
|
|
terminal2 = p2;
|
2006-10-27 15:47:22 +00:00
|
|
|
|
// ajout du conducteur a la liste de conducteurs de chacune des deux bornes
|
2007-01-29 20:32:38 +00:00
|
|
|
|
bool ajout_p1 = terminal1 -> addConducer(this);
|
|
|
|
|
bool ajout_p2 = terminal2 -> addConducer(this);
|
2006-10-27 15:47:22 +00:00
|
|
|
|
// en cas d'echec de l'ajout (conducteur deja existant notamment)
|
|
|
|
|
if (!ajout_p1 || !ajout_p2) return;
|
|
|
|
|
destroyed = false;
|
2007-01-05 14:29:08 +00:00
|
|
|
|
modified_path = false;
|
|
|
|
|
// attributs de dessin par defaut (communs a tous les conducteurs)
|
|
|
|
|
if (!pen_and_brush_initialized) {
|
|
|
|
|
conducer_pen.setJoinStyle(Qt::MiterJoin);
|
|
|
|
|
conducer_pen.setCapStyle(Qt::SquareCap);
|
|
|
|
|
conducer_pen.setColor(Qt::black);
|
|
|
|
|
conducer_pen.setStyle(Qt::SolidLine);
|
|
|
|
|
conducer_pen.setWidthF(1.0);
|
|
|
|
|
conducer_brush.setColor(Qt::white);
|
|
|
|
|
conducer_brush.setStyle(Qt::NoBrush);
|
|
|
|
|
pen_and_brush_initialized = true;
|
|
|
|
|
}
|
2006-10-27 15:47:22 +00:00
|
|
|
|
// calcul du rendu du conducteur
|
2007-02-14 01:08:29 +00:00
|
|
|
|
segments = NULL;
|
2007-01-29 20:32:38 +00:00
|
|
|
|
priv_calculeConducer(terminal1 -> amarrageConducer(), terminal1 -> orientation(), terminal2 -> amarrageConducer(), terminal2 -> orientation());
|
2006-11-26 21:35:05 +00:00
|
|
|
|
setFlags(QGraphicsItem::ItemIsSelectable);
|
2007-02-15 20:00:20 +00:00
|
|
|
|
setAcceptsHoverEvents(true);
|
|
|
|
|
previous_z_value = zValue();
|
2006-10-27 15:47:22 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
Met a jour la representation graphique du conducteur.
|
|
|
|
|
@param rect Rectangle a mettre a jour
|
|
|
|
|
*/
|
2007-01-29 20:32:38 +00:00
|
|
|
|
void Conducer::update(const QRectF &rect) {
|
2007-01-05 14:29:08 +00:00
|
|
|
|
// utilise soit la fonction priv_modifieConducteur soit la fonction priv_calculeConducteur
|
2007-01-29 20:32:38 +00:00
|
|
|
|
void (Conducer::* fonction_update) (const QPointF &, Terminal::Orientation, const QPointF &, Terminal::Orientation);
|
2007-02-14 01:08:29 +00:00
|
|
|
|
fonction_update = (nbSegments() && modified_path) ? &Conducer::priv_modifieConducer : &Conducer::priv_calculeConducer;
|
2007-01-05 14:29:08 +00:00
|
|
|
|
|
|
|
|
|
// appelle la bonne fonction pour calculer l'aspect du conducteur
|
|
|
|
|
(this ->* fonction_update)(
|
2007-01-29 20:32:38 +00:00
|
|
|
|
terminal1 -> amarrageConducer(), terminal1 -> orientation(),
|
|
|
|
|
terminal2 -> amarrageConducer(), terminal2 -> orientation()
|
2007-01-05 14:29:08 +00:00
|
|
|
|
);
|
2006-10-27 15:47:22 +00:00
|
|
|
|
QGraphicsPathItem::update(rect);
|
|
|
|
|
}
|
|
|
|
|
|
2006-11-30 18:05:02 +00:00
|
|
|
|
/**
|
|
|
|
|
Met a jour la representation graphique du conducteur en considerant que la borne b
|
|
|
|
|
a pour position pos
|
|
|
|
|
@param rect Rectangle a mettre a jour
|
|
|
|
|
@param b Borne
|
|
|
|
|
@param pos position de la borne b
|
|
|
|
|
*/
|
2007-01-29 20:32:38 +00:00
|
|
|
|
void Conducer::updateWithNewPos(const QRectF &rect, const Terminal *b, const QPointF &newpos) {
|
2006-11-30 18:05:02 +00:00
|
|
|
|
QPointF p1, p2;
|
2007-01-29 20:14:26 +00:00
|
|
|
|
if (b == terminal1) {
|
2006-11-30 18:05:02 +00:00
|
|
|
|
p1 = newpos;
|
2007-01-29 20:32:38 +00:00
|
|
|
|
p2 = terminal2 -> amarrageConducer();
|
2007-01-29 20:14:26 +00:00
|
|
|
|
} else if (b == terminal2) {
|
2007-01-29 20:32:38 +00:00
|
|
|
|
p1 = terminal1 -> amarrageConducer();
|
2006-11-30 18:05:02 +00:00
|
|
|
|
p2 = newpos;
|
|
|
|
|
} else {
|
2007-01-29 20:32:38 +00:00
|
|
|
|
p1 = terminal1 -> amarrageConducer();
|
|
|
|
|
p2 = terminal2 -> amarrageConducer();
|
2006-11-30 18:05:02 +00:00
|
|
|
|
}
|
2007-02-14 01:08:29 +00:00
|
|
|
|
if (nbSegments() && modified_path)
|
2007-01-29 20:32:38 +00:00
|
|
|
|
priv_modifieConducer(p1, terminal1 -> orientation(), p2, terminal2 -> orientation());
|
2007-01-05 14:29:08 +00:00
|
|
|
|
else
|
2007-01-29 20:32:38 +00:00
|
|
|
|
priv_calculeConducer(p1, terminal1 -> orientation(), p2, terminal2 -> orientation());
|
2007-01-05 14:29:08 +00:00
|
|
|
|
QGraphicsPathItem::update(rect);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
Genere le QPainterPath a partir de la liste des points
|
|
|
|
|
*/
|
2007-02-14 01:08:29 +00:00
|
|
|
|
void Conducer::segmentsToPath() {
|
|
|
|
|
// chemin qui sera dessine
|
2007-01-05 14:29:08 +00:00
|
|
|
|
QPainterPath path;
|
2007-02-14 01:08:29 +00:00
|
|
|
|
|
|
|
|
|
// s'il n'y a pa des segments, on arrete la
|
|
|
|
|
if (segments == NULL) setPath(path);
|
|
|
|
|
|
|
|
|
|
// demarre le chemin
|
|
|
|
|
path.moveTo(segments -> firstPoint());
|
|
|
|
|
|
|
|
|
|
// parcourt les segments pour dessiner le chemin
|
|
|
|
|
ConducerSegment *segment = segments;
|
|
|
|
|
while(segment -> hasNextSegment()) {
|
|
|
|
|
path.lineTo(segment -> secondPoint());
|
|
|
|
|
segment = segment -> nextSegment();
|
2007-01-05 14:29:08 +00:00
|
|
|
|
}
|
2007-02-14 01:08:29 +00:00
|
|
|
|
|
|
|
|
|
// termine le chemin
|
|
|
|
|
path.lineTo(segment -> secondPoint());
|
|
|
|
|
|
|
|
|
|
// affecte le chemin au conducteur
|
2007-01-05 14:29:08 +00:00
|
|
|
|
setPath(path);
|
2006-11-30 18:05:02 +00:00
|
|
|
|
}
|
|
|
|
|
|
2006-12-03 17:44:20 +00:00
|
|
|
|
/**
|
2007-01-05 14:29:08 +00:00
|
|
|
|
Gere les updates
|
2006-12-03 17:44:20 +00:00
|
|
|
|
@param p1 Coordonnees du point d'amarrage de la borne 1
|
2007-01-05 14:29:08 +00:00
|
|
|
|
@param o1 Orientation de la borne 1
|
2006-12-03 17:44:20 +00:00
|
|
|
|
@param p2 Coordonnees du point d'amarrage de la borne 2
|
2007-01-05 14:29:08 +00:00
|
|
|
|
@param o2 Orientation de la borne 2
|
2006-12-03 17:44:20 +00:00
|
|
|
|
*/
|
2007-01-29 20:32:38 +00:00
|
|
|
|
void Conducer::priv_modifieConducer(const QPointF &p1, Terminal::Orientation, const QPointF &p2, Terminal::Orientation) {
|
2007-02-14 01:08:29 +00:00
|
|
|
|
Q_ASSERT_X(nbSegments() > 1, "priv_modifieConducer", "pas de points a modifier");
|
2006-12-03 17:44:20 +00:00
|
|
|
|
|
2007-01-05 14:29:08 +00:00
|
|
|
|
// recupere les dernieres coordonnees connues des bornes
|
2007-01-29 20:32:38 +00:00
|
|
|
|
QPointF old_p1 = mapFromScene(terminal1 -> amarrageConducer());
|
|
|
|
|
QPointF old_p2 = mapFromScene(terminal2 -> amarrageConducer());
|
2006-12-03 17:44:20 +00:00
|
|
|
|
|
2007-01-05 14:29:08 +00:00
|
|
|
|
// recupere les coordonnees fournies des bornes
|
|
|
|
|
QPointF new_p1 = mapFromScene(p1);
|
|
|
|
|
QPointF new_p2 = mapFromScene(p2);
|
2006-12-03 17:44:20 +00:00
|
|
|
|
|
2007-01-05 14:29:08 +00:00
|
|
|
|
// les distances horizontales et verticales entre les anciennes bornes
|
|
|
|
|
// sont stockees dans orig_dist_2_terms_x et orig_dist_2_terms_y
|
2006-12-03 17:44:20 +00:00
|
|
|
|
|
2007-01-05 14:29:08 +00:00
|
|
|
|
// calcule les distances horizontales et verticales entre les nouvelles bornes
|
2007-01-29 20:14:26 +00:00
|
|
|
|
qreal new_dist_2_terminals_x = new_p2.x() - new_p1.x();
|
|
|
|
|
qreal new_dist_2_terminals_y = new_p2.y() - new_p1.y();
|
2006-12-03 17:44:20 +00:00
|
|
|
|
|
2007-01-05 14:29:08 +00:00
|
|
|
|
// en deduit les coefficients de "redimensionnement"
|
2007-01-29 20:14:26 +00:00
|
|
|
|
qreal coeff_x = new_dist_2_terminals_x / orig_dist_2_terms_x;
|
|
|
|
|
qreal coeff_y = new_dist_2_terminals_y / orig_dist_2_terms_y;
|
2007-01-05 14:29:08 +00:00
|
|
|
|
|
|
|
|
|
// genere les nouveaux points
|
|
|
|
|
int limite = moves_x.size() - 1;
|
|
|
|
|
int coeff = type_trajet_x ? 1 : -1;
|
2007-02-14 01:08:29 +00:00
|
|
|
|
|
|
|
|
|
QList<QPointF> points;
|
2007-01-05 14:29:08 +00:00
|
|
|
|
points << (type_trajet_x ? new_p1 : new_p2);
|
|
|
|
|
for (int i = 0 ; i < limite ; ++ i) {
|
|
|
|
|
QPointF previous_point = points.last();
|
|
|
|
|
points << QPointF (
|
|
|
|
|
previous_point.x() + (moves_x.at(i) * coeff_x * coeff),
|
|
|
|
|
previous_point.y() + (moves_y.at(i) * coeff_y * coeff)
|
|
|
|
|
);
|
2006-12-03 17:44:20 +00:00
|
|
|
|
}
|
2007-01-05 14:29:08 +00:00
|
|
|
|
points << (type_trajet_x ? new_p2 : new_p1);
|
2007-02-14 01:08:29 +00:00
|
|
|
|
pointsToSegments(points);
|
|
|
|
|
segmentsToPath();
|
2007-01-05 14:29:08 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
Calcule un trajet "par defaut" pour le conducteur
|
|
|
|
|
@param p1 Coordonnees du point d'amarrage de la borne 1
|
|
|
|
|
@param o1 Orientation de la borne 1
|
|
|
|
|
@param p2 Coordonnees du point d'amarrage de la borne 2
|
|
|
|
|
@param o2 Orientation de la borne 2
|
|
|
|
|
*/
|
2007-01-29 20:32:38 +00:00
|
|
|
|
void Conducer::priv_calculeConducer(const QPointF &p1, Terminal::Orientation o1, const QPointF &p2, Terminal::Orientation o2) {
|
2007-01-05 14:29:08 +00:00
|
|
|
|
QPointF sp1, sp2, depart, newp1, newp2, arrivee, depart0, arrivee0;
|
2007-01-29 20:14:26 +00:00
|
|
|
|
Terminal::Orientation ori_depart, ori_arrivee;
|
2007-02-14 01:08:29 +00:00
|
|
|
|
|
|
|
|
|
// s'assure qu'il n'y a ni points
|
|
|
|
|
QList<QPointF> points;
|
|
|
|
|
|
2007-01-05 14:29:08 +00:00
|
|
|
|
type_trajet_x = p1.x() < p2.x();
|
|
|
|
|
// mappe les points par rapport a la scene
|
|
|
|
|
sp1 = mapFromScene(p1);
|
|
|
|
|
sp2 = mapFromScene(p2);
|
|
|
|
|
|
|
|
|
|
// prolonge les bornes
|
|
|
|
|
newp1 = extendTerminal(sp1, o1);
|
|
|
|
|
newp2 = extendTerminal(sp2, o2);
|
2006-12-03 17:44:20 +00:00
|
|
|
|
|
2007-01-05 14:29:08 +00:00
|
|
|
|
// distingue le depart de l'arrivee : le trajet se fait toujours de gauche a droite (apres prolongation)
|
2006-12-03 17:44:20 +00:00
|
|
|
|
if (newp1.x() <= newp2.x()) {
|
|
|
|
|
depart = newp1;
|
|
|
|
|
arrivee = newp2;
|
|
|
|
|
depart0 = sp1;
|
|
|
|
|
arrivee0 = sp2;
|
2007-01-05 14:29:08 +00:00
|
|
|
|
ori_depart = o1;
|
|
|
|
|
ori_arrivee = o2;
|
2006-10-27 15:47:22 +00:00
|
|
|
|
} else {
|
2006-12-03 17:44:20 +00:00
|
|
|
|
depart = newp2;
|
|
|
|
|
arrivee = newp1;
|
|
|
|
|
depart0 = sp2;
|
|
|
|
|
arrivee0 = sp1;
|
2007-01-05 14:29:08 +00:00
|
|
|
|
ori_depart = o2;
|
|
|
|
|
ori_arrivee = o1;
|
2006-10-27 15:47:22 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// debut du trajet
|
2007-01-05 14:29:08 +00:00
|
|
|
|
points << depart0;
|
2006-12-03 17:44:20 +00:00
|
|
|
|
|
|
|
|
|
// prolongement de la borne de depart
|
2007-01-05 14:29:08 +00:00
|
|
|
|
points << depart;
|
2006-12-03 17:44:20 +00:00
|
|
|
|
|
|
|
|
|
// commence le vrai trajet
|
2006-10-27 15:47:22 +00:00
|
|
|
|
if (depart.y() < arrivee.y()) {
|
|
|
|
|
// trajet descendant
|
2007-01-29 20:14:26 +00:00
|
|
|
|
if ((ori_depart == Terminal::Nord && (ori_arrivee == Terminal::Sud || ori_arrivee == Terminal::Ouest)) || (ori_depart == Terminal::Est && ori_arrivee == Terminal::Ouest)) {
|
2006-10-27 15:47:22 +00:00
|
|
|
|
// cas <20> 3 <20>
|
|
|
|
|
qreal ligne_inter_x = (depart.x() + arrivee.x()) / 2.0;
|
2007-01-05 14:29:08 +00:00
|
|
|
|
points << QPointF(ligne_inter_x, depart.y());
|
|
|
|
|
points << QPointF(ligne_inter_x, arrivee.y());
|
2007-01-29 20:14:26 +00:00
|
|
|
|
} else if ((ori_depart == Terminal::Sud && (ori_arrivee == Terminal::Nord || ori_arrivee == Terminal::Est)) || (ori_depart == Terminal::Ouest && ori_arrivee == Terminal::Est)) {
|
2006-10-27 15:47:22 +00:00
|
|
|
|
// cas <20> 4 <20>
|
|
|
|
|
qreal ligne_inter_y = (depart.y() + arrivee.y()) / 2.0;
|
2007-01-05 14:29:08 +00:00
|
|
|
|
points << QPointF(depart.x(), ligne_inter_y);
|
|
|
|
|
points << QPointF(arrivee.x(), ligne_inter_y);
|
2007-01-29 20:14:26 +00:00
|
|
|
|
} else if ((ori_depart == Terminal::Nord || ori_depart == Terminal::Est) && (ori_arrivee == Terminal::Nord || ori_arrivee == Terminal::Est)) {
|
2007-01-05 14:29:08 +00:00
|
|
|
|
points << QPointF(arrivee.x(), depart.y()); // cas <20> 2 <20>
|
|
|
|
|
} else {
|
|
|
|
|
points << QPointF(depart.x(), arrivee.y()); // cas <20> 1 <20>
|
|
|
|
|
}
|
2006-10-27 15:47:22 +00:00
|
|
|
|
} else {
|
|
|
|
|
// trajet montant
|
2007-01-29 20:14:26 +00:00
|
|
|
|
if ((ori_depart == Terminal::Ouest && (ori_arrivee == Terminal::Est || ori_arrivee == Terminal::Sud)) || (ori_depart == Terminal::Nord && ori_arrivee == Terminal::Sud)) {
|
2006-10-27 15:47:22 +00:00
|
|
|
|
// cas <20> 3 <20>
|
|
|
|
|
qreal ligne_inter_y = (depart.y() + arrivee.y()) / 2.0;
|
2007-01-05 14:29:08 +00:00
|
|
|
|
points << QPointF(depart.x(), ligne_inter_y);
|
|
|
|
|
points << QPointF(arrivee.x(), ligne_inter_y);
|
2007-01-29 20:14:26 +00:00
|
|
|
|
} else if ((ori_depart == Terminal::Est && (ori_arrivee == Terminal::Ouest || ori_arrivee == Terminal::Nord)) || (ori_depart == Terminal::Sud && ori_arrivee == Terminal::Nord)) {
|
2006-10-27 15:47:22 +00:00
|
|
|
|
// cas <20> 4 <20>
|
|
|
|
|
qreal ligne_inter_x = (depart.x() + arrivee.x()) / 2.0;
|
2007-01-05 14:29:08 +00:00
|
|
|
|
points << QPointF(ligne_inter_x, depart.y());
|
|
|
|
|
points << QPointF(ligne_inter_x, arrivee.y());
|
2007-01-29 20:14:26 +00:00
|
|
|
|
} else if ((ori_depart == Terminal::Ouest || ori_depart == Terminal::Nord) && (ori_arrivee == Terminal::Ouest || ori_arrivee == Terminal::Nord)) {
|
2007-01-05 14:29:08 +00:00
|
|
|
|
points << QPointF(depart.x(), arrivee.y()); // cas <20> 2 <20>
|
|
|
|
|
} else {
|
|
|
|
|
points << QPointF(arrivee.x(), depart.y()); // cas <20> 1 <20>
|
|
|
|
|
}
|
2006-10-27 15:47:22 +00:00
|
|
|
|
}
|
2006-12-03 17:44:20 +00:00
|
|
|
|
|
|
|
|
|
// fin du vrai trajet
|
2007-01-05 14:29:08 +00:00
|
|
|
|
points << arrivee;
|
2006-12-03 17:44:20 +00:00
|
|
|
|
|
|
|
|
|
// prolongement de la borne d'arrivee
|
2007-01-05 14:29:08 +00:00
|
|
|
|
points << arrivee0;
|
2006-12-03 17:44:20 +00:00
|
|
|
|
|
2007-02-14 01:08:29 +00:00
|
|
|
|
pointsToSegments(points);
|
|
|
|
|
segmentsToPath();
|
2007-01-05 14:29:08 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
Prolonge une borne.
|
|
|
|
|
@param terminal Le point correspondant a la borne
|
|
|
|
|
@param terminal_orientation L'orientation de la borne
|
|
|
|
|
@param ext_size la taille de la prolongation
|
|
|
|
|
@return le point correspondant a la borne apres prolongation
|
|
|
|
|
*/
|
2007-01-29 20:32:38 +00:00
|
|
|
|
QPointF Conducer::extendTerminal(const QPointF &terminal, Terminal::Orientation terminal_orientation, qreal ext_size) {
|
2007-01-05 14:29:08 +00:00
|
|
|
|
QPointF extended_terminal;
|
|
|
|
|
switch(terminal_orientation) {
|
2007-01-29 20:14:26 +00:00
|
|
|
|
case Terminal::Nord:
|
2007-01-05 14:29:08 +00:00
|
|
|
|
extended_terminal = QPointF(terminal.x(), terminal.y() - ext_size);
|
|
|
|
|
break;
|
2007-01-29 20:14:26 +00:00
|
|
|
|
case Terminal::Est:
|
2007-01-05 14:29:08 +00:00
|
|
|
|
extended_terminal = QPointF(terminal.x() + ext_size, terminal.y());
|
|
|
|
|
break;
|
2007-01-29 20:14:26 +00:00
|
|
|
|
case Terminal::Sud:
|
2007-01-05 14:29:08 +00:00
|
|
|
|
extended_terminal = QPointF(terminal.x(), terminal.y() + ext_size);
|
|
|
|
|
break;
|
2007-01-29 20:14:26 +00:00
|
|
|
|
case Terminal::Ouest:
|
2007-01-05 14:29:08 +00:00
|
|
|
|
extended_terminal = QPointF(terminal.x() - ext_size, terminal.y());
|
|
|
|
|
break;
|
|
|
|
|
default: extended_terminal = terminal;
|
|
|
|
|
}
|
|
|
|
|
return(extended_terminal);
|
2006-10-27 15:47:22 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
Dessine le conducteur sans antialiasing.
|
|
|
|
|
@param qp Le QPainter a utiliser pour dessiner le conducteur
|
|
|
|
|
@param qsogi Les options de style pour le conducteur
|
|
|
|
|
@param qw Le QWidget sur lequel on dessine
|
|
|
|
|
*/
|
2007-01-29 20:32:38 +00:00
|
|
|
|
void Conducer::paint(QPainter *qp, const QStyleOptionGraphicsItem */*qsogi*/, QWidget */*qw*/) {
|
2006-10-27 15:47:22 +00:00
|
|
|
|
qp -> save();
|
2007-01-05 14:29:08 +00:00
|
|
|
|
qp -> setRenderHint(QPainter::Antialiasing, false);
|
2006-11-26 21:35:05 +00:00
|
|
|
|
|
2007-01-05 14:29:08 +00:00
|
|
|
|
// affectation du QPen et de la QBrush modifies au QPainter
|
|
|
|
|
qp -> setBrush(conducer_brush);
|
|
|
|
|
qp -> setPen(conducer_pen);
|
|
|
|
|
if (isSelected()) {
|
|
|
|
|
QPen tmp = qp -> pen();
|
|
|
|
|
tmp.setColor(Qt::red);
|
|
|
|
|
qp -> setPen(tmp);
|
|
|
|
|
}
|
2006-11-26 21:35:05 +00:00
|
|
|
|
|
2007-01-05 14:29:08 +00:00
|
|
|
|
// dessin du conducteur
|
2006-11-26 21:35:05 +00:00
|
|
|
|
qp -> drawPath(path());
|
2007-01-05 14:29:08 +00:00
|
|
|
|
|
|
|
|
|
// dessin des points d'accroche du conducteur si celui-ci est selectionne
|
|
|
|
|
if (isSelected()) {
|
|
|
|
|
qp -> setRenderHint(QPainter::Antialiasing, true);
|
2007-02-14 01:08:29 +00:00
|
|
|
|
QList<QPointF> points = segmentsToPoints();
|
|
|
|
|
QPointF previous_point;
|
|
|
|
|
QBrush square_brush(Qt::darkGreen);
|
2007-01-05 14:29:08 +00:00
|
|
|
|
for (int i = 1 ; i < (points.size() -1) ; ++ i) {
|
|
|
|
|
QPointF point = points.at(i);
|
2007-02-14 01:08:29 +00:00
|
|
|
|
|
|
|
|
|
if (i > 1) {
|
|
|
|
|
qp -> fillRect(
|
|
|
|
|
QRectF(
|
|
|
|
|
((previous_point.x() + point.x()) / 2.0 ) - 2.5,
|
|
|
|
|
((previous_point.y() + point.y()) / 2.0 ) - 2.5,
|
|
|
|
|
5.0,
|
|
|
|
|
5.0
|
|
|
|
|
),
|
|
|
|
|
square_brush
|
|
|
|
|
);
|
|
|
|
|
}
|
2007-01-05 14:29:08 +00:00
|
|
|
|
qp -> drawEllipse(QRectF(point.x() - 3.0, point.y() - 3.0, 6.0, 6.0));
|
2007-02-14 01:08:29 +00:00
|
|
|
|
previous_point = point;
|
2007-01-05 14:29:08 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
2006-10-27 15:47:22 +00:00
|
|
|
|
qp -> restore();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
Indique si deux orientations de Borne sont sur le meme axe (Vertical / Horizontal).
|
|
|
|
|
@param a La premiere orientation de Borne
|
|
|
|
|
@param b La seconde orientation de Borne
|
|
|
|
|
@return Un booleen a true si les deux orientations de bornes sont sur le meme axe
|
|
|
|
|
*/
|
2007-01-29 20:32:38 +00:00
|
|
|
|
bool Conducer::surLeMemeAxe(Terminal::Orientation a, Terminal::Orientation b) {
|
2007-01-29 20:14:26 +00:00
|
|
|
|
if ((a == Terminal::Nord || a == Terminal::Sud) && (b == Terminal::Nord || b == Terminal::Sud)) return(true);
|
|
|
|
|
else if ((a == Terminal::Est || a == Terminal::Ouest) && (b == Terminal::Est || b == Terminal::Ouest)) return(true);
|
2006-10-27 15:47:22 +00:00
|
|
|
|
else return(false);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
Indique si une orientation de borne est horizontale (Est / Ouest).
|
|
|
|
|
@param a L'orientation de borne
|
|
|
|
|
@return True si l'orientation de borne est horizontale, false sinon
|
|
|
|
|
*/
|
2007-01-29 20:32:38 +00:00
|
|
|
|
bool Conducer::estHorizontale(Terminal::Orientation a) {
|
2007-01-29 20:14:26 +00:00
|
|
|
|
return(a == Terminal::Est || a == Terminal::Ouest);
|
2006-10-27 15:47:22 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
Indique si une orientation de borne est verticale (Nord / Sud).
|
|
|
|
|
@param a L'orientation de borne
|
|
|
|
|
@return True si l'orientation de borne est verticale, false sinon
|
|
|
|
|
*/
|
2007-01-29 20:32:38 +00:00
|
|
|
|
bool Conducer::estVerticale(Terminal::Orientation a) {
|
2007-01-29 20:14:26 +00:00
|
|
|
|
return(a == Terminal::Nord || a == Terminal::Sud);
|
2006-10-27 15:47:22 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
Methode de preparation a la destruction du conducteur ; le conducteur se detache de ses deux bornes
|
|
|
|
|
*/
|
2007-01-29 20:32:38 +00:00
|
|
|
|
void Conducer::destroy() {
|
2006-10-27 15:47:22 +00:00
|
|
|
|
destroyed = true;
|
2007-01-29 20:32:38 +00:00
|
|
|
|
terminal1 -> removeConducer(this);
|
|
|
|
|
terminal2 -> removeConducer(this);
|
2006-10-27 15:47:22 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
Methode de validation d'element XML
|
|
|
|
|
@param e Un element XML sense represente un Conducteur
|
|
|
|
|
@return true si l'element XML represente bien un Conducteur ; false sinon
|
|
|
|
|
*/
|
2007-01-29 20:32:38 +00:00
|
|
|
|
bool Conducer::valideXml(QDomElement &e){
|
2006-10-27 15:47:22 +00:00
|
|
|
|
// verifie le nom du tag
|
|
|
|
|
if (e.tagName() != "conducteur") return(false);
|
|
|
|
|
|
|
|
|
|
// verifie la presence des attributs minimaux
|
|
|
|
|
if (!e.hasAttribute("borne1")) return(false);
|
|
|
|
|
if (!e.hasAttribute("borne2")) return(false);
|
|
|
|
|
|
|
|
|
|
bool conv_ok;
|
|
|
|
|
// parse l'abscisse
|
|
|
|
|
e.attribute("borne1").toInt(&conv_ok);
|
|
|
|
|
if (!conv_ok) return(false);
|
|
|
|
|
|
|
|
|
|
// parse l'ordonnee
|
|
|
|
|
e.attribute("borne2").toInt(&conv_ok);
|
|
|
|
|
if (!conv_ok) return(false);
|
|
|
|
|
return(true);
|
|
|
|
|
}
|
2007-01-05 14:29:08 +00:00
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
Gere les clics sur le conducteur.
|
|
|
|
|
@param e L'evenement decrivant le clic.
|
|
|
|
|
*/
|
2007-01-29 20:32:38 +00:00
|
|
|
|
void Conducer::mousePressEvent(QGraphicsSceneMouseEvent *e) {
|
2007-01-05 14:29:08 +00:00
|
|
|
|
// clic gauche
|
|
|
|
|
if (e -> buttons() & Qt::LeftButton) {
|
2007-02-14 01:08:29 +00:00
|
|
|
|
// recupere les coordonnees du clic
|
2007-01-05 14:29:08 +00:00
|
|
|
|
press_point = mapFromScene(e -> pos());
|
2007-02-14 01:08:29 +00:00
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
parcourt les segments pour determiner si le clic a eu lieu
|
|
|
|
|
- sur l'extremite d'un segment
|
|
|
|
|
- sur le milieu d'un segment
|
|
|
|
|
- ailleurs
|
|
|
|
|
*/
|
|
|
|
|
ConducerSegment *segment = segments;
|
|
|
|
|
while (segment -> hasNextSegment()) {
|
|
|
|
|
if (hasClickedOn(press_point, segment -> secondPoint())) {
|
2007-01-05 14:29:08 +00:00
|
|
|
|
moving_point = true;
|
2007-02-14 01:08:29 +00:00
|
|
|
|
moving_segment = false;
|
2007-02-15 20:00:20 +00:00
|
|
|
|
previous_z_value = zValue();
|
|
|
|
|
setZValue(5000.0);
|
2007-02-14 01:08:29 +00:00
|
|
|
|
moved_segment = segment;
|
|
|
|
|
break;
|
|
|
|
|
} else if (hasClickedOn(press_point, segment -> middle())) {
|
|
|
|
|
moving_point = false;
|
|
|
|
|
moving_segment = true;
|
2007-02-15 20:00:20 +00:00
|
|
|
|
previous_z_value = zValue();
|
|
|
|
|
setZValue(5000.0);
|
2007-02-14 01:08:29 +00:00
|
|
|
|
moved_segment = segment;
|
2007-01-05 14:29:08 +00:00
|
|
|
|
break;
|
|
|
|
|
}
|
2007-02-14 01:08:29 +00:00
|
|
|
|
segment = segment -> nextSegment();
|
2007-01-05 14:29:08 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
QGraphicsPathItem::mousePressEvent(e);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
Gere les deplacements de souris sur le conducteur.
|
|
|
|
|
@param e L'evenement decrivant le deplacement de souris.
|
|
|
|
|
@todo
|
|
|
|
|
-calculer le trajet du conducteur differemment selon l'etat du flag "trajet modifie"
|
|
|
|
|
-garder une liste des points constituants le trajet
|
|
|
|
|
-lorsque le fil est selectionne, dessiner ces points (cercles)
|
|
|
|
|
-lors d'un mousemoveevent: detecter la position du clic : si cela tombe dans la zone d'un point :
|
|
|
|
|
-deplacer ce point en consequence
|
|
|
|
|
-mettre le flag "trajet modifie" a true
|
|
|
|
|
-gerer les contraintes
|
|
|
|
|
*/
|
2007-01-29 20:32:38 +00:00
|
|
|
|
void Conducer::mouseMoveEvent(QGraphicsSceneMouseEvent *e) {
|
2007-01-05 14:29:08 +00:00
|
|
|
|
// clic gauche
|
|
|
|
|
if (e -> buttons() & Qt::LeftButton) {
|
2007-02-14 01:08:29 +00:00
|
|
|
|
// position pointee par la souris
|
|
|
|
|
qreal mouse_x = e -> pos().x();
|
|
|
|
|
qreal mouse_y = e -> pos().y();
|
|
|
|
|
|
2007-01-05 14:29:08 +00:00
|
|
|
|
if (moving_point) {
|
2007-02-14 01:08:29 +00:00
|
|
|
|
// la modification par points revient bientot
|
|
|
|
|
/*
|
2007-01-05 14:29:08 +00:00
|
|
|
|
// position precedente du point
|
2007-02-14 01:08:29 +00:00
|
|
|
|
QPointF p = moved_segment -> secondPoint();
|
2007-01-05 14:29:08 +00:00
|
|
|
|
qreal p_x = p.x();
|
|
|
|
|
qreal p_y = p.y();
|
|
|
|
|
|
2007-02-14 01:08:29 +00:00
|
|
|
|
// calcul du deplacement
|
|
|
|
|
moved_segment -> moveX(mouse_x - p_x());
|
|
|
|
|
moved_segment -> moveY(mouse_y - p_y());
|
2007-01-05 14:29:08 +00:00
|
|
|
|
|
2007-02-14 01:08:29 +00:00
|
|
|
|
// application du deplacement
|
|
|
|
|
modified_path = true;
|
|
|
|
|
updatePoints();
|
|
|
|
|
segmentsToPath();
|
|
|
|
|
*/
|
|
|
|
|
} else if (moving_segment) {
|
|
|
|
|
// position precedente du point
|
|
|
|
|
QPointF p = moved_segment -> middle();
|
2007-01-05 14:29:08 +00:00
|
|
|
|
|
2007-02-14 01:08:29 +00:00
|
|
|
|
// calcul du deplacement
|
|
|
|
|
moved_segment -> moveX(mouse_x - p.x());
|
|
|
|
|
moved_segment -> moveY(mouse_y - p.y());
|
2007-01-05 14:29:08 +00:00
|
|
|
|
|
|
|
|
|
// application du deplacement
|
|
|
|
|
modified_path = true;
|
|
|
|
|
updatePoints();
|
2007-02-14 01:08:29 +00:00
|
|
|
|
segmentsToPath();
|
2007-01-05 14:29:08 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
QGraphicsPathItem::mouseMoveEvent(e);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
Gere les relachements de boutons de souris sur le conducteur
|
|
|
|
|
@param e L'evenement decrivant le lacher de bouton.
|
|
|
|
|
*/
|
2007-01-29 20:32:38 +00:00
|
|
|
|
void Conducer::mouseReleaseEvent(QGraphicsSceneMouseEvent *e) {
|
2007-01-05 14:29:08 +00:00
|
|
|
|
// clic gauche
|
2007-02-14 01:08:29 +00:00
|
|
|
|
moving_point = false;
|
|
|
|
|
moving_segment = false;
|
2007-02-15 20:00:20 +00:00
|
|
|
|
setZValue(previous_z_value);
|
2007-02-14 01:08:29 +00:00
|
|
|
|
QGraphicsPathItem::mouseReleaseEvent(e);
|
2007-01-05 14:29:08 +00:00
|
|
|
|
}
|
|
|
|
|
|
2007-02-15 20:00:20 +00:00
|
|
|
|
void Conducer::hoverMoveEvent(QGraphicsSceneHoverEvent *e) {
|
|
|
|
|
if (isSelected()) {
|
|
|
|
|
QPointF hover_point = mapFromScene(e -> pos());
|
|
|
|
|
ConducerSegment *segment = segments;
|
|
|
|
|
bool cursor_set = false;
|
|
|
|
|
while (segment -> hasNextSegment()) {
|
|
|
|
|
/*if (hasClickedOn(hover_point, segment -> secondPoint())) {
|
|
|
|
|
setCursor(Qt::CrossCursor);
|
|
|
|
|
cursor_set = true;
|
|
|
|
|
} else */if (hasClickedOn(hover_point, segment -> middle())) {
|
|
|
|
|
setCursor(segment -> isVertical() ? Qt::SplitHCursor : Qt::SplitVCursor);
|
|
|
|
|
cursor_set = true;
|
|
|
|
|
}
|
|
|
|
|
segment = segment -> nextSegment();
|
|
|
|
|
}
|
|
|
|
|
if (!cursor_set) setCursor(Qt::ArrowCursor);
|
|
|
|
|
}
|
|
|
|
|
QGraphicsPathItem::hoverMoveEvent(e);
|
|
|
|
|
}
|
|
|
|
|
|
2007-01-05 14:29:08 +00:00
|
|
|
|
/**
|
|
|
|
|
@return Le rectangle delimitant l'espace de dessin du conducteur
|
|
|
|
|
*/
|
2007-01-29 20:32:38 +00:00
|
|
|
|
QRectF Conducer::boundingRect() const {
|
2007-01-05 14:29:08 +00:00
|
|
|
|
QRectF retour = QGraphicsPathItem::boundingRect();
|
|
|
|
|
retour.adjust(-5.0, -5.0, 5.0, 5.0);
|
|
|
|
|
return(retour);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
@return La forme / zone "cliquable" du conducteur
|
|
|
|
|
*/
|
2007-01-29 20:32:38 +00:00
|
|
|
|
QPainterPath Conducer::shape() const {
|
2007-02-14 01:08:29 +00:00
|
|
|
|
QList<QPointF> points = segmentsToPoints();
|
2007-01-05 14:29:08 +00:00
|
|
|
|
QPainterPath area;
|
|
|
|
|
QPointF previous_point;
|
|
|
|
|
QPointF *point1, *point2;
|
|
|
|
|
foreach(QPointF point, points) {
|
|
|
|
|
if (!previous_point.isNull()) {
|
|
|
|
|
if (point.x() == previous_point.x()) {
|
|
|
|
|
if (point.y() <= previous_point.y()) {
|
|
|
|
|
point1 = &point;
|
|
|
|
|
point2 = &previous_point;
|
|
|
|
|
} else {
|
|
|
|
|
point1 = &previous_point;
|
|
|
|
|
point2 = &point;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
if (point.x() <= previous_point.x()) {
|
|
|
|
|
point1 = &point;
|
|
|
|
|
point2 = &previous_point;
|
|
|
|
|
} else {
|
|
|
|
|
point1 = &previous_point;
|
|
|
|
|
point2 = &point;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
qreal p1_x = point1 -> x();
|
|
|
|
|
qreal p1_y = point1 -> y();
|
|
|
|
|
qreal p2_x = point2 -> x();
|
|
|
|
|
qreal p2_y = point2 -> y();
|
|
|
|
|
area.setFillRule(Qt::OddEvenFill);
|
|
|
|
|
area.addRect(p1_x - 5.0, p1_y - 5.0, 10.0 + p2_x - p1_x, 10.0 + p2_y - p1_y);
|
|
|
|
|
}
|
|
|
|
|
previous_point = point;
|
|
|
|
|
area.setFillRule(Qt::WindingFill);
|
|
|
|
|
area.addRect(point.x() - 5.0, point.y() - 5.0, 10.0, 10.0);
|
|
|
|
|
}
|
|
|
|
|
return(area);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
Met <EFBFBD> jour deux listes de reels.
|
|
|
|
|
*/
|
2007-01-29 20:32:38 +00:00
|
|
|
|
void Conducer::updatePoints() {
|
2007-02-14 01:08:29 +00:00
|
|
|
|
QList<QPointF> points = segmentsToPoints();
|
2007-01-05 14:29:08 +00:00
|
|
|
|
int s = points.size();
|
|
|
|
|
moves_x.clear();
|
|
|
|
|
moves_y.clear();
|
|
|
|
|
for (int i = 1 ; i < s ; ++ i) {
|
|
|
|
|
moves_x << points.at(i).x() - points.at(i - 1).x();
|
|
|
|
|
moves_y << points.at(i).y() - points.at(i - 1).y();
|
|
|
|
|
}
|
|
|
|
|
QPointF b1 = points.at(0);
|
|
|
|
|
QPointF b2 = points.at(s - 1);
|
|
|
|
|
orig_dist_2_terms_x = b2.x() - b1.x();
|
|
|
|
|
orig_dist_2_terms_y = b2.y() - b1.y();
|
|
|
|
|
}
|
|
|
|
|
|
2007-01-29 20:32:38 +00:00
|
|
|
|
qreal Conducer::conducer_bound(qreal tobound, qreal bound1, qreal bound2) {
|
2007-01-05 14:29:08 +00:00
|
|
|
|
qreal space = 5.0;
|
|
|
|
|
if (bound1 < bound2) {
|
|
|
|
|
return(qBound(bound1 + space, tobound, bound2 - space));
|
|
|
|
|
} else {
|
|
|
|
|
return(qBound(bound2 + space, tobound, bound1 - space));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2007-01-29 20:32:38 +00:00
|
|
|
|
qreal Conducer::conducer_bound(qreal tobound, qreal bound, bool positive) {
|
2007-01-05 14:29:08 +00:00
|
|
|
|
qreal space = 5.0;
|
|
|
|
|
return(positive ? qMax(tobound, bound + space) : qMin(tobound, bound - space));
|
|
|
|
|
}
|
2007-02-14 01:08:29 +00:00
|
|
|
|
|
|
|
|
|
int Conducer::nbSegments() {
|
|
|
|
|
if (segments == NULL) return(0);
|
|
|
|
|
int nb_seg = 1;
|
|
|
|
|
ConducerSegment *segment = segments;
|
|
|
|
|
while (segment -> hasNextSegment()) {
|
|
|
|
|
++ nb_seg;
|
|
|
|
|
segment = segment -> nextSegment();
|
|
|
|
|
}
|
|
|
|
|
return(nb_seg);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
Genere une liste de points a partir des segments de ce conducteur
|
|
|
|
|
@return La liste de points representant ce conducteur
|
|
|
|
|
*/
|
|
|
|
|
QList<QPointF> Conducer::segmentsToPoints() const {
|
|
|
|
|
// liste qui sera retournee
|
|
|
|
|
QList<QPointF> points_list;
|
|
|
|
|
|
|
|
|
|
// on retourne la liste tout de suite s'il n'y a pas de segments
|
|
|
|
|
if (segments == NULL) return(points_list);
|
|
|
|
|
|
|
|
|
|
// recupere le premier point
|
|
|
|
|
points_list << segments -> firstPoint();
|
|
|
|
|
|
|
|
|
|
// parcourt les segments pour recuperer les autres points
|
|
|
|
|
ConducerSegment *segment = segments;
|
|
|
|
|
while(segment -> hasNextSegment()) {
|
|
|
|
|
points_list << segment -> secondPoint();
|
|
|
|
|
segment = segment -> nextSegment();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// recupere le dernier point
|
|
|
|
|
points_list << segment -> secondPoint();
|
|
|
|
|
|
|
|
|
|
//retourne la liste
|
|
|
|
|
return(points_list);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
Regenere les segments de ce conducteur a partir de la liste de points passee en parametre
|
|
|
|
|
@param points_list Liste de points a utiliser pour generer les segments
|
|
|
|
|
*/
|
|
|
|
|
void Conducer::pointsToSegments(QList<QPointF> points_list) {
|
|
|
|
|
// supprime les segments actuels
|
|
|
|
|
if (segments != NULL) {
|
|
|
|
|
ConducerSegment *segment = segments;
|
|
|
|
|
while (segment -> hasNextSegment()) {
|
|
|
|
|
ConducerSegment *nextsegment = segment -> nextSegment();
|
|
|
|
|
delete segment;
|
|
|
|
|
segment = nextsegment;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// cree les segments a partir de la liste de points
|
|
|
|
|
ConducerSegment *last_segment = NULL;
|
|
|
|
|
for (int i = 0 ; i < points_list.size() - 1 ; ++ i) {
|
|
|
|
|
last_segment = new ConducerSegment(points_list.at(i), points_list.at(i + 1), last_segment);
|
|
|
|
|
if (!i) segments = last_segment;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool Conducer::hasClickedOn(QPointF press_point, QPointF point) {
|
|
|
|
|
return (
|
|
|
|
|
press_point.x() >= point.x() - 5.0 &&\
|
|
|
|
|
press_point.x() < point.x() + 5.0 &&\
|
|
|
|
|
press_point.y() >= point.y() - 5.0 &&\
|
|
|
|
|
press_point.y() < point.y() + 5.0
|
|
|
|
|
);
|
|
|
|
|
}
|
2007-02-18 19:33:15 +00:00
|
|
|
|
|
|
|
|
|
bool Conducer::fromXml(QDomElement &e) {
|
|
|
|
|
// parcourt les elements XML "segment" et en extrait deux listes de longueurs
|
|
|
|
|
// les segments non valides sont ignores
|
|
|
|
|
QList<qreal> segments_x, segments_y;
|
|
|
|
|
for (QDomNode node = e.firstChild() ; !node.isNull() ; node = node.nextSibling()) {
|
|
|
|
|
// on s'interesse aux elements XML "segment"
|
|
|
|
|
QDomElement current_segment = node.toElement();
|
|
|
|
|
if (current_segment.isNull() || current_segment.tagName() != "segment") continue;
|
|
|
|
|
|
|
|
|
|
// le segment doit avoir une longueur
|
|
|
|
|
if (!current_segment.hasAttribute("length")) continue;
|
|
|
|
|
|
|
|
|
|
// cette longueur doit etre un reel
|
|
|
|
|
bool ok;
|
|
|
|
|
qreal segment_length = current_segment.attribute("length").toDouble(&ok);
|
|
|
|
|
if (!ok) continue;
|
|
|
|
|
|
|
|
|
|
if (current_segment.attribute("orientation") == "horizontal") {
|
|
|
|
|
segments_x << segment_length;
|
|
|
|
|
segments_y << 0.0;
|
|
|
|
|
} else {
|
|
|
|
|
segments_x << 0.0;
|
|
|
|
|
segments_y << segment_length;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// s'il n'y a pas de segments, on renvoie true
|
|
|
|
|
if (!segments_x.size()) return(true);
|
|
|
|
|
|
|
|
|
|
// les longueurs recueillies doivent etre coherentes avec les positions des bornes
|
|
|
|
|
qreal width = 0.0, height= 0.0;
|
|
|
|
|
foreach (qreal t, segments_x) width += t;
|
|
|
|
|
foreach (qreal t, segments_y) height += t;
|
|
|
|
|
QPointF t1 = terminal1 -> amarrageConducer();
|
|
|
|
|
QPointF t2 = terminal2 -> amarrageConducer();
|
|
|
|
|
qreal expected_width = qAbs(t2.x() - t1.x());
|
|
|
|
|
qreal expected_height = qAbs(t2.y() - t1.y());
|
|
|
|
|
|
|
|
|
|
if (expected_width != width || expected_height != height) return(false);
|
|
|
|
|
|
|
|
|
|
/* on recree les segments a partir des donnes XML */
|
|
|
|
|
// cree la liste de points
|
|
|
|
|
QList<QPointF> points_list;
|
|
|
|
|
points_list << t1;
|
|
|
|
|
for (int i = 0 ; i < segments_x.size() ; ++ i) {
|
|
|
|
|
points_list << QPointF(
|
|
|
|
|
points_list.last().x() + segments_x.at(i),
|
|
|
|
|
points_list.last().y() + segments_y.at(i)
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
qDebug() << points_list;
|
|
|
|
|
pointsToSegments(points_list);
|
|
|
|
|
|
|
|
|
|
// initialise divers parametres lies a la modification des conducteurs
|
|
|
|
|
modified_path = true;
|
|
|
|
|
moves_x = segments_x;
|
|
|
|
|
moves_y = segments_y;
|
|
|
|
|
type_trajet_x = points_list.at(0).x() < points_list.at(points_list.size() - 1).x();
|
|
|
|
|
orig_dist_2_terms_x = points_list.at(points_list.size() - 1).x() - points_list.at(0).x();
|
|
|
|
|
orig_dist_2_terms_y = points_list.at(points_list.size() - 1).y() - points_list.at(0).y();
|
|
|
|
|
|
|
|
|
|
segmentsToPath();
|
|
|
|
|
return(true);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Conducer::toXml(QDomDocument &d, QDomElement &e) {
|
|
|
|
|
// on n'exporte les segments du conducteur que si ceux-ci ont
|
|
|
|
|
// ete modifies par l'utilisateur
|
|
|
|
|
if (!modified_path) return;
|
|
|
|
|
|
|
|
|
|
// parcours et export des segments
|
|
|
|
|
ConducerSegment *segment = segments;
|
|
|
|
|
QDomElement current_segment;
|
|
|
|
|
while (segment -> hasNextSegment()) {
|
|
|
|
|
current_segment = d.createElement("segment");
|
|
|
|
|
current_segment.setAttribute("orientation", segment -> isHorizontal() ? "horizontal" : "vertical");
|
|
|
|
|
current_segment.setAttribute("length", segment -> length());
|
|
|
|
|
e.appendChild(current_segment);
|
|
|
|
|
segment = segment -> nextSegment();
|
|
|
|
|
}
|
|
|
|
|
current_segment = d.createElement("segment");
|
|
|
|
|
current_segment.setAttribute("orientation", segment -> isHorizontal() ? "horizontal" : "vertical");
|
|
|
|
|
current_segment.setAttribute("length", segment -> length());
|
|
|
|
|
e.appendChild(current_segment);
|
|
|
|
|
}
|