diff --git a/sources/diagram.cpp b/sources/diagram.cpp index e4935170e..ae2f765bf 100644 --- a/sources/diagram.cpp +++ b/sources/diagram.cpp @@ -31,6 +31,7 @@ #include "qetgraphicsitem/independenttextitem.h" #include "qetapp.h" #include "qetgraphicsitem/diagramimageitem.h" +#include "qetgraphicsitem/conductor.h" #include "qetgraphicsitem/qetshapeitem.h" #include "terminal.h" #include "elementtextsmover.h" @@ -78,6 +79,8 @@ Diagram::Diagram(QObject *parent) : &border_and_titleblock, SIGNAL(diagramTitleChanged(const QString &)), this, SLOT(titleChanged(const QString &)) ); + + _binaryGrid = new BinaryGrid(this); } /** @@ -105,6 +108,8 @@ Diagram::~Diagram() { } qDeleteAll (deletable_items); + + delete _binaryGrid; } /** @@ -189,6 +194,35 @@ void Diagram::keyReleaseEvent(QKeyEvent *e) { bool transmit_event = true; if (!isReadOnly()) { // detecte le relachement d'une touche de direction ( = deplacement d'elements) + if ( e -> key() == Qt::Key_C) { + Conductor::bDebugGrid= !Conductor::bDebugGrid; + update(); + } + else if ( e -> key() == Qt::Key_P) { + Conductor::bAffPoint = !Conductor::bAffPoint; + update(); + } + else if ( e -> key() == Qt::Key_S) { + Conductor::bSmooth = !Conductor::bSmooth; + Conductor::reBuild(); + update(); + } + else if ( e -> key() == Qt::Key_D) { + Conductor::bDebug = !Conductor::bDebug; + Conductor::reBuild(); + update(); + } + else if ( e -> key() == Qt::Key_Plus) { + Conductor::iIndiceDebug++; + Conductor::reBuild(); + update(); + } + else if ( e -> key() == Qt::Key_Minus) { + Conductor::iIndiceDebug--; + Conductor::reBuild(); + update(); + } + if ( (e -> key() == Qt::Key_Left || e -> key() == Qt::Key_Right || e -> key() == Qt::Key_Up || e -> key() == Qt::Key_Down) && diff --git a/sources/diagram.h b/sources/diagram.h index 1cb25f02b..6a37e8425 100644 --- a/sources/diagram.h +++ b/sources/diagram.h @@ -27,6 +27,7 @@ #include "numerotationcontext.h" #include "qetproject.h" #include "properties/xrefproperties.h" +#include "binarygrid.h" class Conductor; class CustomElement; @@ -43,6 +44,7 @@ class Terminal; class ConductorTextItem; class DiagramImageItem; class ElementTextsMover; +class BinaryGrid; /** This class represents an electric diagram. It manages its various child elements, conductors and texts and handles their graphic rendering. @@ -224,6 +226,9 @@ class Diagram : public QGraphicsScene { void editElementRequired(const ElementsLocation &); void reportPropertiesChanged(QString); void XRefPropertiesChanged(); + + public: + BinaryGrid* _binaryGrid; }; Q_DECLARE_METATYPE(Diagram *) diff --git a/sources/diagramview.cpp b/sources/diagramview.cpp index 040253da7..2435da2c7 100644 --- a/sources/diagramview.cpp +++ b/sources/diagramview.cpp @@ -447,6 +447,7 @@ void DiagramView::paste(const QPointF &pos, QClipboard::Mode clipboard_mode) { // objet pour recuperer le contenu ajoute au schema par le coller DiagramContent content_pasted; scene -> fromXml(document_xml, pos, false, &content_pasted); + qDebug()<< "PASTE" << texte_presse_papier; // si quelque chose a effectivement ete ajoute au schema, on cree un objet d'annulation if (content_pasted.count()) { diff --git a/sources/qetapp.cpp b/sources/qetapp.cpp index 57c59755c..2edec5d3b 100644 --- a/sources/qetapp.cpp +++ b/sources/qetapp.cpp @@ -59,6 +59,7 @@ RecentFiles *QETApp::projects_recent_files_ = 0; RecentFiles *QETApp::elements_recent_files_ = 0; AboutQET *QETApp::about_dialog_ = 0; TitleBlockTemplate *QETApp::default_titleblock_template_ = 0; +bool QETApp::bConductor2 = false; /** Constructeur diff --git a/sources/qetapp.h b/sources/qetapp.h index 337ab0a3a..2bce71c23 100644 --- a/sources/qetapp.h +++ b/sources/qetapp.h @@ -131,6 +131,7 @@ class QETApp : public QETSingleApplication { static QList titleBlockTemplateEditors(QETProject *); static QTextOrientationSpinBoxWidget *createTextOrientationSpinBoxWidget(); static TitleBlockTemplate *defaultTitleBlockTemplate(); + static bool bConductor2; protected: #ifdef Q_OS_DARWIN diff --git a/sources/qetarguments.cpp b/sources/qetarguments.cpp index 42b685e99..6f6a3bd88 100644 --- a/sources/qetarguments.cpp +++ b/sources/qetarguments.cpp @@ -16,6 +16,7 @@ along with QElectroTech. If not, see . */ #include "qetarguments.h" +#include "qetapp.h" #include "titleblock/templatescollection.h" /** @@ -249,6 +250,9 @@ void QETArguments::handleOptionArgument(const QString &option) { print_license_ = true; options_ << option; return; + } else if (option == QString("--conductor2")) { + QETApp::bConductor2 = true; + return; } #ifdef QET_ALLOW_OVERRIDE_CED_OPTION diff --git a/sources/qetgraphicsitem/Mathlib.h b/sources/qetgraphicsitem/Mathlib.h new file mode 100644 index 000000000..82c06a006 --- /dev/null +++ b/sources/qetgraphicsitem/Mathlib.h @@ -0,0 +1,231 @@ +/*************************************************************************** + * Mathlib + * + * Copyright (C) 2003-2004, Alexander Zaprjagaev + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + *************************************************************************** + * Update 2004/08/19 + * + * added ivec2, ivec3 & ivec4 methods + * vec2d, vec3d & vec4d data : added texture coords (s,t,p,q) and color enums (r,g,b,a) + * mat3d & mat4d : added multiple double constructor ad modified methods returning mat3d or mat4d + * optimisations like "x / 2.0f" replaced by faster "x * 0.5f" + * defines of multiples usefull maths values and radian/degree conversions + * vec2d : added methods : set, reset, compare, dot, closestPointOnLine, closestPointOnSegment, + * projectionOnLine, lerp, angle + * vec3d : added methods : set, reset, compare, dot, cross, closestPointOnLine, closestPointOnSegment, + * projectionOnLine, lerp, angle + * vec4d : added methods : set, reset, compare + *************************************************************************** + * Update 2014/08/20 + * + * Transform float to double + * for using with QT program + * author : Rene Negre + *************************************************************************** + */ + +#ifndef __HMATHLIB_D__ +#define __HMATHLIB_D__ + +#include +#include +#include + +#define EPSILON 0.00000001 +//#define M_PI 3.141592653589793238462643383279f // PI +#define M_PIDIV2 1.570796326794896619231321691639f // PI / 2 +#define M_2PI 6.283185307179586476925286766559f // 2 * PI +#define M_PI2 9.869604401089358618834490999876f // PI au carre +#define M_PIDIV180 0.01745329251994329576923690768488f // PI / 180 +#define M_180DIVPI 57.295779513082320876798154814105f // 180 / PI + +#define DegToRadd(a) (a)*=M_PIDIV180 +#define RadToDegd(a) (a)*=M_180DIVPI +#define DEG2RADd(a) ((a)*M_PIDIV180) +#define RAD2DEGd(a) ((a)*M_180DIVPI) +#define RADIANSd(a) ((a)*M_PIDIV180) +#define DEGRESd(a) ((a)*M_180DIVPI) +#define DegToRad DEG2RADd + + +const double INV_RAND_MAX = 1.0 / (RAND_MAX); +const double INV_RAND_MAXd = 1.0 / (RAND_MAX ); +inline double randomd(double max=1.0) { return max * rand() * INV_RAND_MAX; } +inline double randomd(double min, double max) { return min + (max - min) * INV_RAND_MAX * rand(); } +inline int randomd(int max=RAND_MAX) { return rand()%(max+1); } + +class vec2d; +class ivec2; + + +/*****************************************************************************/ +/* */ +/* vec2d */ +/* */ +/*****************************************************************************/ + +class vec2d { +public: + static int count; + vec2d(void) : x(0), y(0) { count++; } + vec2d(double _x,double _y) : x(_x), y(_y) { count++; } + vec2d(const double *_v) : x(_v[0]), y(_v[1]) { count++; } + vec2d(const vec2d &_p1, const vec2d & _p2) : x(_p2.x-_p1.x), y(_p2.y-_p1.y) { count++; } + vec2d(const QPointF &_qp) : x(_qp.x()), y(_qp.y()) { count++; } + + ~vec2d() { count--; } + + bool operator==(const vec2d &_v) { return (fabs(this->x - _v.x) < EPSILON && fabs(this->y - _v.y) < EPSILON); } + int operator!=(const vec2d &_v) { return !(*this == _v); } + + vec2d &operator=(double _f) { this->x=_f; this->y=_f; return (*this); } + const vec2d operator*(double _f) const { return vec2d(this->x * _f,this->y * _f); } + const vec2d operator/(double _f) const { + if(fabs(_f) < EPSILON) return *this; + _f = 1.0f / _f; + return (*this) * _f; + } + const vec2d operator+(const vec2d &_v) const { return vec2d(this->x + _v.x,this->y + _v.y); } + const vec2d operator-() const { return vec2d(-this->x,-this->y); } + const vec2d operator-(const vec2d &_v) const { return vec2d(this->x - _v.x,this->y - _v.y); } + + vec2d &operator*=(double _f) { return *this = *this * _f; } + vec2d &operator/=(double _f) { return *this = *this / _f; } + vec2d &operator+=(const vec2d &_v) { return *this = *this + _v; } + vec2d &operator-=(const vec2d &_v) { return *this = *this - _v; } + + double operator*(const vec2d &_v) const { return this->x * _v.x + this->y * _v.y; } + + operator double*() { return this->v; } + operator const double*() const { return this->v; } +// double &operator[](int _i) { return this->v[_i]; } +// const double &operator[](int _i) const { return this->v[_i]; } + + void set(double _x,double _y) { this->x = _x; this->y = _y; } + void reset(void) { this->x = this->y = 0; } + double length(void) const { return sqrtf(this->x * this->x + this->y * this->y); } + double normalize(void) { + double inv,l = this->length(); + if(l < EPSILON) return 0.0f; + inv = 1.0f / l; + this->x *= inv; + this->y *= inv; + return l; + } + double dot(const vec2d &v) { return ((this->x*v.x) + (this->y*v.y)); } // Produit scalaire + bool compare(const vec2d &_v,double epsi=EPSILON) { return (fabs(this->x - _v.x) < epsi && fabs(this->y - _v.y) < epsi); } + // retourne les coordonnée du point le plus proche de *this sur la droite passant par vA et vB + vec2d closestPointOnLine(const vec2d &vA, const vec2d &vB) { return (((vB-vA) * this->projectionOnLine(vA, vB)) + vA); } + // retourne les coordonnée du point le plus proche de *this sur le segment vA,vB + vec2d closestPointOnSegment(const vec2d &vA, const vec2d &vB) { + double factor = this->projectionOnLine(vA, vB); + if (factor <= 0.0f) return vA; + if (factor >= 1.0f) return vB; + return (((vB-vA) * factor) + vA); + } + // retourne le facteur de la projection de *this sur la droite passant par vA et vB + double projectionOnLine(const vec2d &vA, const vec2d &vB) { + vec2d v(vB - vA); + return v.dot(*this - vA) / v.dot(v); + } + // Fonction d'interpolation linéaire entre 2 vecteurs + vec2d lerp(vec2d &u, vec2d &v, double factor) { return ((u * (1 - factor)) + (v * factor)); } + vec2d lerp(vec2d &u, vec2d &v, vec2d& factor) { return (vec2d((u.x * (1 - factor.x)) + (v.x * factor.x), (u.y * (1 - factor.y)) + (v.y * factor.y))); } + double angle(void) { return (double)atan2(this->y,this->x); } + double angle(const vec2d &v) { return (double)atan2(v.y-this->y,v.x-this->x); } + + vec2d mul(const vec2d &v) { return vec2d(this->x*=v.x, this->y*=v.y); } // Produit des ccordonnes + vec2d& mulCoord(const vec2d &v) { this->x*=v.x, this->y*=v.y; return *this; } // Produit des ccordonnes + double addCoord() { return this->x + this->y; } // Produit des ccordonnes + vec2d vabs(void) { return vec2d( fabs(this->x), fabs(this->y) ); } + void abs(void) { this->x = fabs(this->x); this->y = fabs(this->y); } + vec2d exch(void) { return vec2d( this->y, this->x ); } + QPointF toQPointF() { return QPointF(this->x, this->y); } + + vec2d vnormalize(void) { + double inv,l = this->length(); + if(l < EPSILON) return vec2d(0.0,0.0); + inv = 1.0f / l; + return vec2d(this->x * inv, this->y * inv); + } + + + union { + struct {double x,y;}; + struct {double s,t;}; + double v[2]; + }; +}; + +inline vec2d operator*(double fl, const vec2d& v) { return vec2d(v.x*fl, v.y*fl);} + +inline double Dot(const vec2d& a, const vec2d& b) { return(a.x*b.x+a.y*b.y); } + + +/*****************************************************************************/ +/* */ +/* ivec2 */ +/* */ +/*****************************************************************************/ + +class ivec2 { +public: + ivec2(void) : a(0), b(0) { } + ivec2(long _a,long _b) : a(_a), b(_b) { } + ivec2(const long *iv) : a(iv[0]), b(iv[1]) { } + ivec2(const ivec2 &iv) : a(iv.a), b(iv.b) { } + ivec2(const vec2d &v) : x((int)v.x), y((int)v.y) { } + + int operator==(const ivec2 &iv) { return ((this->a == iv.a) && (this->b == iv.b)); } + int operator!=(const ivec2 &iv) { return !(*this == iv); } + + ivec2 &operator=(long _i) { this->x=_i; this->y=_i; return (*this); } + const ivec2 operator*(long _i) const { return ivec2(this->a * _i,this->b * _i); } + const ivec2 operator/(long _i) const { return ivec2(this->a / _i,this->b / _i); } + const ivec2 operator+(const ivec2 &iv) const { return ivec2(this->a + iv.a,this->b + iv.b); } + const ivec2 operator-() const { return ivec2(-this->a,-this->b); } + const ivec2 operator-(const ivec2 &iv) const { return ivec2(this->a - iv.a,this->b - iv.b); } + + ivec2 &operator*=(long _i) { return *this = *this * _i; } + ivec2 &operator/=(long _i) { return *this = *this / _i; } + ivec2 &operator+=(const ivec2 &iv) { return *this = *this + iv; } + ivec2 &operator-=(const ivec2 &iv) { return *this = *this - iv; } + + long operator*(const ivec2 &iv) const { return this->a * iv.a + this->b * iv.b; } + + operator long*() { return this->i; } + operator const long*() const { return this->i; } +// long &operator[](int _i) { return this->i[_i]; } +// const long &operator[](int _i) const { return this->i[_i]; } + + void set(long _a,long _b) { this->a = _a; this->b = _b; } + void reset(void) { this->a = this->b = 0; } + void swap(ivec2 &iv) { long tmp=a; a=iv.a; iv.a=tmp; tmp=b; b=iv.b; iv.b=tmp; } + void swap(ivec2 *iv) { this->swap(*iv); } + + union { + struct {long a,b;}; + struct {long x,y;}; + long i[2]; + }; +}; + + + +#endif // __HMATHLIB_D__ + diff --git a/sources/qetgraphicsitem/binarygrid.cpp b/sources/qetgraphicsitem/binarygrid.cpp new file mode 100644 index 000000000..e029e2a57 --- /dev/null +++ b/sources/qetgraphicsitem/binarygrid.cpp @@ -0,0 +1,409 @@ +/* + * binarygrid.cpp + * + * Created on: 8 nov. 2014 + * Author: rene + */ + + + +#include +#include "element.h" +#include "binarygrid.h" + + +/* + * + */ +BinaryGrid::BinaryGrid( Diagram* d ) { + diagram = d; + reset(); +} + + +/* + * + */ +BinaryGrid::~BinaryGrid() { +} + + + + + +/* + * + */ +QString reverse( QString s ) { + QString ret = ""; + const int nb = s.count(); + for(int i=0; i elements = diagram -> elements(); + for ( int i=0; i terminals().size() == 0 ) continue; + + vec2d topLeft, bottomRight; + rect2side( &topLeft, &bottomRight, element -> boundingRectTrue() ); + + add2grid( topLeft, bottomRight, 3 ); + + QList conductors = element->conductors(); + const int nb = conductors.size(); + + for( int i=0; i 8 bits ??? + if ( uMask == 64 ) mask[n] = (U64)-1; + + for( int i=0; i 8 bits ??? + if ( uMask == 64 ) mask[n] = (U64)-1; + + for( int i=0; i v2.x || v1.y > v2.y ) { + vec2d v = vec2d( v1 ); + v1 = v2; + v2 = v; + } +} + + + +/* + * + */ +void BinaryGrid::add2grid( Conductor* pConductor ) { + QList vec2ds = pConductor -> getVec2ds(); + + const int nb = vec2ds.size() - 1; + for( int i=0; iscenePos()) ); + vec2d v2 = vec2d( vec2ds[i+1] + vec2d(pConductor->scenePos()) ); + + orderVect( v1, v2 ); + + vec2d vDir = vec2d( v1, v2 ); + if ( vDir.dot( vec2d(0.0,1.0) ) == 0 ) add2grid( v1, v2, VERT); + else add2grid( v1, v2, HORI ); + } +} + + + +/* + * + */ +bool BinaryGrid::testMask( U64* mask, int lineBeg, int lineEnd, int map ) { + for ( int i=lineBeg; i<=lineEnd; i++ ) { + for( int j=0; j<5; j++ ) { + U64 val = 0; + if ( (map & HORI) == HORI ) val = bitHrzt[i][j]; + if ( (map & VERT) == VERT ) val = bitVrtc[i][j]; + + if ( (val|mask[j]) != (val^mask[j]) ) return true; + } + } + return false; +} + + + + +/* + * + */ +bool BinaryGrid::test( vec2d p1, vec2d p2 ) { + qDebug() <<"BinaryGrid::test"; + + orderVect( p1, p2 ); +// printVec2d( "p1 : ", p1 ); +// printVec2d( "p2 : ", p2 ); + + double left = vec2d(p1).mul(vec2d(1.0,0.0)).addCoord(); + double right = vec2d(p2).mul(vec2d(1.0,0.0)).addCoord(); + + double top = vec2d(p1).mul(vec2d(0.0,1.0)).addCoord(); + double bottom = vec2d(p2).mul(vec2d(0.0,1.0)).addCoord(); + + int map; + vec2d vDir = vec2d( p1, p2 ); + if ( vDir.dot( vec2d(0.0,1.0) ) == 0 ) map = HORI; + else map = VERT; + + + // compute mask 0 and mask 1 + U64 M0[5]; computeFirstMask( left, M0 ); + U64 M1[5]; computeSecondMask( right, M1 ); + + // mask = mask0 xor mask1 + U64 mask[5]; + for( int i=0; i<5; i++ ) mask[i] = M0[i] ^ M1[i]; + + int idx0 = computeFirstLine(top); + int idx1 = computeLastLine(bottom); + +// qDebug() << "idx 0 : "<< idx0; +// qDebug() << "idx 1 : "<< idx1; +// +// debugGrid( idx0-2, idx1+2); + + return testMask( mask, idx0, idx1, map ); +} + + + + +/* + * + */ +bool BinaryGrid::computeMinSegment( vec2d p1, vec2d p2 ) { + qDebug() <<"BinaryGrid::test"; + + orderVect( p1, p2 ); +// printVec2d( "p1 : ", p1 ); +// printVec2d( "p2 : ", p2 ); + + double left = vec2d(p1).mul(vec2d(1.0,0.0)).addCoord(); + double right = vec2d(p2).mul(vec2d(1.0,0.0)).addCoord(); + + double top = vec2d(p1).mul(vec2d(0.0,1.0)).addCoord(); + double bottom = vec2d(p2).mul(vec2d(0.0,1.0)).addCoord(); + + int map; + vec2d vDir = vec2d( p1, p2 ); + if ( vDir.dot( vec2d(0.0,1.0) ) == 0 ) map = HORI; + else map = VERT; + + + // compute mask 0 and mask 1 + U64 M0[5]; computeFirstMask( left, M0 ); + U64 M1[5]; computeSecondMask( right, M1 ); + + // mask = mask0 xor mask1 + U64 mask[5]; + for( int i=0; i<5; i++ ) mask[i] = M0[i] ^ M1[i]; + + int idx0 = computeFirstLine(top); + int idx1 = computeLastLine(bottom); + +// qDebug() << "idx 0 : "<< idx0; +// qDebug() << "idx 1 : "<< idx1; +// +// debugGrid( idx0-2, idx1+2); + + return testMask( mask, idx0, idx1, map ); +} + + + + diff --git a/sources/qetgraphicsitem/binarygrid.h b/sources/qetgraphicsitem/binarygrid.h new file mode 100644 index 000000000..28f1a8ace --- /dev/null +++ b/sources/qetgraphicsitem/binarygrid.h @@ -0,0 +1,52 @@ +/* + * binarygrid.h + * + * Created on: 8 nov. 2014 + * Author: rene + */ + +#ifndef BINARYGRID_H_ +#define BINARYGRID_H_ + +#include "diagram.h" +#include "conductor.h" +#include "Mathlib.h" + +typedef unsigned long long U64; + +#define HORI 0x01 +#define VERT 0x02 + +class BinaryGrid { + + public: + BinaryGrid(Diagram * diagram); + ~BinaryGrid(); + + void reset(); + void build(Conductor*); + void reBuild(Conductor*); + + void computeFirstMask( double, U64* ); + void computeSecondMask( double, U64*); + int computeFirstLine( double ); + int computeLastLine( double ); + + void debugGrid(int, int); + void debugGrid(); + void add2grid( vec2d, vec2d, int ); + void orderVect( vec2d&, vec2d& ); + void add2grid( Conductor* ); + + bool testMask( U64*, int, int, int ); + bool test( vec2d, vec2d ); + bool computeMinSegment( vec2d, vec2d ); + + private: + U64 bitHrzt[400][5]; + U64 bitVrtc[400][5]; + + Diagram* diagram; +}; + +#endif /* BINARYGRID_H_ */ diff --git a/sources/qetgraphicsitem/conductor.cpp b/sources/qetgraphicsitem/conductor.cpp index 0532fa422..7b0f50a52 100644 --- a/sources/qetgraphicsitem/conductor.cpp +++ b/sources/qetgraphicsitem/conductor.cpp @@ -27,12 +27,31 @@ #include "terminal.h" #include "conductorautonumerotation.h" #include "conductorpropertiesdialog.h" -#define PR(x) qDebug() << #x " = " << x; +#include "../qetapp.h" +#include "binarygrid.h" + +#define PR(x) qDebug() << #x " = " << x;extend bool Conductor::pen_and_brush_initialized = false; QPen Conductor::conductor_pen = QPen(); QBrush Conductor::conductor_brush = QBrush(); QBrush Conductor::square_brush = QBrush(Qt::darkGreen); + +int vec2d::count = 0; + + +bool Conductor::bAffPoint = true; +bool Conductor::bSmooth = false; +Conductor* Conductor::lastConductor = NULL; +QPointF Conductor::P1; +Qet::Orientation Conductor::O1; +QPointF Conductor::P2; +Qet::Orientation Conductor::O2; +bool Conductor::bDebug = false; +bool Conductor::bDebugGrid = false; +int Conductor::iIndiceDebug = 0; + + /** Constructeur @param p1 Premiere Borne a laquelle le conducteur est lie @@ -99,6 +118,7 @@ Conductor::Conductor(Terminal *p1, Terminal* p2, Diagram *parent_diagram) : this, SLOT(displayedTextChanged()) ); + bMouseOver = false; } /** @@ -171,6 +191,11 @@ void Conductor::updateConductorPath(const QPointF &p1, Qet::Orientation o1, cons Q_UNUSED(o1); Q_UNUSED(o2); + if ( QETApp::bConductor2 ) { + //qDebug() << "updateConductorPath2"; + generateConductorPath2(p1, o1, p2, o2 ); + return; + } ConductorProfile &conductor_profile = conductor_profiles[currentPathType()]; Q_ASSERT_X(conductor_profile.segmentsCount(QET::Both) > 1, "Conductor::priv_modifieConductor", "pas de points a modifier"); @@ -296,6 +321,11 @@ QHash Conductor::shareOffsetBetweenSegments( @param o2 Orientation de la borne 2 */ void Conductor::generateConductorPath(const QPointF &p1, Qet::Orientation o1, const QPointF &p2, Qet::Orientation o2) { + if ( QETApp::bConductor2 ){ + //qDebug() << "generateConductorPath2"; + generateConductorPath2(p1, o1, p2, o2 ); + return; + } QPointF sp1, sp2, depart, newp1, newp2, arrivee, depart0, arrivee0; Qet::Orientation ori_depart, ori_arrivee; @@ -391,6 +421,477 @@ void Conductor::generateConductorPath(const QPointF &p1, Qet::Orientation o1, co segmentsToPath(); } + + + + + + + + + + + + + + + + +void Conductor::addPoint( vec2d p ) { + vec2d vScenePos = vec2d(scenePos()); + p -= vScenePos; + + qDebug() << "Test Point : "<< currentIndice; + if ( currentIndice > 1 ){ + vec2d ori = vec2d( vec2ds[currentIndice-1] ); + if ( diagram() ) { + if ( diagram() -> _binaryGrid ->test( ori, p ) ) + qDebug()<< "Test droie OK de "<< currentIndice-1 <<" à "<< currentIndice; + else + qDebug()<< "Test droie NOK de "<< currentIndice-1 <<" à "<< currentIndice; + } + } + + if ( bDebug ) { + qDebug() << "--------------------------"; + qDebug() << " point no : " << currentIndice; + printVec2d( " Ajout de : ", p ); + qDebug() << "--------------------------"; + } + vec2ds << p; + currentIndice++; + if ( currentIndice == iIndiceDebug ) bDebug = true; + else bDebug = false; +} + +void Conductor::printVec2d( QString str, vec2d v ) { + qDebug() << str <<" ("<< v.x <<","<< v.y <<")"; +} + +void Conductor::printDoubl( QString str, double d ) { + qDebug() << str <<" "<< d; +} + + + +/* + * + */ +vec2d Conductor::orientation2vec2d( Qet::Orientation orientation ) { + switch(orientation) { + case Qet::North: return vec2d( 0.0,-1.0 ); + case Qet::East: return vec2d( 1.0, 0.0 ); + case Qet::South: return vec2d( 0.0, 1.0 ); + case Qet::West: return vec2d(-1.0, 0.0 ); + } + return vec2d(0.0,0.0); +} + + + +void Conductor::rect2corner( vec2d* topLeft, vec2d* topRight, vec2d*bottomLeft, vec2d* bottomRight, QRectF qRectF, QPointF pos ) { + *topLeft = vec2d( pos + qRectF.topLeft() ) + vec2d(1.0,1.0); + *topRight = vec2d( pos + qRectF.topRight() ) + vec2d(-1.0,1.0); + *bottomLeft = vec2d( pos + qRectF.bottomLeft() ) + vec2d(1.0,-1.0); + *bottomRight = vec2d( pos + qRectF.bottomRight() ) + vec2d(-1.0,-1.0); +} + +void Conductor::rect2side( vec2d* topLeft, vec2d* bottomRight, QRectF qRectF, QPointF pos ) { + *topLeft = vec2d( pos + qRectF.topLeft() ); + *bottomRight = vec2d( pos + qRectF.bottomRight() ); +} + + +void Conductor::rect2side( vec2d* topLeft, vec2d* bottomRight, QRectF qRectF ) { + *topLeft = vec2d( qRectF.topLeft() ); + *bottomRight = vec2d( qRectF.bottomRight() ); +} + + +int Conductor::sign( double d ) { return d==0.0 ? 0 : d<-EPSILON ? -1: 1;} + +int Conductor::computeSign( vec2d p1, vec2d p2, vec2d vDir ) { + vec2d c_p1 = vec2d( p1 ).mulCoord( vDir ); + vec2d c_p2 = vec2d( p2 ).mulCoord( vDir ); + +// qDebug() << " computeSign()"; +// printVec2d( " p1 : ", c_p1 ); +// printVec2d( " p2 : ", c_p2 ); + + int ret = sign( vec2d( c_p1, c_p2 ).addCoord() ); + +// printDoubl( " Sign : ", ret ); + + return ret; + +} + +bool Conductor::isInsideRect( vec2d pt, vec2d topLeft, vec2d bottomRight ) { + + int s_ol = computeSign( pt, topLeft , east ); + int s_or = computeSign( pt, bottomRight , east ); + if ( s_ol == s_or ) return false; + + s_ol = computeSign( pt, topLeft , south ); + s_or = computeSign( pt, bottomRight , south ); + if ( s_ol == s_or ) return false; + + return true; +} + +bool Conductor::isInsideRect( vec2d orig, vec2d dest, vec2d topLeft, vec2d bottomRight ) { + + int s_ol = computeSign( orig, topLeft , east ); + int s_or = computeSign( orig, bottomRight , east ); + int s_dl = computeSign( dest, topLeft , east ); + int s_dr = computeSign( dest, bottomRight , east ); + + + if ( s_ol == s_or && s_ol == s_dl && s_ol == s_dr ) { + return false; + } + + s_ol = computeSign( orig, topLeft , south ); + s_or = computeSign( orig, bottomRight , south ); + s_dl = computeSign( dest, topLeft , south ); + s_dr = computeSign( dest, bottomRight , south ); + + + if ( s_ol == s_or && s_ol == s_dl && s_ol == s_dr ) { + return false; + } + + return true; +} + + +void Conductor::computeIntersection( vec2d orig, vec2d& dest, vec2d topLeft, vec2d bottomRight ) { + + vec2d orientation; + + + vec2d vDir = vec2d( orig, dest ).vnormalize(); + double sign = vDir.addCoord(); + + if ( vDir.dot(south) == 0.0 ) orientation = east; + else orientation = south; + + if ( bDebug ) { + printVec2d( " orig : ", orig ); + printVec2d( " dest : ", orig ); + printVec2d( " dir : ", orientation); + } + + vec2d vOL = vec2d( orig, topLeft ).mul(orientation); + vec2d vOR = vec2d( orig, bottomRight).mul(orientation); + + double dOL = vOL.addCoord() * sign; + double dOR = vOR.addCoord() * sign; + + if ( bDebug ) { + printDoubl( " dOL : ", dOL ); + printDoubl( " dOR : ", dOR ); + } + + double res; + if ( dOL < dOR ) { + res = dOL; + res -= 10.0; + } + else { + res = dOR; + res += 10.0; + } + + + dest = orig + res * vDir; + snapOnGrid(dest); + if ( bDebug ) { + printVec2d( " dest : ", dest); + } + +} + + +bool Conductor::isInsideElement( vec2d pt, Element* element) { + + vec2d topLeft, bottomRight; + rect2side( &topLeft, &bottomRight, element -> boundingRectTrue() ); + + return isInsideRect( pt, topLeft, bottomRight ); +} + + +Element* Conductor::intersectionElement( vec2d &pt, vec2d ori, Element* element ) { + if ( element == NULL ) return NULL; + + vec2d topLeft, bottomRight; + rect2side( &topLeft, &bottomRight, element -> boundingRectTrue() ); + + if ( bDebug ) { + qDebug() << " test intersection avec : "<< element -> name(); + printVec2d( " topLeft : ", topLeft ); + printVec2d( " bottomRgiht : ", bottomRight ); + } + + if ( isInsideRect( ori, pt, topLeft, bottomRight ) ) { + + if ( bDebug ) { + qDebug() <<" *** Intersection "; + qDebug() <<" *** computeInstersection"; + } + computeIntersection( ori, pt, topLeft, bottomRight ); + return element; + } + else { + if ( bDebug ) { + qDebug() <<" Pas d'intersection "; + //intersection( pt, ori, topLeft, bottomRight ); + } + } + return NULL; +} + + +Element* Conductor::intersectionElements( vec2d &pt, vec2d ori ) { + Element* returnElement = NULL; + if ( bDebug ) { + qDebug() << "Intersection Elements"; + } + + if ( diagram() ){ + QList elements = diagram() -> elements(); + for ( int i=0; i terminals() != null ) continue; + if ( element -> terminals().size() == 0 ) continue; + Element* ret = intersectionElement( pt, ori, element ); + if ( ret ) returnElement = ret; + } + } + return returnElement; +} + + +void Conductor::intersectionConductors( vec2d &pt, vec2d ori ) { + if ( bDebug ) { + qDebug() << "Intersection Conductor"; + } + + if ( diagram() ){ + QList elements = diagram() -> elements(); + int nbElem = elements.size(); + for ( int i=0; i terminals = element -> terminals(); + int nbTerm = terminals.size(); + + for( int j=0; j conductors = terminal -> conductors(); + int nbCond = conductors.size(); + + for( int k=0; k vec2ds = conductor -> vec2ds; + int nbVec2d= vec2ds.size() - 1 ; + + vec2d vDir = vec2d(ori, pt).vnormalize(); + //return; + + for( int l=0; l 400.0 ) return; + + + vOrtho = vOrtho.vabs(); + + vec2d o = pt + test * vOrtho; + vec2d p = o + 50.0 * vDir; + + if ( bDebug ) { + printDoubl( " evaluate t : ", test ); + printVec2d( " evaluate p : ", p ); + printVec2d( " evaluate o : ", o ); + } + + intersectionElement( p, o, element ); + + if ( bDebug ) { + printVec2d( " evaluate p : ", p ); + printVec2d( " evaluate o : ", o ); + } + + test += sign(test) * 10.0; + + if ( p == o ) + evaluatePath( ori, pt, element, test ); + else + pt = o; +} + +double Conductor::computeSensEvaluatePath( vec2d ori, vec2d pt, vec2d dest ) { + vec2d vDir = vec2d( ori, dest ); + vec2d vNew = vec2d( ori, pt ).exch().vabs(); + vDir = vDir.mul(vNew); + + double ret = vDir.addCoord(); + ret = ret >= 0.0 ? 1.0 : -1.0; + return ret; +} + + + + + + +vec2d Conductor::previousDir() { + if ( currentIndice > 2 ) { + vec2d p2 = vec2ds[currentIndice - 1]; + vec2d p1 = vec2ds[currentIndice - 2]; + + vec2d vDir = vec2d( p1, p2 ).vnormalize(); + return vDir; + } + return vec2d(0.0,0.0); +} + + + +vec2d Conductor::findNextPoint( vec2d p1, vec2d& vD1, vec2d p2, vec2d vD2 ) { + + + vec2d vP1P2n = vec2d(p1, p2).vnormalize(); + + double dot = vD1.dot(vD2); + double coef = 1.0; + + vec2d v = vec2d( p1, p2 ); + vec2d vnorm = v.vnormalize(); + // if direction are opposite the next point is in the middle + // and not in the same line + if ( dot < -0.9 && vnorm.dot(vD1) != 1.0) { coef = 0.5; } + // tout droit + if ( vP1P2n == vD1 ) { + /* + vec2d newPoint = vec2d( p2 ); + Element* element = intersectionElements( newPoint, p1 ); + if ( element == NULL ) { + addPoint( p2 ); + return p2; + } + */ + coef = 1.0; + } + // New point follow first direction horizontal or vertical + v.x *= coef * fabs(vD1.x); + v.y *= coef * fabs(vD1.y); + + + vec2d newPoint = p1 + v; + // snap on grid + snapOnGrid( newPoint ); + + + vec2d svgPt = newPoint; + + //intersectionConductors( newPoint, p1 ); + Element* element = intersectionElements( newPoint, p1 ); + + if ( newPoint != svgPt ) { + //vec2d newDir; + vec2d svgEvalPt = newPoint; + // compute sens + double first = computeSensEvaluatePath( p1, newPoint, p2) * 10.0; + evaluatePath( p1, newPoint, element, first ); + if ( svgEvalPt != newPoint ) { + addPoint( svgEvalPt ); + // on conserve la direction + return newPoint; + } + } + else { + if ( vP1P2n == vD1 && newPoint == p2 ) + return p2; + } + + + + // compute new direction + vec2d newD1 = vec2d( newPoint, p2 ); + newD1.mul(vD1.exch().vabs()); + newD1.normalize(); + + if ( newD1 == vec2d(0.0,0.0) ) { + newD1 = vD1.exch(); + + addPoint( newPoint ); + newPoint += 60.0 * newD1; + newD1 = vD1; + + } + // normalize vector 1 unit lenght + newD1.normalize(); + //Change vD1 (it's a reference) isn't it + vD1.x = newD1.x; + vD1.y = newD1.y; +// printVec2d(" New dir : ", vD1); +// printVec2d("New point : ", newPoint); + + // printVec2d("New point : ", newPoint); + return newPoint; +} + /** Prolonge une borne. @param terminal Le point correspondant a la borne @@ -413,10 +914,336 @@ QPointF Conductor::extendTerminal(const QPointF &terminal, Qet::Orientation term case Qet::West: extended_terminal = QPointF(terminal.x() - ext_size, terminal.y()); break; - default: extended_terminal = terminal; + default: extended_terminal = terminal; break; } return(extended_terminal); } + + + + +vec2d Conductor::extendOutOfElement( vec2d pt, vec2d vDir, Element* element) { + vec2d newPt = pt; + + if ( element ) { + while( isInsideElement( newPt , element )) { + newPt += 10.0 * vDir; + } + } + return newPt; +} + + + + +void Conductor::snapOnGrid( vec2d& pt ) { + vec2d newPt; + //pt += vec2d(5.0,5.0); + + int x = (int) pt.x % 10; + int X = (int) pt.x / 10; + + if ( x >= 5 ) X++; + newPt.x = 10.0 * X; + + int y = (int) pt.y % 10; + int Y = (int) pt.y / 10; + + if ( y >= 5 ) Y++; + newPt.y = 10.0 * Y; + + pt = newPt; +} + + + + + + + + + + + + + + + + + + +/* + * + */ +void Conductor::generateConductorPath2( const QPointF &p1, Qet::Orientation o1, const QPointF &p2, Qet::Orientation o2) { + //diagram() -> _binaryGrid -> add2grid( vec2d(25.0,10.0), vec2d(405.0,45.0) ); + if ( diagram() ) + if ( diagram()->_binaryGrid) + diagram() -> _binaryGrid -> reBuild(this); + + + QPointF sp1, sp2, depart; + vec2d newp1, newp2; + vec2d vScenePos = vec2d(scenePos()); + + Conductor::lastConductor = this; + Conductor::P1 = p1; + Conductor::O1 = o1; + Conductor::P2 = p2; + Conductor::O2 = o2; + //Qet::Orientation ori_depart, ori_arrivee; + + qDebug() << "-------------------------------"; + if ( diagram() ){ + qDebug() <<"Diagram title : "<< diagram() -> title(); + } + + + + // s'assure qu'il n'y a ni points + QList points; + vec2ds.clear(); + + // mappe les points par rapport a la scene + if ( p1.x() < p2.x() ) { + sp1 = mapFromScene(p1); + sp2 = mapFromScene(p2); + } + else { + sp1 = mapFromScene(p2); + sp2 = mapFromScene(p1); + Qet::Orientation o = o1; + o1 = o2; + o2 = o; + } + + // prolonge les bornes + Element* element; + Element* element1 = terminal1 -> parentElement(); + Element* element2 = terminal2 -> parentElement(); + + newp1 = vec2d(sp1) + vScenePos; + snapOnGrid( newp1 ); + vec2d vDir1 = orientation2vec2d(o1); + + element = NULL; + if ( isInsideElement( newp1, element1 ) ) element = element1; + else if ( isInsideElement( newp1, element2 ) ) element = element2; + if ( element ) qDebug() <<"Intersection terminal1 : "<< element -> name(); + else qDebug() <<"*** Erreur Intersection terminal1 : "; + + newp1 = extendOutOfElement( newp1, vDir1, element ); + + newp2 = vec2d(sp2) + vScenePos; + snapOnGrid( newp2 ); + vec2d vDir2 = orientation2vec2d(o2); + + element = NULL; + if ( isInsideElement( newp2, element1 ) ) element = element1; + else if ( isInsideElement( newp2, element2 ) ) element = element2; + + newp2 = extendOutOfElement( newp2, vDir2, element ); + + //-------------------------- + currentIndice = 0; + addPoint( vec2d(sp1) + vScenePos ); + addPoint( newp1 ); + + vec2d newPt = newp1; + vec2d vo = orientation2vec2d(o1); + + // tout droit petite distance + vec2d P1 = vec2d(sp1); + vec2d P2 = vec2d(sp2); + vec2d vDir = vec2d( P1, P2 ); + vec2d vNor = vDir.vnormalize(); +// printVec2d( "P1", P1); +// printVec2d( "P2", P2); +// printVec2d( "DI", vDir); +// printVec2d( "NO", vNor); +// printDoubl( "dot1", fabs(vNor.dot(vDir1)) ); +// printDoubl( "dot2", fabs(vNor.dot(vDir2)) ); +// printDoubl( "leng", vDir.length() ); + //if ( vDir != vec2d(0.0,0.0) && ( fabs(vNor.dot(vDir1)) != 1.0 || fabs(vNor.dot(vDir2)) != 1.0 || vDir.length() > 45.0 ) ) { + if ( vDir != vec2d(0.0,0.0) && ( vDir.length() > 45.0 ) ) { + + + while ( newPt != newp2 ) { + if ( bDebug ) { + qDebug() << "**** Point suivant :"<< currentIndice; + printVec2d( " a partir de newPt : ", newPt ); + printVec2d( " vers : ", newp2 ); + } + + newPt = findNextPoint( newPt, vo, newp2, orientation2vec2d(o2) ); + addPoint( newPt ); + + if( currentIndice>=30 ) break; + } + } + else { + qDebug()<<"Tout droit"; + vec2ds.removeAt(1); + } + + //vec2ds << newp2; + addPoint( vec2d(sp2) + vScenePos ); + if ( bSmooth ) smooth(); + + // change vec2d to QPointF + int nb = vec2ds.size(); + for( int i=0; i _binaryGrid -> add2grid(this); + if ( Conductor::bDebugGrid ) diagram() -> _binaryGrid -> debugGrid(); +} + + + + +void Conductor::reBuild() { + if ( ! lastConductor ) return; + lastConductor -> generateConductorPath2( P1, O1, P2, O2 ); + +} + + + +void Conductor::smooth(){ + int nb = vec2ds.size()-4; + vec2d vNull = vec2d(0.0,0.0); + + QList removePoints; + + for ( int i=1; i name(); + if ( element2 ) qDebug() <<"Intersection 2 avec : "<< element2 -> name(); + } + } + } + + } +} + + + +/* +"P0 : " ( 220 , 290 ) +"P1 : " ( 220 , 470 ) +"P4 : " ( 540 , 470 ) + */ + + + + + + + +void Conductor::updateConductorPath2(const QPointF &p1, Qet::Orientation o1, const QPointF &p2, Qet::Orientation o2) { + generateConductorPath2( p1, o1, p2, o2); +} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + /** Dessine le conducteur sans antialiasing. @@ -451,6 +1278,10 @@ void Conductor::paint(QPainter *qp, const QStyleOptionGraphicsItem *options, QWi // affectation du QPen et de la QBrush modifies au QPainter qp -> setBrush(conductor_brush); + + if ( bMouseOver ) conductor_pen.setWidthF(3.0); + else conductor_pen.setWidthF(1.0); + QPen final_conductor_pen = conductor_pen; // modification du QPen generique pour lui affecter la couleur et le style adequats @@ -515,6 +1346,35 @@ void Conductor::paint(QPainter *qp, const QStyleOptionGraphicsItem *options, QWi qp -> drawEllipse(QRectF(point.x() - pretty_offset, point.y() - pretty_offset, 2.0, 2.0)); } } + + //Dessine tous les points + QFont font = qp -> font() ; + font.setPointSize ( 8 ); + //font.setWeight(QFont::DemiBold); + qp -> setFont(font); + + if ( Conductor::bAffPoint ) { + int nb = vec2ds.size(); + vec2d prevPt = vec2d(0.0,0.0); + double nbPt = 0.0; + for (int i = 0 ; i < nb ; i++) { + vec2d pt = vec2ds[i]; + vec2d vtl = vec2d(pt) - vec2d( 2.0, 2.0 ); // topLeft + vec2d vbr = vec2d(pt) + vec2d( 2.0, 2.0 ); // bottomRight + + if ( prevPt == pt ) nbPt += 1.0; + else nbPt = 0.0; + + // Point + QPointF coordText = vec2d( pt + nbPt * vec2d(10.0,0.0) + vec2d(2.0,-1.0) ).toQPointF(); + qp -> fillRect( QRectF( vtl.toQPointF(), vbr.toQPointF() ) , square_brush ); + // Texte + QString text = QString::number(i,10) +":"+ QString::number( (int)pt.x ) +", "+ QString::number( (int)pt.y ); + qp -> drawText( coordText, text ); + prevPt = pt; + } + } + qp -> restore(); } @@ -712,9 +1572,9 @@ void Conductor::hoverLeaveEvent(QGraphicsSceneHoverEvent *e) { @param e Le QGraphicsSceneHoverEvent decrivant l'evenement */ void Conductor::hoverMoveEvent(QGraphicsSceneHoverEvent *e) { - /* + if (isSelected()) { - QPointF hover_point = mapFromScene(e -> pos()); + QPointF hover_point = mapFromScene(e -> pos()) + scenePos(); ConductorSegment *segment = segments; bool cursor_set = false; while (segment -> hasNextSegment()) { @@ -729,7 +1589,7 @@ void Conductor::hoverMoveEvent(QGraphicsSceneHoverEvent *e) { } if (!cursor_set) setCursor(Qt::ArrowCursor); } - */ + QGraphicsPathItem::hoverMoveEvent(e); } diff --git a/sources/qetgraphicsitem/conductor.h b/sources/qetgraphicsitem/conductor.h index 3f0651f06..db0ba41f5 100644 --- a/sources/qetgraphicsitem/conductor.h +++ b/sources/qetgraphicsitem/conductor.h @@ -19,6 +19,7 @@ #define CONDUCTOR_H #include "conductorproperties.h" +#include "Mathlib.h" class ConductorProfile; class ConductorSegmentProfile; @@ -171,6 +172,35 @@ class Conductor : public QObject, public QGraphicsPathItem { void saveProfile(bool = true); void generateConductorPath(const QPointF &, Qet::Orientation, const QPointF &, Qet::Orientation); void updateConductorPath(const QPointF &, Qet::Orientation, const QPointF &, Qet::Orientation); + + void addPoint(vec2d); + void printVec2d( QString, vec2d ); + void printDoubl( QString, double ); + vec2d qPointF2vec2d( QPointF ); + QPointF vec2d2qPointF( vec2d ); + vec2d orientation2vec2d( Qet::Orientation ); + void rect2side( vec2d*, vec2d*, QRectF, QPointF ); + void rect2side( vec2d*, vec2d*, QRectF ); + void rect2corner( vec2d*, vec2d*, vec2d*, vec2d*, QRectF, QPointF ); + int sign( double ); + int computeSign( vec2d, vec2d, vec2d ); + bool isInsideRect( vec2d, vec2d, vec2d ); + bool isInsideRect( vec2d, vec2d, vec2d, vec2d ); + void computeIntersection( vec2d, vec2d&, vec2d, vec2d ); + bool isInsideElement( vec2d, Element* ); + Element* intersectionElement( vec2d&, vec2d, Element* ); + Element* intersectionElements( vec2d&, vec2d ); + void intersectionConductors( vec2d&, vec2d ); + void evaluatePath( vec2d, vec2d&, Element*, double = 10.0 ); + double computeSensEvaluatePath( vec2d, vec2d, vec2d ); + vec2d previousDir(); + vec2d findNextPoint( vec2d, vec2d&, vec2d, vec2d ); + vec2d extendOutOfElement( vec2d, vec2d, Element* ); + void snapOnGrid( vec2d& ); + void generateConductorPath2(const QPointF &, Qet::Orientation, const QPointF &, Qet::Orientation); + void smooth( void ); + void updateConductorPath2(const QPointF &, Qet::Orientation, const QPointF &, Qet::Orientation); + uint segmentsCount(QET::ConductorSegmentType = QET::Both) const; QList segmentsToPoints() const; QList bends() const; @@ -187,6 +217,29 @@ class Conductor : public QObject, public QGraphicsPathItem { static qreal conductor_bound(qreal, qreal, bool); static Qt::Corner movementType(const QPointF &, const QPointF &); static QPointF movePointIntoPolygon(const QPointF &, const QPainterPath &); + + QList vec2ds; + vec2d north = vec2d( 0.0,-1.0); + vec2d south = vec2d( 0.0, 1.0); + vec2d east = vec2d( 1.0, 0.0); + vec2d west = vec2d(-1.0, 0.0); + + int currentIndice; +// Element elementParent1; +// Element elementParent2; + public: + static bool bAffPoint; + static bool bSmooth; + static bool bDebug; + static bool bDebugGrid; + static int iIndiceDebug; + static Conductor* lastConductor; + static QPointF P1; + static Qet::Orientation O1; + static QPointF P2; + static Qet::Orientation O2; + static void reBuild(void); + inline QList getVec2ds() { return vec2ds; } }; Conductor * longuestConductorInPotential (Conductor *conductor, bool all_diagram = false); diff --git a/sources/qetgraphicsitem/conductortextitem.h b/sources/qetgraphicsitem/conductortextitem.h index a8335ee1a..251025290 100644 --- a/sources/qetgraphicsitem/conductortextitem.h +++ b/sources/qetgraphicsitem/conductortextitem.h @@ -68,5 +68,8 @@ class ConductorTextItem : public DiagramTextItem { bool moved_by_user_; bool rotate_by_user_; QPointF before_mov_pos_; + + + }; #endif diff --git a/sources/qetgraphicsitem/diagramtextitem.cpp b/sources/qetgraphicsitem/diagramtextitem.cpp index ba94f601b..dfa127287 100644 --- a/sources/qetgraphicsitem/diagramtextitem.cpp +++ b/sources/qetgraphicsitem/diagramtextitem.cpp @@ -73,6 +73,7 @@ void DiagramTextItem::build() { setFlag(QGraphicsItem::ItemSendsGeometryChanges, true); #endif connect(this, SIGNAL(lostFocus()), this, SLOT(setNonFocusable())); + setAcceptHoverEvents(true); } /** @@ -213,7 +214,8 @@ void DiagramTextItem::setFontSize(int &s) { @param widget Le QWidget sur lequel on dessine */ void DiagramTextItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) { - painter -> setRenderHint(QPainter::Antialiasing, false); + painter -> setRenderHint(QPainter::Antialiasing, true); + //option-> QGraphicsTextItem::paint(painter, option, widget); if ( bMouseOver ) { @@ -232,7 +234,6 @@ void DiagramTextItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *o painter -> drawRoundRect(boundingRect().adjusted(0, 0, 0, 0), 10, 10); painter -> restore(); } - } /** diff --git a/sources/qetgraphicsitem/diagramtextitem.h b/sources/qetgraphicsitem/diagramtextitem.h index 708d20f83..e8bb9b06f 100644 --- a/sources/qetgraphicsitem/diagramtextitem.h +++ b/sources/qetgraphicsitem/diagramtextitem.h @@ -101,5 +101,6 @@ class DiagramTextItem : public QGraphicsTextItem { bool no_editable; bool m_first_move; QPointF m_mouse_to_origin_movement; + }; #endif diff --git a/sources/qetgraphicsitem/element.cpp b/sources/qetgraphicsitem/element.cpp index d8c190b01..cda28cee6 100644 --- a/sources/qetgraphicsitem/element.cpp +++ b/sources/qetgraphicsitem/element.cpp @@ -85,7 +85,7 @@ void Element::setHighlighted(bool hl) { @param widget Le widget sur lequel on dessine */ void Element::paint(QPainter *painter, const QStyleOptionGraphicsItem *options, QWidget *widget) { - + #ifndef Q_WS_WIN // corrige un bug de rendu ne se produisant que lors du rendu sur QGraphicsScene sous X11 au zoom par defaut static bool must_correct_rendering_bug = QETApp::settings().value("correct-rendering", false).toBool(); @@ -100,6 +100,7 @@ void Element::paint(QPainter *painter, const QStyleOptionGraphicsItem *options, } } #endif + if (must_highlight_) drawHighlight(painter, options); // Dessin de l'element lui-meme @@ -115,9 +116,18 @@ void Element::paint(QPainter *painter, const QStyleOptionGraphicsItem *options, @return Le rectangle delimitant le contour de l'element */ QRectF Element::boundingRect() const { +// qDebug() << QRectF(QPointF(-hotspot_coord.x(), -hotspot_coord.y()), dimensions); +// qDebug() << "orientation : " << orientation(); return(QRectF(QPointF(-hotspot_coord.x(), -hotspot_coord.y()), dimensions)); } +/** + @return Le rectangle delimitant le contour de l'element +*/ +QRectF Element::boundingRectTrue() const { + return mapRectToScene( boundingRect() ); +} + /** Definit la taille de l'element sur le schema. Les tailles doivent etre des multiples de 10 ; si ce n'est pas le cas, les dimensions indiquees @@ -195,6 +205,7 @@ QPixmap Element::pixmap() { * @param angle */ void Element::rotateBy(const qreal &angle) { + qDebug() << "Rotation : " << angle; qreal applied_angle = QET::correctAngle(angle); applyRotation(applied_angle + rotation()); @@ -263,7 +274,8 @@ void Element::drawSelection(QPainter *painter, const QStyleOptionGraphicsItem *o t.setStyle(Qt::DashDotLine); painter -> setPen(t); // Le dessin se fait a partir du rectangle delimitant - painter -> drawRoundRect(boundingRect().adjusted(1, 1, -1, -1), 10, 10); + //painter -> drawRoundRect(boundingRect().adjusted(1, 1, -1, -1), 10, 10); + painter -> drawRoundRect(boundingRect().adjusted(0, 0, 0, 0), 10, 10); painter -> restore(); } @@ -289,7 +301,8 @@ void Element::drawHighlight(QPainter *painter, const QStyleOptionGraphicsItem *o painter -> setPen(Qt::NoPen); painter -> setBrush(brush); // Le dessin se fait a partir du rectangle delimitant - painter -> drawRoundRect(boundingRect().adjusted(1, 1, -1, -1), 10, 10); + //painter -> drawRoundRect(boundingRect().adjusted(1, 1, -1, -1), 10, 10); + painter -> drawRoundRect(boundingRect().adjusted(0, 0, 0, 0), 10, 10); painter -> restore(); } diff --git a/sources/qetgraphicsitem/element.h b/sources/qetgraphicsitem/element.h index 98578a118..7a0448666 100644 --- a/sources/qetgraphicsitem/element.h +++ b/sources/qetgraphicsitem/element.h @@ -150,6 +150,7 @@ class Element : public QetGraphicsItem { virtual void setHighlighted(bool); void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget *); QRectF boundingRect() const; + QRectF boundingRectTrue() const; QSize setSize(int, int); QSize size() const; QPixmap pixmap(); @@ -181,6 +182,7 @@ class Element : public QetGraphicsItem { void drawAxes(QPainter *, const QStyleOptionGraphicsItem *); private: + bool bMouseHover; bool internal_connections_; bool must_highlight_; void drawSelection(QPainter *, const QStyleOptionGraphicsItem *); diff --git a/sources/qetgraphicsitem/terminal.cpp b/sources/qetgraphicsitem/terminal.cpp index b033b2fdd..d48532492 100644 --- a/sources/qetgraphicsitem/terminal.cpp +++ b/sources/qetgraphicsitem/terminal.cpp @@ -405,7 +405,8 @@ void Terminal::mouseReleaseEvent(QGraphicsSceneMouseEvent *e) { // on s'arrete la s'il n'est pas possible de relier les bornes if (!canBeLinkedTo(other_terminal)) return; // autrement, on pose un conducteur - Conductor *new_conductor = new Conductor(this, other_terminal); + //Conductor *new_conductor = new Conductor(this, other_terminal); + Conductor *new_conductor = new Conductor(this, other_terminal, d); new_conductor -> setProperties(d -> defaultConductorProperties); d -> undoStack().push(new AddItemCommand(new_conductor, d)); new_conductor -> autoText(); diff --git a/sources/qetgraphicsitem/waypoint.cpp b/sources/qetgraphicsitem/waypoint.cpp new file mode 100644 index 000000000..8e5a26727 --- /dev/null +++ b/sources/qetgraphicsitem/waypoint.cpp @@ -0,0 +1,28 @@ +/* + * waypoint.cpp + * + * Created on: 6 nov. 2014 + * Author: rene + */ + + + + +#include "waypoint.h" + + + + +Waypoint::Waypoint( vec2d o, vec2d d) { + orig = o; + dest = d; + + vDir = vec2d( orig, dest ); + vNor = vDir.vnormalize(); + + nexttLeft = NULL; + nexttRight = NULL; +} + + + diff --git a/sources/qetgraphicsitem/waypoint.h b/sources/qetgraphicsitem/waypoint.h new file mode 100644 index 000000000..9cad9ed6a --- /dev/null +++ b/sources/qetgraphicsitem/waypoint.h @@ -0,0 +1,33 @@ +/* + * waypoint.h + * + * Created on: 6 nov. 2014 + * Author: rene + */ + +#ifndef WAYPOINT_H_ +#define WAYPOINT_H_ + +#include "Mathlib.h" + +class Waypoint; + + +class Waypoint { + public: + Waypoint(vec2d, vec2d); + ~Waypoint(); + + private: + vec2d next; + + vec2d orig; + vec2d dest; + vec2d vDir; + vec2d vNor; + + Waypoint* nexttLeft; + Waypoint* nexttRight; +}; + +#endif /* WAYPOINT_H_ */