mirror of
https://github.com/qelectrotech/qelectrotech-source-mirror.git
synced 2025-12-20 08:10:52 +01:00
Implementation d'un nouvel algorithme de modification des conducteurs
git-svn-id: svn+ssh://svn.tuxfamily.org/svnroot/qet/qet/trunk@125 bfdf4180-ca20-0410-9c96-a3a8aa849046
This commit is contained in:
261
conducer.cpp
261
conducer.cpp
@@ -1,6 +1,7 @@
|
||||
#include <QtDebug>
|
||||
#include "conducer.h"
|
||||
#include "conducersegment.h"
|
||||
#include "conducersegmentprofile.h"
|
||||
#include "element.h"
|
||||
#define PR(x) qDebug() << #x " = " << x;
|
||||
|
||||
@@ -15,17 +16,23 @@ QBrush Conducer::conducer_brush = QBrush();
|
||||
@param parent Element parent du conducteur (0 par defaut)
|
||||
@param scene QGraphicsScene auquelle appartient le conducteur
|
||||
*/
|
||||
Conducer::Conducer(Terminal *p1, Terminal* p2, Element *parent, QGraphicsScene *scene) : QGraphicsPathItem(parent, scene) {
|
||||
// bornes que le conducteur relie
|
||||
terminal1 = p1;
|
||||
terminal2 = p2;
|
||||
Conducer::Conducer(Terminal *p1, Terminal* p2, Element *parent, QGraphicsScene *scene) :
|
||||
QGraphicsPathItem(parent, scene),
|
||||
terminal1(p1),
|
||||
terminal2(p2),
|
||||
destroyed(false),
|
||||
segments(NULL),
|
||||
previous_z_value(zValue()),
|
||||
modified_path(false),
|
||||
has_to_save_profile(false)
|
||||
{
|
||||
// ajout du conducteur a la liste de conducteurs de chacune des deux bornes
|
||||
bool ajout_p1 = terminal1 -> addConducer(this);
|
||||
bool ajout_p2 = terminal2 -> addConducer(this);
|
||||
|
||||
// en cas d'echec de l'ajout (conducteur deja existant notamment)
|
||||
if (!ajout_p1 || !ajout_p2) return;
|
||||
destroyed = false;
|
||||
modified_path = false;
|
||||
|
||||
// attributs de dessin par defaut (communs a tous les conducteurs)
|
||||
if (!pen_and_brush_initialized) {
|
||||
conducer_pen.setJoinStyle(Qt::MiterJoin);
|
||||
@@ -37,12 +44,11 @@ Conducer::Conducer(Terminal *p1, Terminal* p2, Element *parent, QGraphicsScene *
|
||||
conducer_brush.setStyle(Qt::NoBrush);
|
||||
pen_and_brush_initialized = true;
|
||||
}
|
||||
|
||||
// calcul du rendu du conducteur
|
||||
segments = NULL;
|
||||
priv_calculeConducer(terminal1 -> amarrageConducer(), terminal1 -> orientation(), terminal2 -> amarrageConducer(), terminal2 -> orientation());
|
||||
setFlags(QGraphicsItem::ItemIsSelectable);
|
||||
setAcceptsHoverEvents(true);
|
||||
previous_z_value = zValue();
|
||||
|
||||
// ajout du champ de texte editable
|
||||
text_item = new QGraphicsTextItem();
|
||||
@@ -148,51 +154,125 @@ void Conducer::segmentsToPath() {
|
||||
@param o2 Orientation de la borne 2
|
||||
*/
|
||||
void Conducer::priv_modifieConducer(const QPointF &p1, QET::Orientation, const QPointF &p2, QET::Orientation) {
|
||||
Q_ASSERT_X(nbSegments() > 1, "priv_modifieConducer", "pas de points a modifier");
|
||||
// determine le nombre de segments horizontaux et verticaux
|
||||
uint nb_horiz_segments = conducer_profile.nbSegments(QET::Horizontal);
|
||||
uint nb_verti_segments = conducer_profile.nbSegments(QET::Vertical);
|
||||
|
||||
// recupere les dernieres coordonnees connues des bornes
|
||||
QPointF old_p1 = mapFromScene(terminal1 -> amarrageConducer());
|
||||
QPointF old_p2 = mapFromScene(terminal2 -> amarrageConducer());
|
||||
Q_ASSERT_X(nb_horiz_segments + nb_verti_segments > 1, "Conducer::priv_modifieConducer", "pas de points a modifier");
|
||||
Q_ASSERT_X(!conducer_profile.isNull(), "Conducer::priv_modifieConducer", "pas de profil utilisable");
|
||||
|
||||
// recupere les coordonnees fournies des bornes
|
||||
QPointF new_p1 = mapFromScene(p1);
|
||||
QPointF new_p2 = mapFromScene(p2);
|
||||
QRectF new_rect = QRectF(new_p1, new_p2);
|
||||
|
||||
// les distances horizontales et verticales entre les anciennes bornes
|
||||
// sont stockees dans orig_dist_2_terms_x et orig_dist_2_terms_y
|
||||
// recupere la largeur et la hauteur du profil
|
||||
qreal profile_width = conducer_profile.width();
|
||||
qreal profile_height = conducer_profile.height();
|
||||
|
||||
// calcule les distances horizontales et verticales entre les nouvelles bornes
|
||||
qreal new_dist_2_terminals_x = new_p2.x() - new_p1.x();
|
||||
qreal new_dist_2_terminals_y = new_p2.y() - new_p1.y();
|
||||
// calcule les differences verticales et horizontales a appliquer
|
||||
qreal h_diff = (qAbs(new_rect.width()) - qAbs(profile_width) ) * getSign(profile_width);
|
||||
qreal v_diff = (qAbs(new_rect.height()) - qAbs(profile_height)) * getSign(profile_height);
|
||||
|
||||
// applique les differences aux segments
|
||||
QHash<ConducerSegmentProfile *, qreal> segments_lengths;
|
||||
segments_lengths.unite(shareOffsetBetweenSegments(h_diff, conducer_profile.horizontalSegments()));
|
||||
segments_lengths.unite(shareOffsetBetweenSegments(v_diff, conducer_profile.verticalSegments()));
|
||||
|
||||
// en deduit egalement les coefficients d'inversion (-1 pour une inversion, +1 pour conserver le meme sens)
|
||||
int horiz_coeff = getCoeff(new_rect.width(), profile_width);
|
||||
int verti_coeff = getCoeff(new_rect.height(), profile_height);
|
||||
|
||||
// en deduit les coefficients de "redimensionnement"
|
||||
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;
|
||||
/*
|
||||
if (!orig_dist_2_terms_x || !orig_dist_2_terms_y) {
|
||||
qDebug() << "ca va planter";
|
||||
PR(coeff_x)
|
||||
PR(coeff_y)
|
||||
}
|
||||
*/
|
||||
// genere les nouveaux points
|
||||
int limite = moves_x.size() - 1;
|
||||
int coeff = type_trajet_x ? 1 : -1;
|
||||
|
||||
QList<QPointF> points;
|
||||
points << (type_trajet_x ? new_p1 : new_p2);
|
||||
for (int i = 0 ; i < limite ; ++ i) {
|
||||
points << new_p1;
|
||||
int limit = conducer_profile.segments.count() - 1;
|
||||
for (int i = 0 ; i < limit ; ++ i) {
|
||||
// dernier point
|
||||
QPointF previous_point = points.last();
|
||||
|
||||
// profil de segment de conducteur en cours
|
||||
ConducerSegmentProfile *csp = conducer_profile.segments.at(i);
|
||||
|
||||
// coefficient et offset a utiliser pour ce point
|
||||
qreal coeff = csp -> isHorizontal ? horiz_coeff : verti_coeff;
|
||||
qreal offset_applied = segments_lengths[csp];
|
||||
|
||||
// applique l'offset et le coeff au point
|
||||
if (csp -> isHorizontal) {
|
||||
points << QPointF (
|
||||
previous_point.x() + (moves_x.at(i) * coeff_x * coeff),
|
||||
previous_point.y() + (moves_y.at(i) * coeff_y * coeff)
|
||||
previous_point.x() + (coeff * offset_applied),
|
||||
previous_point.y()
|
||||
);
|
||||
} else {
|
||||
points << QPointF (
|
||||
previous_point.x(),
|
||||
previous_point.y() + (coeff * offset_applied)
|
||||
);
|
||||
}
|
||||
points << (type_trajet_x ? new_p2 : new_p1);
|
||||
}
|
||||
points << new_p2;
|
||||
pointsToSegments(points);
|
||||
segmentsToPath();
|
||||
}
|
||||
|
||||
/**
|
||||
@param offset Longueur a repartir entre les segments
|
||||
@param segments_list Segments sur lesquels il faut repartir la longueur
|
||||
@param precision seuil en-deca duquel on considere qu'il ne reste rien a repartir
|
||||
*/
|
||||
QHash<ConducerSegmentProfile *, qreal> Conducer::shareOffsetBetweenSegments(
|
||||
const qreal &offset,
|
||||
const QList<ConducerSegmentProfile *> &segments_list,
|
||||
const qreal &precision
|
||||
) const {
|
||||
// construit le QHash qui sera retourne
|
||||
QHash<ConducerSegmentProfile *, qreal> segments_hash;
|
||||
foreach(ConducerSegmentProfile *csp, segments_list) {
|
||||
segments_hash.insert(csp, csp -> length);
|
||||
}
|
||||
|
||||
// memorise le signe de la longueur de chaque segement
|
||||
QHash<ConducerSegmentProfile *, int> segments_signs;
|
||||
foreach(ConducerSegmentProfile *csp, segments_hash.keys()) {
|
||||
segments_signs.insert(csp, getSign(csp -> length));
|
||||
}
|
||||
|
||||
//qDebug() << "repartition d'un offset de" << offset << "px sur" << segments_list.count() << "segments";
|
||||
|
||||
// repartit l'offset sur les segments
|
||||
qreal remaining_offset = offset;
|
||||
while (remaining_offset > precision || remaining_offset < -precision) {
|
||||
// recupere le nombre de segments differents ayant une longueur non nulle
|
||||
uint segments_count = 0;
|
||||
foreach(ConducerSegmentProfile *csp, segments_hash.keys()) if (segments_hash[csp]) ++ segments_count;
|
||||
//qDebug() << " remaining_offset =" << remaining_offset;
|
||||
qreal local_offset = remaining_offset / segments_count;
|
||||
//qDebug() << " repartition d'un offset local de" << local_offset << "px sur" << segments_count << "segments";
|
||||
remaining_offset = 0.0;
|
||||
foreach(ConducerSegmentProfile *csp, segments_hash.keys()) {
|
||||
// ignore les segments de longueur nulle
|
||||
if (!segments_hash[csp]) continue;
|
||||
// applique l'offset au segment
|
||||
//qreal segment_old_length = segments_hash[csp];
|
||||
segments_hash[csp] += local_offset;
|
||||
|
||||
// (la longueur du segment change de signe) <=> (le segment n'a pu absorbe tout l'offset)
|
||||
if (segments_signs[csp] != getSign(segments_hash[csp])) {
|
||||
|
||||
// on remet le trop-plein dans la reserve d'offset
|
||||
remaining_offset += qAbs(segments_hash[csp]) * getSign(local_offset);
|
||||
//qDebug() << " trop-plein de" << qAbs(segments_hash[csp]) * getSign(local_offset) << "remaining_offset =" << remaining_offset;
|
||||
segments_hash[csp] = 0.0;
|
||||
} else {
|
||||
//qDebug() << " offset local de" << local_offset << "accepte";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return(segments_hash);
|
||||
}
|
||||
|
||||
/**
|
||||
Calcule un trajet "par defaut" pour le conducteur
|
||||
@param p1 Coordonnees du point d'amarrage de la borne 1
|
||||
@@ -207,7 +287,6 @@ void Conducer::priv_calculeConducer(const QPointF &p1, QET::Orientation o1, cons
|
||||
// s'assure qu'il n'y a ni points
|
||||
QList<QPointF> points;
|
||||
|
||||
type_trajet_x = p1.x() < p2.x();
|
||||
// mappe les points par rapport a la scene
|
||||
sp1 = mapFromScene(p1);
|
||||
sp2 = mapFromScene(p2);
|
||||
@@ -282,6 +361,13 @@ void Conducer::priv_calculeConducer(const QPointF &p1, QET::Orientation o1, cons
|
||||
// prolongement de la borne d'arrivee
|
||||
points << arrivee0;
|
||||
|
||||
// inverse eventuellement l'ordre des points afin que le trajet soit exprime de la borne 1 vers la borne 2
|
||||
if (newp1.x() > newp2.x()) {
|
||||
QList<QPointF> points2;
|
||||
for (int i = points.size() - 1 ; i >= 0 ; -- i) points2 << points.at(i);
|
||||
points = points2;
|
||||
}
|
||||
|
||||
pointsToSegments(points);
|
||||
segmentsToPath();
|
||||
}
|
||||
@@ -480,7 +566,7 @@ void Conducer::mouseMoveEvent(QGraphicsSceneMouseEvent *e) {
|
||||
|
||||
// application du deplacement
|
||||
modified_path = true;
|
||||
updatePoints();
|
||||
has_to_save_profile = true;
|
||||
segmentsToPath();
|
||||
calculateTextItemPosition();
|
||||
}
|
||||
@@ -496,6 +582,10 @@ void Conducer::mouseReleaseEvent(QGraphicsSceneMouseEvent *e) {
|
||||
// clic gauche
|
||||
moving_point = false;
|
||||
moving_segment = false;
|
||||
if (has_to_save_profile) {
|
||||
saveProfile();
|
||||
has_to_save_profile = false;
|
||||
}
|
||||
setZValue(previous_z_value);
|
||||
QGraphicsPathItem::mouseReleaseEvent(e);
|
||||
calculateTextItemPosition();
|
||||
@@ -577,24 +667,6 @@ QPainterPath Conducer::shape() const {
|
||||
return(area);
|
||||
}
|
||||
|
||||
/**
|
||||
Met à jour deux listes de reels.
|
||||
*/
|
||||
void Conducer::updatePoints() {
|
||||
QList<QPointF> points = segmentsToPoints();
|
||||
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();
|
||||
}
|
||||
|
||||
/**
|
||||
Renvoie une valeur donnee apres l'avoir bornee entre deux autres valeurs,
|
||||
en y ajoutant une marge interne.
|
||||
@@ -603,8 +675,8 @@ void Conducer::updatePoints() {
|
||||
@param bound2 borne 2
|
||||
@return La valeur bornee
|
||||
*/
|
||||
qreal Conducer::conducer_bound(qreal tobound, qreal bound1, qreal bound2) {
|
||||
qreal space = 5.0;
|
||||
qreal Conducer::conducer_bound(qreal tobound, qreal bound1, qreal bound2, qreal space) {
|
||||
qDebug() << "will bound" << tobound << "between" << bound1 << "and" << bound2 ;
|
||||
if (bound1 < bound2) {
|
||||
return(qBound(bound1 + space, tobound, bound2 - space));
|
||||
} else {
|
||||
@@ -625,15 +697,15 @@ qreal Conducer::conducer_bound(qreal tobound, qreal bound, bool positive) {
|
||||
}
|
||||
|
||||
/**
|
||||
@param type Type de Segments
|
||||
@return Le nombre de segments composant le conducteur.
|
||||
*/
|
||||
int Conducer::nbSegments() const {
|
||||
if (segments == NULL) return(0);
|
||||
int nb_seg = 1;
|
||||
ConducerSegment *segment = segments;
|
||||
while (segment -> hasNextSegment()) {
|
||||
++ nb_seg;
|
||||
segment = segment -> nextSegment();
|
||||
uint Conducer::nbSegments(QET::ConducerSegmentType type) const {
|
||||
QList<ConducerSegment *> segments_list = segmentsList();
|
||||
if (type == QET::Both) return(segments_list.count());
|
||||
uint nb_seg = 0;
|
||||
foreach(ConducerSegment *conducer_segment, segments_list) {
|
||||
if (conducer_segment -> type() == type) ++ nb_seg;
|
||||
}
|
||||
return(nb_seg);
|
||||
}
|
||||
@@ -740,15 +812,14 @@ bool Conducer::fromXml(QDomElement &e) {
|
||||
|
||||
// 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());
|
||||
qreal expected_width = t2.x() - t1.x();
|
||||
qreal expected_height = t2.y() - t1.y();
|
||||
qreal precision = std::numeric_limits<qreal>::epsilon();
|
||||
if (
|
||||
expected_width > width + precision ||\
|
||||
@@ -760,7 +831,7 @@ bool Conducer::fromXml(QDomElement &e) {
|
||||
/* on recree les segments a partir des donnes XML */
|
||||
// cree la liste de points
|
||||
QList<QPointF> points_list;
|
||||
points_list << (t1.x() < t2.x() ? t1 : t2);
|
||||
points_list << t1;
|
||||
for (int i = 0 ; i < segments_x.size() ; ++ i) {
|
||||
points_list << QPointF(
|
||||
points_list.last().x() + segments_x.at(i),
|
||||
@@ -772,11 +843,7 @@ bool Conducer::fromXml(QDomElement &e) {
|
||||
|
||||
// initialise divers parametres lies a la modification des conducteurs
|
||||
modified_path = true;
|
||||
moves_x = segments_x;
|
||||
moves_y = segments_y;
|
||||
type_trajet_x = t1.x() < t2.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();
|
||||
saveProfile();
|
||||
|
||||
segmentsToPath();
|
||||
return(true);
|
||||
@@ -800,20 +867,29 @@ QDomElement Conducer::toXml(QDomDocument &d, QHash<Terminal *, int> &table_adr_i
|
||||
if (!modified_path) return(e);
|
||||
|
||||
// parcours et export des segments
|
||||
ConducerSegment *segment = segments;
|
||||
QDomElement current_segment;
|
||||
while (segment -> hasNextSegment()) {
|
||||
foreach(ConducerSegment *segment, segmentsList()) {
|
||||
current_segment = d.createElement("segment");
|
||||
current_segment.setAttribute("orientation", segment -> isHorizontal() ? "horizontal" : "vertical");
|
||||
current_segment.setAttribute("length", segment -> length());
|
||||
e.appendChild(current_segment);
|
||||
}
|
||||
return(e);
|
||||
}
|
||||
|
||||
/// @return les segments de ce conducteur
|
||||
const QList<ConducerSegment *> Conducer::segmentsList() const {
|
||||
if (segments == NULL) return(QList<ConducerSegment *>());
|
||||
|
||||
QList<ConducerSegment *> segments_vector;
|
||||
ConducerSegment *segment = segments;
|
||||
|
||||
while (segment -> hasNextSegment()) {
|
||||
segments_vector << 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);
|
||||
return(e);
|
||||
segments_vector << segment;
|
||||
return(segments_vector);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -859,3 +935,28 @@ ConducerSegment *Conducer::middleSegment() {
|
||||
void Conducer::calculateTextItemPosition() {
|
||||
text_item -> setPos(middleSegment() -> middle());
|
||||
}
|
||||
|
||||
/**
|
||||
Sauvegarde le profil courant du conducteur pour l'utiliser ulterieurement
|
||||
dans priv_modifieConducer.
|
||||
*/
|
||||
void Conducer::saveProfile() {
|
||||
conducer_profile = ConducerProfile(this);
|
||||
}
|
||||
|
||||
/**
|
||||
@param value1 Premiere valeur
|
||||
@param value2 Deuxieme valeur
|
||||
@return 1 si les deux valeurs sont de meme signe, -1 sinon
|
||||
*/
|
||||
int Conducer::getCoeff(const qreal &value1, const qreal &value2) {
|
||||
return(getSign(value1) * getSign(value2));
|
||||
}
|
||||
|
||||
/**
|
||||
@param value valeur
|
||||
@return 1 si valeur est negatif, 1 s'il est positif ou nul
|
||||
*/
|
||||
int Conducer::getSign(const qreal &value) {
|
||||
return(value < 0 ? -1 : 1);
|
||||
}
|
||||
|
||||
21
conducer.h
21
conducer.h
@@ -2,6 +2,7 @@
|
||||
#define CONDUCTEUR_H
|
||||
#include <QtGui>
|
||||
#include "terminal.h"
|
||||
#include "conducerprofile.h"
|
||||
class ConducerSegment;
|
||||
class Element;
|
||||
/**
|
||||
@@ -20,6 +21,7 @@ class Conducer : public QGraphicsPathItem {
|
||||
// attributs
|
||||
public:
|
||||
enum { Type = UserType + 1001 };
|
||||
|
||||
///Premiere borne a laquelle le fil est rattache
|
||||
Terminal *terminal1;
|
||||
///Deuxieme borne a laquelle le fil est rattache
|
||||
@@ -30,11 +32,6 @@ class Conducer : public QGraphicsPathItem {
|
||||
bool destroyed;
|
||||
QGraphicsTextItem *text_item;
|
||||
ConducerSegment *segments;
|
||||
QList<qreal> moves_x;
|
||||
QList<qreal> moves_y;
|
||||
qreal orig_dist_2_terms_x;
|
||||
qreal orig_dist_2_terms_y;
|
||||
bool type_trajet_x;
|
||||
QPointF press_point;
|
||||
bool moving_point;
|
||||
bool moving_segment;
|
||||
@@ -42,6 +39,8 @@ class Conducer : public QGraphicsPathItem {
|
||||
qreal previous_z_value;
|
||||
ConducerSegment *moved_segment;
|
||||
bool modified_path;
|
||||
bool has_to_save_profile;
|
||||
ConducerProfile conducer_profile;
|
||||
static QPen conducer_pen;
|
||||
static QBrush conducer_brush;
|
||||
static bool pen_and_brush_initialized;
|
||||
@@ -61,6 +60,7 @@ class Conducer : public QGraphicsPathItem {
|
||||
static bool valideXml(QDomElement &);
|
||||
bool fromXml(QDomElement &);
|
||||
QDomElement toXml(QDomDocument &, QHash<Terminal *, int> &) const;
|
||||
const QList<ConducerSegment *> segmentsList() const;
|
||||
|
||||
protected:
|
||||
void mousePressEvent(QGraphicsSceneMouseEvent *);
|
||||
@@ -70,16 +70,19 @@ class Conducer : public QGraphicsPathItem {
|
||||
|
||||
private:
|
||||
void segmentsToPath();
|
||||
void updatePoints();
|
||||
void saveProfile();
|
||||
void priv_calculeConducer(const QPointF &, QET::Orientation, const QPointF &, QET::Orientation);
|
||||
void priv_modifieConducer(const QPointF &, QET::Orientation, const QPointF &, QET::Orientation);
|
||||
int nbSegments() const;
|
||||
uint nbSegments(QET::ConducerSegmentType = QET::Both) const;
|
||||
QList<QPointF> segmentsToPoints() const;
|
||||
void pointsToSegments(QList<QPointF>);
|
||||
bool hasClickedOn(QPointF, QPointF) const;
|
||||
void calculateTextItemPosition();
|
||||
static int getCoeff(const qreal &, const qreal &);
|
||||
static int getSign(const qreal &);
|
||||
QHash<ConducerSegmentProfile *, qreal> shareOffsetBetweenSegments(const qreal &offset, const QList<ConducerSegmentProfile *> &, const qreal & = 0.01) const;
|
||||
static QPointF extendTerminal(const QPointF &, QET::Orientation, qreal = 12.0);
|
||||
static qreal conducer_bound(qreal tobound, qreal bound1, qreal bound2);
|
||||
static qreal conducer_bound(qreal tobound, qreal bound, bool positive);
|
||||
static qreal conducer_bound(qreal, qreal, qreal, qreal = 0.0);
|
||||
static qreal conducer_bound(qreal, qreal, bool);
|
||||
};
|
||||
#endif
|
||||
|
||||
92
conducerprofile.cpp
Normal file
92
conducerprofile.cpp
Normal file
@@ -0,0 +1,92 @@
|
||||
#include "conducerprofile.h"
|
||||
#include "conducer.h"
|
||||
#include "conducersegmentprofile.h"
|
||||
|
||||
/// Constructeur
|
||||
ConducerProfile::ConducerProfile() {
|
||||
}
|
||||
|
||||
/**
|
||||
Constructeur
|
||||
@param Conducer conducteur dont il faut extraire le profil
|
||||
*/
|
||||
ConducerProfile::ConducerProfile(Conducer *conducer) {
|
||||
foreach(ConducerSegment *conducer_segment, conducer -> segmentsList()) {
|
||||
segments << new ConducerSegmentProfile(conducer_segment);
|
||||
}
|
||||
beginOrientation = conducer -> terminal1 -> orientation();
|
||||
endOrientation = conducer -> terminal2 -> orientation();
|
||||
}
|
||||
|
||||
/// destructeur
|
||||
ConducerProfile::~ConducerProfile() {
|
||||
}
|
||||
|
||||
/// @return true si le profil est nul
|
||||
bool ConducerProfile::isNull() const {
|
||||
return(segments.isEmpty());
|
||||
}
|
||||
|
||||
/// @return la largeur occupee par le conducteur
|
||||
qreal ConducerProfile::width() const {
|
||||
qreal width = 0.0;
|
||||
foreach(ConducerSegmentProfile *csp, segments) {
|
||||
if (csp -> isHorizontal) width += csp -> length;
|
||||
}
|
||||
return(width);
|
||||
}
|
||||
|
||||
/// @return la hauteur occupee par le conducteur
|
||||
qreal ConducerProfile::height() const{
|
||||
qreal height = 0.0;
|
||||
foreach(ConducerSegmentProfile *csp, segments) {
|
||||
if (!csp -> isHorizontal) height += csp -> length;
|
||||
}
|
||||
return(height);
|
||||
}
|
||||
|
||||
/**
|
||||
@param type Type de Segments
|
||||
@return Le nombre de segments composant le conducteur.
|
||||
*/
|
||||
uint ConducerProfile::nbSegments(QET::ConducerSegmentType type) const {
|
||||
if (type == QET::Both) return(segments.count());
|
||||
uint nb_seg = 0;
|
||||
foreach(ConducerSegmentProfile *csp, segments) {
|
||||
if (type == QET::Horizontal && csp -> isHorizontal) ++ nb_seg;
|
||||
else if (type == QET::Vertical && !csp -> isHorizontal) ++ nb_seg;
|
||||
}
|
||||
return(nb_seg);
|
||||
}
|
||||
|
||||
/// @return les segments horizontaux de ce profil
|
||||
QList<ConducerSegmentProfile *> ConducerProfile::horizontalSegments() {
|
||||
QList<ConducerSegmentProfile *> segments_list;
|
||||
foreach(ConducerSegmentProfile *csp, segments) {
|
||||
if (csp -> isHorizontal) segments_list << csp;
|
||||
}
|
||||
return(segments_list);
|
||||
}
|
||||
|
||||
/// @return les segments verticaux de ce profil
|
||||
QList<ConducerSegmentProfile *> ConducerProfile::verticalSegments() {
|
||||
QList<ConducerSegmentProfile *> segments_list;
|
||||
foreach(ConducerSegmentProfile *csp, segments) {
|
||||
if (!csp -> isHorizontal) segments_list << csp;
|
||||
}
|
||||
return(segments_list);
|
||||
}
|
||||
|
||||
/**
|
||||
Permet de debugger un profil de conducteur
|
||||
@param d Object QDebug a utiliser pour l'affichage des informations de debug
|
||||
@param t Profil de conducteur a debugger
|
||||
*/
|
||||
QDebug &operator<<(QDebug d, ConducerProfile &t) {
|
||||
d << "ConducerProfile {";
|
||||
foreach(ConducerSegmentProfile *csp, t.segments) {
|
||||
d << "CSP" << (csp -> isHorizontal ? "horizontal" : "vertical") << ":" << csp -> length << ",";
|
||||
}
|
||||
d << "}";
|
||||
return(d.space());
|
||||
}
|
||||
34
conducerprofile.h
Normal file
34
conducerprofile.h
Normal file
@@ -0,0 +1,34 @@
|
||||
#ifndef CONDUCER_PROFILE_H
|
||||
#define CONDUCER_PROFILE_H
|
||||
#include <QList>
|
||||
#include "qet.h"
|
||||
class Conducer;
|
||||
class ConducerSegmentProfile;
|
||||
/**
|
||||
Cette classe contient le profil (= les caracteristiques essentielles) d'un
|
||||
conducteur.
|
||||
*/
|
||||
class ConducerProfile {
|
||||
public:
|
||||
// constructeurs, destructeur
|
||||
ConducerProfile();
|
||||
ConducerProfile(Conducer *conducer);
|
||||
virtual ~ConducerProfile();
|
||||
|
||||
// attributs
|
||||
public:
|
||||
QList<ConducerSegmentProfile *> segments;
|
||||
QET::Orientation beginOrientation;
|
||||
QET::Orientation endOrientation;
|
||||
|
||||
// methodes
|
||||
public:
|
||||
bool isNull() const;
|
||||
qreal width() const;
|
||||
qreal height() const;
|
||||
uint nbSegments(QET::ConducerSegmentType) const;
|
||||
QList<ConducerSegmentProfile *> horizontalSegments();
|
||||
QList<ConducerSegmentProfile *> verticalSegments();
|
||||
};
|
||||
QDebug &operator<<(QDebug d, ConducerProfile &);
|
||||
#endif
|
||||
@@ -25,7 +25,6 @@ ConducerSegment::ConducerSegment(
|
||||
Destructeur - Relie le segment precedent au suivant
|
||||
*/
|
||||
ConducerSegment::~ConducerSegment() {
|
||||
//qDebug() << "~ConducerSegment()" << (void *)this;
|
||||
if (hasPreviousSegment()) previousSegment() -> setNextSegment(nextSegment());
|
||||
if (hasNextSegment()) nextSegment() -> setPreviousSegment(previousSegment());
|
||||
}
|
||||
@@ -494,3 +493,7 @@ qreal ConducerSegment::length() const {
|
||||
return(secondPoint().y() - firstPoint().y());
|
||||
}
|
||||
}
|
||||
|
||||
QET::ConducerSegmentType ConducerSegment::type() const {
|
||||
return(isHorizontal() ? QET::Horizontal : QET::Vertical);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#ifndef CONDUCER_SEGMENT_H
|
||||
#define CONDUCER_SEGMENT_H
|
||||
#include <QPointF>
|
||||
#include "qet.h"
|
||||
/**
|
||||
Cette classe represente un segment de conducteur.
|
||||
*/
|
||||
@@ -41,6 +42,7 @@ class ConducerSegment {
|
||||
QPointF middle() const;
|
||||
bool isHorizontal() const;
|
||||
bool isVertical() const;
|
||||
QET::ConducerSegmentType type() const;
|
||||
qreal length() const;
|
||||
bool canMove1stPointX(const qreal &, qreal &) const;
|
||||
bool canMove2ndPointX(const qreal &, qreal &) const;
|
||||
|
||||
42
conducersegmentprofile.h
Normal file
42
conducersegmentprofile.h
Normal file
@@ -0,0 +1,42 @@
|
||||
#ifndef CONDUCER_SEGMENT_PROFILE_H
|
||||
#define CONDUCER_SEGMENT_PROFILE_H
|
||||
#include <QtCore>
|
||||
#include "conducersegment.h"
|
||||
/**
|
||||
Cette classe contient le profil (= les caracteristiques essentielles) d'un
|
||||
segment de conducteur.
|
||||
*/
|
||||
class ConducerSegmentProfile {
|
||||
// constructeurs, destructeur
|
||||
public:
|
||||
/**
|
||||
Constructeur
|
||||
@param l longueur du segment
|
||||
@param ori true si le segment est horizontal, false s'il est vertical
|
||||
*/
|
||||
ConducerSegmentProfile(qreal l, bool ori = true) :
|
||||
length(l),
|
||||
isHorizontal(ori)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
Constructeur
|
||||
@param segment ConducerSegment dont il faut extraire le profil
|
||||
*/
|
||||
ConducerSegmentProfile(ConducerSegment *segment) :
|
||||
length(segment -> length()),
|
||||
isHorizontal(segment -> isHorizontal())
|
||||
{
|
||||
}
|
||||
|
||||
/// Destructeur
|
||||
virtual ~ConducerSegmentProfile() {
|
||||
}
|
||||
|
||||
// attributs
|
||||
public:
|
||||
qreal length; /// longueur du segment
|
||||
bool isHorizontal; /// orientation du segment
|
||||
};
|
||||
#endif
|
||||
@@ -60,7 +60,9 @@ HEADERS += aboutqet.h \
|
||||
editor/texteditor.h \
|
||||
editor/textfieldeditor.h \
|
||||
elementscategorydeleter.h \
|
||||
elementdeleter.h
|
||||
elementdeleter.h \
|
||||
conducersegmentprofile.h \
|
||||
conducerprofile.h
|
||||
SOURCES += aboutqet.cpp \
|
||||
borderinset.cpp \
|
||||
conducer.cpp \
|
||||
@@ -114,7 +116,8 @@ SOURCES += aboutqet.cpp \
|
||||
editor/texteditor.cpp \
|
||||
editor/textfieldeditor.cpp \
|
||||
elementscategorydeleter.cpp \
|
||||
elementdeleter.cpp
|
||||
elementdeleter.cpp \
|
||||
conducerprofile.cpp
|
||||
RESOURCES += qelectrotech.qrc
|
||||
TRANSLATIONS += lang/qet_en.ts lang/qt_fr.ts
|
||||
QT += xml
|
||||
|
||||
1
qet.h
1
qet.h
@@ -8,6 +8,7 @@
|
||||
*/
|
||||
namespace QET {
|
||||
enum Orientation {North, East, South, West};
|
||||
enum ConducerSegmentType { Horizontal = 1, Vertical = 2, Both = 3 };
|
||||
QET::Orientation nextOrientation(QET::Orientation);
|
||||
QET::Orientation previousOrientation(QET::Orientation);
|
||||
QET::Orientation orientationFromString(const QString &);
|
||||
|
||||
Reference in New Issue
Block a user