1 // Copyright (C) 2007-2023 CEA/DEN, EDF R&D, OPEN CASCADE
3 // Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License, or (at your option) any later version.
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 // Lesser General Public License for more details.
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
23 #include "GLViewer_BaseObjects.h"
24 #include "GLViewer_BaseDrawers.h"
25 #include "GLViewer_AspectLine.h"
26 #include "GLViewer_CoordSystem.h"
27 #include "GLViewer_Text.h"
28 #include "GLViewer_Group.h"
29 #include "GLViewer_Drawer.h"
36 GLViewer_MarkerSet::GLViewer_MarkerSet( int number, float size, const QString& toolTip ) :
47 myUSelNumbers.clear();
48 myCurSelNumbers.clear();
49 myPrevHNumbers.clear();
51 myType = "GLViewer_MarkerSet";
52 myToolTipText = toolTip;
54 setNumMarkers( number );
60 GLViewer_MarkerSet::~GLViewer_MarkerSet()
69 Adds coords to text buffer in HPGL format
70 \param buffer - text buffer
71 \param command - command to be added with coords
72 \param aViewerCS - viewer co-ordinates system
73 \param aPaperCS - paper co-ordinates system
74 \param x - x co-ordinate
75 \param y - y co-ordinate
76 \param NewLine - adds new line to buffer
78 void AddCoordsToHPGL( QString& buffer, QString command, GLViewer_CoordSystem* aViewerCS,
79 GLViewer_CoordSystem* aPaperCS, double x, double y, bool NewLine = true )
81 if( aViewerCS && aPaperCS )
82 aViewerCS->transform( *aPaperCS, x, y );
84 QString temp = command + "%1, %2;";
85 buffer += temp.arg( x ).arg( y );
91 Adds coords to text buffer in PostScript format
92 \param buffer - text buffer
93 \param command - command to be added with coords
94 \param aViewerCS - viewer co-ordinates system
95 \param aPaperCS - paper co-ordinates system
96 \param x - x co-ordinate
97 \param y - y co-ordinate
98 \param NewLine - adds new line to buffer
100 void AddCoordsToPS( QString& buffer, QString command, GLViewer_CoordSystem* aViewerCS,
101 GLViewer_CoordSystem* aPaperCS, double x, double y, bool NewLine = true )
103 if( aViewerCS && aPaperCS )
104 aViewerCS->transform( *aPaperCS, x, y );
106 QString temp = "%1 %2 "+command;
107 buffer += temp.arg( x ).arg( y );
113 Adds line aspect description to text buffer in PostScript format
114 \param buffer - text buffer
115 \param anAspect - line aspect
116 \param aViewerCS - viewer co-ordinates system
117 \param aPaperCS - paper co-ordinates system
119 void AddLineAspectToPS( QString& buffer, GLViewer_AspectLine* anAspect,
120 GLViewer_CoordSystem* aViewerCS, GLViewer_CoordSystem* aPaperCS )
124 QColor col1, col2, col3;
125 anAspect->getLineColors( col1, col2, col3 );
127 float aWidth = anAspect->getLineWidth();
128 int aLineType = anAspect->getLineType();
130 QString temp = "%1 %2 %3 setrgbcolor\n";
131 double rr = 1 - double( col1.red() ) / 255.0, //color inverting
132 gg = 1 - double( col1.green() ) / 255.0,
133 bb = 1 - double( col1.blue() ) / 255.0;
135 buffer += temp.arg( rr ).arg( gg ).arg( bb );
137 double x_stretch, y_stretch;
138 aViewerCS->getStretching( *aPaperCS, x_stretch, y_stretch );
139 buffer += temp.arg( x_stretch * aWidth )+" setlinewidth\n";
141 if( aLineType==0 ) //solid
142 buffer += "[] 0 setdash\n";
143 else if( aLineType==1 ) //strip
144 buffer += "[2] 0 setdash\n";
150 Adds line aspect description EMF image
151 \param hDC - descriptor of EMF
152 \param anAspect - line aspect
153 \param aViewerCS - viewer co-ordinates system
154 \param aPaperCS - paper co-ordinates system
156 HPEN AddLineAspectToEMF( HDC hDC, GLViewer_AspectLine* anAspect,
157 GLViewer_CoordSystem* aViewerCS, GLViewer_CoordSystem* aPaperCS )
161 QColor col1, col2, col3;
162 anAspect->getLineColors( col1, col2, col3 );
164 double x_stretch, y_stretch;
165 aViewerCS->getStretching( *aPaperCS, x_stretch, y_stretch );
167 double aWidth = anAspect->getLineWidth()*x_stretch;
168 int aLineType = anAspect->getLineType();
170 return CreatePen( PS_SOLID, aWidth, RGB( 255-col1.red(), 255-col1.green(), 255-col1.blue() ) );
178 Saves to file PostScript set of markers
179 \param hFile - file instance
180 \param aViewerCS - viewer co-ordinates system
181 \param aPSCS - paper co-ordinates system
183 bool GLViewer_MarkerSet::translateToPS( QFile& hFile, GLViewer_CoordSystem* aViewerCS, GLViewer_CoordSystem* aPSCS )
187 QString aBuffer = "newpath\n";
189 AddLineAspectToPS( aBuffer, getAspectLine(), aViewerCS, aPSCS );
191 for( int i=0; i<myNumber; i++ )
195 double x_stretch, y_stretch;
196 aViewerCS->getStretching( *aPSCS, x_stretch, y_stretch );
198 double x0 = myXCoord[i],
203 for( int j=0; j<=noPoints; j++ )
205 x = x0 + r*cos( double(j)*2*PI/double(noPoints) );
206 y = y0 + r*sin( double(j)*2*PI/double(noPoints) );
208 AddCoordsToPS( aBuffer, "moveto", aViewerCS, aPSCS, x, y, true );
210 AddCoordsToPS( aBuffer, "lineto", aViewerCS, aPSCS, x, y, true );
213 aBuffer+="closepath\nstroke\n";
215 hFile.write( aBuffer.toLatin1() );
221 Saves to file HPGL set of markers
222 \param hFile - file instance
223 \param aViewerCS - viewer co-ordinates system
224 \param aHPGLCS - paper co-ordinates system
226 bool GLViewer_MarkerSet::translateToHPGL( QFile& hFile, GLViewer_CoordSystem* aViewerCS,
227 GLViewer_CoordSystem* aHPGLCS )
231 for( int i=0; i<myNumber; i++ )
235 double x_stretch, y_stretch;
236 aViewerCS->getStretching( *aHPGLCS, x_stretch, y_stretch );
238 double x0 = myXCoord[i],
243 AddCoordsToHPGL( aBuffer, "PA", aViewerCS, aHPGLCS, x0+r, y0 );
245 for( int j=1; j<=noPoints; j++ )
247 x = x0 + r*cos( double(j)*2*PI/double(noPoints) );
248 y = y0 + r*sin( double(j)*2*PI/double(noPoints) );
249 AddCoordsToHPGL( aBuffer, "PD", aViewerCS, aHPGLCS, x, y );
253 hFile.write( aBuffer.toLatin1() );
261 Saves to EMF image set of markers
262 \param dc - EMF image descriptor
263 \param aViewerCS - viewer co-ordinates system
264 \param aEMFCS - paper co-ordinates system
266 bool GLViewer_MarkerSet::translateToEMF( HDC dc, GLViewer_CoordSystem* aViewerCS, GLViewer_CoordSystem* aEMFCS )
269 if( !aViewerCS || !aEMFCS )
272 HPEN pen = AddLineAspectToEMF( dc, getAspectLine(), aViewerCS, aEMFCS );
273 HGDIOBJ old = SelectObject( dc, pen );
275 for( int i=0; i<myNumber; i++ )
277 double x0 = myXCoord[i],
282 for( int j=0; j<=noPoints; j++ )
284 x = x0 + r*cos( double(j)*2*PI/double(noPoints) );
285 y = y0 + r*sin( double(j)*2*PI/double(noPoints) );
286 aViewerCS->transform( *aEMFCS, x, y );
288 MoveToEx( dc, x, y, NULL );
294 SelectObject( dc, old );
302 Computes all necessary information about object for presentation in drawer
304 void GLViewer_MarkerSet::compute()
306 // cout << "GLViewer_MarkerSet::compute" << endl;
307 GLfloat xa = myXCoord[0];
308 GLfloat xb = myXCoord[0];
309 GLfloat ya = myYCoord[0];
310 GLfloat yb = myYCoord[0];
312 for ( int i = 0; i < myNumber; i++ )
314 xa = qMin( xa, myXCoord[i] );
315 xb = qMax( xb, myXCoord[i] );
316 ya = qMin( ya, myYCoord[i] );
317 yb = qMax( yb, myYCoord[i] );
320 myXGap = ( xb - xa ) / 10;
321 myYGap = ( yb - ya ) / 10;
323 myRect->setLeft( xa - myXGap );
324 myRect->setTop( yb + myYGap );
325 myRect->setRight( xb + myXGap );
326 myRect->setBottom( ya - myYGap );
330 Creates corresponding drawer
332 GLViewer_Drawer* GLViewer_MarkerSet::createDrawer()
334 // cout << "GLViewer_MarkerSet::createDrawer" << endl;
335 return myDrawer = new GLViewer_MarkerDrawer();
339 Computes highlight presentation
342 \param tol - tolerance of detecting
343 \param isCircle - true if sensitive area of detection is round
344 \return true if highlight status is changed
346 GLboolean GLViewer_MarkerSet::highlight( GLfloat x, GLfloat y, GLfloat tol, GLboolean isCircle )
350 // cout << "GLViewer_MarkerSet::highlight " << x <<" " << y << " " << tol << endl;
352 GLfloat xdist, ydist, radius;
353 QList<int>::Iterator it;
354 QList<int> curHNumbers;
359 radius = tol - myMarkerSize / 2.;
361 myUHNumbers += myHNumbers;
364 for ( int i = 0; i < myNumber; i++ )
366 xdist = ( myXCoord[i] - x ) * myXScale;
367 ydist = ( myYCoord[i] - y ) * myYScale;
369 // if ( isCircle && ( xdist * xdist + ydist * ydist <= radius * radius ) ||
370 if ( ( isCircle && ( xdist * xdist + ydist * ydist <= myMarkerSize * myMarkerSize ) ) ||
371 ( !isCircle && ( fabs( xdist ) <= radius && fabs( ydist ) <= radius ) ) )
375 for ( it = myCurSelNumbers.begin(); it != myCurSelNumbers.end(); ++it )
379 curHNumbers.append( i );
383 myHNumbers.append( i );
388 myCurSelNumbers = curHNumbers;
390 myIsHigh = ( GLboolean )count;
391 update = ( GLboolean )( myHNumbers != myPrevHNumbers );
393 myPrevHNumbers = myHNumbers;
395 //cout << "GLViewer_MarkerSet::highlight complete with " << (int)myIsHigh << endl;
402 GLboolean GLViewer_MarkerSet::unhighlight()
404 if( !myHNumbers.isEmpty() )
406 myUHNumbers += myHNumbers;
407 myPrevHNumbers.clear();
409 //??? myCurSelNumbers.clear();
418 /param x, y - co-ordinates of mouse
419 /param tol - tolerance
420 /param rect - rectangle (in case of rectangular selection)
421 /param isFull - if it is true, then object may selected only if it lays whole in selection zone
422 \param isCircle - true if sensitive area of detection is round
423 \param isShift - true if selection exec with append option
425 GLboolean GLViewer_MarkerSet::select( GLfloat x, GLfloat y, GLfloat tol, GLViewer_Rect /*rect*/, GLboolean /*isFull*/,
426 GLboolean isCircle, GLboolean isShift )
430 // cout << "GLViewer_MarkerSet::select " << x << " " << y << endl;
432 GLfloat xdist, ydist, radius;
433 QList<int>::Iterator it;
434 QList<int>::Iterator it1;
435 QList<int>::Iterator remIt;
436 QList<int>::Iterator curIt;
438 radius = tol - myMarkerSize / 2.;
440 if( radius < myMarkerSize / 2.)
441 radius = myMarkerSize / 2.;
443 count = isShift ? mySelNumbers.count() : 0;
445 myUSelNumbers = mySelNumbers;
449 mySelNumbers.clear();
450 myCurSelNumbers.clear();
453 for ( int i = 0; i < myNumber; i++ )
455 xdist = ( myXCoord[i] - x ) * myXScale;
456 ydist = ( myYCoord[i] - y ) * myYScale;
458 //if ( isCircle && ( xdist * xdist + ydist * ydist <= radius * radius ) ||
459 if ( ( isCircle && ( xdist * xdist + ydist * ydist <= myMarkerSize * myMarkerSize ) ) ||
460 ( !isCircle && ( fabs( xdist ) <= radius && fabs( ydist ) <= radius ) ) )
465 bool isFound = false;
466 for( it = mySelNumbers.begin(); it != mySelNumbers.end(); ++it )
469 myUSelNumbers.append( *it );
477 mySelNumbers.append( i );
478 myCurSelNumbers.append( i );
479 for ( it1 = myHNumbers.begin(); it1 != myHNumbers.end(); ++it1 )
482 myHNumbers.erase( it1 );
485 for ( it1 = myUHNumbers.begin(); it1 != myUHNumbers.end(); ++it1 )
488 myUHNumbers.erase( it1 );
494 mySelNumbers.erase( remIt );
495 for ( curIt = myCurSelNumbers.begin(); curIt != myCurSelNumbers.end(); ++curIt )
496 if( *curIt == *remIt)
498 myCurSelNumbers.erase( curIt );
501 for ( it1 = myHNumbers.begin(); it1 != myHNumbers.end(); ++it1 )
504 myHNumbers.erase( it1 );
507 for ( it1 = myUHNumbers.begin(); it1 != myUHNumbers.end(); ++it1 )
510 myUHNumbers.erase( it1 );
517 mySelNumbers.append( i );
518 myCurSelNumbers.append( i );
519 for ( it1 = myHNumbers.begin(); it1 != myHNumbers.end(); ++it1 )
522 myHNumbers.erase( it1 );
525 for ( it1 = myUHNumbers.begin(); it1 != myUHNumbers.end(); ++it1 )
528 myUHNumbers.erase( it1 );
535 for( it = mySelNumbers.begin(); it != mySelNumbers.end(); ++it )
536 for( it1 = myUSelNumbers.begin(); it1 != myUSelNumbers.end(); ++it1 )
539 it1 = myUSelNumbers.erase( it1 );
543 myIsSel = (GLboolean)count;
545 // cout << "GLViewer_MarkerSet::select complete with " << (int)myIsSel << endl;
552 GLboolean GLViewer_MarkerSet::unselect()
554 if( !mySelNumbers.isEmpty() )
556 myUSelNumbers = mySelNumbers;
557 mySelNumbers.clear();
558 myCurSelNumbers.clear();
566 \return update object rectangle
567 Does not equal getRect() if object have a persistence to some viewer transformations
569 GLViewer_Rect* GLViewer_MarkerSet::getUpdateRect()
571 GLViewer_Rect* rect = new GLViewer_Rect();
573 rect->setLeft( myRect->left() + myXGap - myMarkerSize / myXScale );
574 rect->setTop( myRect->top() + myYGap + myMarkerSize / myYScale );
575 rect->setRight( myRect->right() - myXGap + myMarkerSize / myXScale );
576 rect->setBottom( myRect->bottom() - myYGap - myMarkerSize / myYScale );
577 //cout << " Additional tolerance " << myMarkerSize / myYScale << endl;
578 //rect->setLeft( myRect->left() - myMarkerSize / myXScale );
579 //rect->setTop( myRect->top() - myMarkerSize / myYScale );
580 //rect->setRight( myRect->right() + myMarkerSize / myXScale );
581 //rect->setBottom( myRect->bottom() + myMarkerSize / myYScale );
587 Sets array of x coords of points
588 \param xCoord - array of co-ordinates
589 \param size - array size
591 void GLViewer_MarkerSet::setXCoord( GLfloat* xCoord, int size )
593 myXCoord = new GLfloat[ size ];
594 for( int i = 0; i < size; i++ )
595 myXCoord[i] = xCoord[i];
599 Sets array of y coords of points
600 \param yCoord - array of co-ordinates
601 \param size - array size
603 void GLViewer_MarkerSet::setYCoord( GLfloat* yCoord, int size )
605 myYCoord = new GLfloat[ size ];
606 for( int i = 0; i < size; i++ )
607 myYCoord[i] = yCoord[i];
611 Sets number of markers
612 \param number - new number of markers
614 void GLViewer_MarkerSet::setNumMarkers( GLint number )
616 if ( myNumber == number )
619 if ( myXCoord && myYCoord )
626 myXCoord = new GLfloat[ myNumber ];
627 myYCoord = new GLfloat[ myNumber ];
632 Export numbers of highlighted/selected lines
634 void GLViewer_MarkerSet::exportNumbers( QList<int>& highlight,
635 QList<int>& unhighlight,
637 QList<int>& unselect )
639 highlight = myHNumbers;
640 unhighlight = myUHNumbers;
641 select = mySelNumbers;
642 unselect = myUSelNumbers;
644 myUHNumbers = myHNumbers;
648 Adds or remove selected number
649 \param index - selected index
651 bool GLViewer_MarkerSet::addOrRemoveSelected( int index )
653 if( index < 0 || index > myNumber )
656 int n = mySelNumbers.indexOf( index );
658 mySelNumbers.append( index );
661 mySelNumbers.removeAt(n);
662 myUSelNumbers.append( index );
668 Adds some selected numbers
669 \param seq - sequence of indices
671 void GLViewer_MarkerSet::addSelected( const TColStd_SequenceOfInteger& seq )
673 for ( int i = 1; i <= seq.Length(); i++ )
674 if( mySelNumbers.indexOf( seq.Value( i ) ) == -1 )
675 mySelNumbers.append( seq.Value( i ) - 1 );
679 Sets some numbers as selected
680 \param seq - sequence of indices
682 void GLViewer_MarkerSet::setSelected( const TColStd_SequenceOfInteger& seq )
684 // for( QList<int>::Iterator it = mySelNumbers.begin(); it != mySelNumbers.end(); ++it )
685 // if( myUSelNumbers.findIndex( *it ) == -1 )
686 // myUSelNumbers.append( *it );
688 myUSelNumbers = mySelNumbers;
689 mySelNumbers.clear();
691 for ( int i = 1; i <= seq.Length(); i++ )
692 mySelNumbers.append( seq.Value( i ) - 1 );
695 /*! Moves object by recomputing
696 \param dx - moving along X coord
697 \param dy - moving along Y coord
698 \param fromGroup - is true if this method called from group
700 void GLViewer_MarkerSet::moveObject( float theX, float theY, bool fromGroup )
702 if( !fromGroup && myGroup)
704 myGroup->dragingObjects( theX, theY );
707 for( int i = 0; i < myNumber; i++ )
709 myXCoord[i] = myXCoord[i] + theX;
710 myYCoord[i] = myYCoord[i] + theY;
716 Codes marker set as byte copy
719 QByteArray GLViewer_MarkerSet::getByteCopy()
722 int anISize = sizeof( GLint );
723 int aFSize = sizeof( GLfloat );
725 QByteArray aObject = GLViewer_Object::getByteCopy();
728 aResult.resize( anISize + 2*aFSize*myNumber + aFSize + aObject.size());
730 char* aPointer = (char*)&myNumber;
731 for( i = 0; i < anISize; i++, aPointer++ )
732 aResult[i] = *aPointer;
734 aPointer = (char*)myXCoord;
735 for( ; i < anISize + aFSize*myNumber; i++, aPointer++ )
736 aResult[i] = *aPointer;
737 aPointer = (char*)myYCoord;
738 for( ; i < anISize + 2*aFSize*myNumber; i++, aPointer++ )
739 aResult[i] = *aPointer;
741 aPointer = (char*)&myMarkerSize;
742 for( ; i < anISize + 2*aFSize*myNumber + aFSize; i++, aPointer++ )
743 aResult[i] = *aPointer;
746 for ( ; i < (int)aResult.size(); i++ )
747 aResult[i] = aObject[i - anISize - 2*aFSize*myNumber - aFSize];
753 Initialize marker set by byte array
754 \param theArray - byte array
756 bool GLViewer_MarkerSet::initializeFromByteCopy( QByteArray theArray )
759 int anISize = sizeof( GLint );
760 int aFSize = sizeof( GLfloat );
762 char* aPointer = (char*)&myNumber;
763 for( i = 0; i < anISize; i++, aPointer++ )
764 *aPointer = theArray[i];
766 int aSize = theArray.size();
767 if( aSize < anISize + 2*aFSize*myNumber + aFSize)
770 myXCoord = new GLfloat[myNumber];
771 myYCoord = new GLfloat[myNumber];
772 aPointer = (char*)myXCoord;
773 for( ; i < anISize + aFSize*myNumber; i++, aPointer++ )
774 *aPointer = theArray[i];
775 aPointer = (char*)myYCoord;
776 for( ; i < anISize + 2*aFSize*myNumber; i++, aPointer++ )
777 *aPointer = theArray[i];
779 aPointer = (char*)&myMarkerSize;
780 for( ; i < anISize + 2*aFSize*myNumber + aFSize; i++, aPointer++ )
781 *aPointer = theArray[i];
783 int aCurIndex = anISize + 2*aFSize*myNumber + aFSize;
785 aObject.resize( aSize - aCurIndex );
786 for( ; i < aSize; i++ )
787 aObject[i - aCurIndex] = theArray[i];
790 if( !GLViewer_Object::initializeFromByteCopy( aObject ) || myType != "GLViewer_MarkerSet" )
795 mySelNumbers.clear();
796 myUSelNumbers.clear();
797 myCurSelNumbers.clear();
798 myPrevHNumbers.clear();
804 \class GLViewer_Polyline
813 \param number - number of segments
814 \param size - size of polyline
815 \param toolTip - tool tip of polyline
817 GLViewer_Polyline::GLViewer_Polyline( int number, float /*size*/, const QString& toolTip ):
823 myHighFlag = GL_TRUE;
827 mySelNumbers.clear();
828 myUSelNumbers.clear();
829 myCurSelNumbers.clear();
830 myPrevHNumbers.clear();
834 myType = "GLViewer_Polyline";
835 myToolTipText = toolTip;
839 Destructor, destroys internal arrays of co-ordinates
841 GLViewer_Polyline::~GLViewer_Polyline()
850 Saves polyline to file PostScript
851 \param hFile - file instance
852 \param aViewerCS - viewer co-ordinates system
853 \param aPSCS - paper co-ordinates system
855 bool GLViewer_Polyline::translateToPS( QFile& hFile, GLViewer_CoordSystem* aViewerCS, GLViewer_CoordSystem* aPSCS )
857 QString aBuffer = "newpath\n";
859 AddLineAspectToPS( aBuffer, getAspectLine(), aViewerCS, aPSCS );
861 for( int i=0; i<myNumber; i++ )
863 AddCoordsToPS( aBuffer, "moveto", aViewerCS, aPSCS, myXCoord[i], myYCoord[i] );
865 AddCoordsToPS( aBuffer, "lineto", aViewerCS, aPSCS, myXCoord[i], myYCoord[i] );
868 AddCoordsToPS( aBuffer, "lineto", aViewerCS, aPSCS, myXCoord[0], myYCoord[0] );
870 aBuffer+="closepath\nstroke\n";
872 hFile.write( aBuffer.toLatin1() );
878 Saves polyline to file HPGL
879 \param hFile - file instance
880 \param aViewerCS - viewer co-ordinates system
881 \param aHPGLCS - paper co-ordinates system
883 bool GLViewer_Polyline::translateToHPGL( QFile& hFile, GLViewer_CoordSystem* aViewerCS, GLViewer_CoordSystem* aHPGLCS )
885 QString aBuffer = "";
886 for( int i=0; i<myNumber; i++ )
888 AddCoordsToHPGL( aBuffer, "PA", aViewerCS, aHPGLCS, myXCoord[i], myYCoord[i] );
894 AddCoordsToHPGL( aBuffer, "PA", aViewerCS, aHPGLCS, myXCoord[0], myYCoord[0] );
898 hFile.write( aBuffer.toLatin1() );
905 Saves polyline to EMF image
906 \param dc - EMF image descriptor
907 \param aViewerCS - viewer co-ordinates system
908 \param aEMFCS - paper co-ordinates system
910 bool GLViewer_Polyline::translateToEMF( HDC dc, GLViewer_CoordSystem* aViewerCS, GLViewer_CoordSystem* aEMFCS )
912 if( !aViewerCS || !aEMFCS )
915 HPEN pen = AddLineAspectToEMF( dc, getAspectLine(), aViewerCS, aEMFCS );
916 HGDIOBJ old = SelectObject( dc, pen );
919 for( int i=0; i<myNumber; i++ )
923 aViewerCS->transform( *aEMFCS, x, y );
925 MoveToEx( dc, x, y, NULL );
934 aViewerCS->transform( *aEMFCS, x, y );
938 SelectObject( dc, old );
947 Computes all necessary information about object for presentation in drawer
949 void GLViewer_Polyline::compute()
951 // cout << "GLViewer_MarkerSet::compute" << endl;
952 GLfloat xa = myXCoord[0];
953 GLfloat xb = myXCoord[0];
954 GLfloat ya = myYCoord[0];
955 GLfloat yb = myYCoord[0];
957 for ( int i = 0; i < myNumber; i++ )
959 xa = qMin( xa, myXCoord[i] );
960 xb = qMax( xb, myXCoord[i] );
961 ya = qMin( ya, myYCoord[i] );
962 yb = qMax( yb, myYCoord[i] );
965 GLfloat xGap = ( xb - xa ) / 10;
966 GLfloat yGap = ( yb - ya ) / 10;
968 myRect->setLeft( xa - xGap );
969 myRect->setTop( yb + yGap );
970 myRect->setRight( xb + xGap );
971 myRect->setBottom( ya - yGap );
975 \return update object rectangle
976 Does not equal getRect() if object have a persistence to some viewer transformations
978 GLViewer_Rect* GLViewer_Polyline::getUpdateRect()
980 GLViewer_Rect* rect = new GLViewer_Rect();
982 rect->setLeft( myRect->left() - myXGap );
983 rect->setTop( myRect->top() + myYGap );
984 rect->setRight( myRect->right() + myXGap );
985 rect->setBottom( myRect->bottom() - myYGap );
991 Creates corresponding drawer
993 GLViewer_Drawer* GLViewer_Polyline::createDrawer()
995 // cout << "GLViewer_MarkerSet::createDrawer" << endl;
996 return myDrawer = new GLViewer_PolylineDrawer();
1000 Computes highlight presentation
1003 \param tol - tolerance of detecting
1004 \param isCircle - true if sensitive area of detection is round
1005 \return true if highlight status is changed
1007 GLboolean GLViewer_Polyline::highlight( GLfloat x, GLfloat y, GLfloat /*tol*/, GLboolean /*isCircle*/ )
1011 GLfloat xa, xb, ya, yb, l;
1012 GLfloat rsin, rcos, r, ra, rb;
1014 GLboolean highlighted = myIsHigh;
1016 myIsHigh = GL_FALSE;
1022 for( int i = 0; i < myNumber-1+c; i++ )
1026 if( i != myNumber-1 )
1037 l = sqrt( (xb-xa)*(xb-xa) + (yb-ya)*(yb-ya) );
1040 r = ( (x-xa)*(y-yb) - (x-xb)*(y-ya) ) / ( rsin*(ya-yb) + rcos*(xa-xb) );
1041 ra = sqrt( (x-xa)*(x-xa) + (y-ya)*(y-ya) );
1042 rb = sqrt( (x-xb)*(x-xb) + (y-yb)*(y-yb) );
1043 if( fabs( r ) * myXScale <= DISTANTION && ra <= l + DISTANTION && rb <= l + DISTANTION )
1050 if( !myHighFlag && myIsHigh )
1051 myIsHigh = GL_FALSE;
1053 myHighFlag = GL_TRUE;
1055 update = ( GLboolean )( myIsHigh != highlighted );
1057 // cout << "GLViewer_Polyline::highlight complete with " << (int)myIsHigh << endl;
1064 GLboolean GLViewer_Polyline::unhighlight()
1066 // if( !myHNumbers.isEmpty() )
1068 // myUHNumbers = myHNumbers;
1069 // myHNumbers.clear();
1075 myIsHigh = GL_FALSE;
1084 /param x, y - co-ordinates of mouse
1085 /param tol - tolerance
1086 /param rect - rectangle (in case of rectangular selection)
1087 /param isFull - if it is true, then object may selected only if it lays whole in selection zone
1088 \param isCircle - true if sensitive area of detection is round
1089 \param isShift - true if selection exec with append option
1091 GLboolean GLViewer_Polyline::select( GLfloat x, GLfloat y, GLfloat /*tol*/, GLViewer_Rect /*rect*/, GLboolean /*isFull*/,
1092 GLboolean /*isCircle*/, GLboolean /*isShift*/ )
1096 GLfloat xa, xb, ya, yb, l;
1097 GLfloat rsin, rcos, r, ra, rb;
1098 // GLboolean update;
1099 // GLboolean selected = myIsSel;
1107 for( int i = 0; i < myNumber-1+c; i++ )
1111 if( i != myNumber-1 )
1122 l = sqrt( (xb-xa)*(xb-xa) + (yb-ya)*(yb-ya) );
1125 r = ( (x-xa)*(y-yb) - (x-xb)*(y-ya) ) / ( rsin*(ya-yb) + rcos*(xa-xb) );
1126 ra = sqrt( (x-xa)*(x-xa) + (y-ya)*(y-ya) );
1127 rb = sqrt( (x-xb)*(x-xb) + (y-yb)*(y-yb) );
1128 if( fabs( r ) * myXScale <= DISTANTION && ra <= l + DISTANTION && rb <= l + DISTANTION )
1137 myHighFlag = GL_FALSE;
1138 myIsHigh = GL_FALSE;
1141 myHighFlag = GL_TRUE;
1143 // update = ( GLboolean )( myIsSel != selected );
1145 // cout << "GLViewer_Polyline::select complete with " << (int)myIsSel << endl;
1147 // return update; !!!!!!!!!!!!!!!!!!!!!!!!!!! no here
1154 GLboolean GLViewer_Polyline::unselect()
1156 // if( !mySelNumbers.isEmpty() )
1158 // myUSelNumbers = mySelNumbers;
1159 // mySelNumbers.clear();
1160 // myCurSelNumbers.clear();
1174 Sets array of abscisses for points of polyline
1175 \param xCoord - array of of abscisses
1176 \param size - size of array
1178 void GLViewer_Polyline::setXCoord( GLfloat* xCoord, int size )
1180 myXCoord = new GLfloat[ size ];
1181 for( int i = 0; i < size; i++ )
1182 myXCoord[i] = xCoord[i];
1186 Sets array of ordinates for points of polyline
1187 \param xCoord - array of of ordinates
1188 \param size - size of array
1190 void GLViewer_Polyline::setYCoord( GLfloat* yCoord, int size )
1192 myYCoord = new GLfloat[ size ];
1193 for( int i = 0; i < size; i++ )
1194 myYCoord[i] = yCoord[i];
1198 Sets number of points
1199 \param number - new number of points
1201 void GLViewer_Polyline::setNumber( GLint number )
1203 if ( myNumber == number )
1206 if ( myXCoord && myYCoord )
1213 myXCoord = new GLfloat[ myNumber ];
1214 myYCoord = new GLfloat[ myNumber ];
1218 Export numbers of highlighted/selected lines
1220 void GLViewer_Polyline::exportNumbers( QList<int>& highlight,
1221 QList<int>& unhighlight,
1223 QList<int>& unselect )
1225 highlight = myHNumbers;
1226 unhighlight = myUHNumbers;
1227 select = mySelNumbers;
1228 unselect = myUSelNumbers;
1232 Moves object by recomputing
1233 \param dx - moving along X coord
1234 \param dy - moving along Y coord
1235 \param fromGroup - is true if this method called from group
1237 void GLViewer_Polyline::moveObject( float theX, float theY, bool fromGroup )
1239 if( !fromGroup && myGroup)
1241 myGroup->dragingObjects( theX, theY );
1244 for( int i = 0; i < myNumber; i++ )
1246 myXCoord[i] = myXCoord[i] + theX;
1247 myYCoord[i] = myYCoord[i] + theY;
1253 Codes polyline as byte copy
1256 QByteArray GLViewer_Polyline::getByteCopy()
1259 int anISize = sizeof( GLint );
1260 int aFSize = sizeof( GLfloat );
1261 int aBSize = sizeof( GLboolean );
1263 QByteArray aObject = GLViewer_Object::getByteCopy();
1266 aResult.resize( aFSize*myNumber*2 + anISize + 2*aBSize + aObject.size());
1268 char* aPointer = (char*)&myNumber;
1269 for( i = 0; i < anISize; i++, aPointer++ )
1270 aResult[i] = *aPointer;
1272 aPointer = (char*)myXCoord;
1273 for( ; i < anISize + aFSize*myNumber; i++, aPointer++ )
1274 aResult[i] = *aPointer;
1275 aPointer = (char*)myYCoord;
1276 for( ; i < anISize + 2*aFSize*myNumber; i++, aPointer++ )
1277 aResult[i] = *aPointer;
1279 aPointer = (char*)&myIsClosed;
1280 for( ; i < anISize + 2*aFSize*myNumber + aBSize; i++, aPointer++ )
1281 aResult[i] = *aPointer;
1282 aPointer = (char*)&myHighSelAll;
1283 for( ; i < anISize + 2*aFSize*myNumber + 2*aBSize; i++, aPointer++ )
1284 aResult[i] = *aPointer;
1286 for ( ; i < (int)aResult.size(); i++ )
1287 aResult[i] = aObject[i - anISize - 2*aFSize*myNumber - 2*aBSize];
1294 Initialize polyline by byte array
1295 \param theArray - byte array
1297 bool GLViewer_Polyline::initializeFromByteCopy( QByteArray theArray )
1300 int anISize = sizeof( GLint );
1301 int aFSize = sizeof( GLfloat );
1302 int aBSize = sizeof( GLboolean );
1304 char* aPointer = (char*)&myNumber;
1305 for( i = 0; i < anISize; i++, aPointer++ )
1306 *aPointer = theArray[i];
1308 int aSize = theArray.size();
1309 if( aSize < aFSize*myNumber*2 + anISize + 2*aBSize )
1312 myXCoord = new GLfloat[myNumber];
1313 myYCoord = new GLfloat[myNumber];
1314 aPointer = (char*)myXCoord;
1315 for( ; i < anISize + aFSize*myNumber; i++, aPointer++ )
1316 *aPointer = theArray[i];
1317 aPointer = (char*)myYCoord;
1318 for( ; i < anISize + 2*aFSize*myNumber; i++, aPointer++ )
1319 *aPointer = theArray[i];
1321 aPointer = (char*)&myIsClosed;
1322 for( ; i < anISize + 2*aFSize*myNumber + aBSize; i++, aPointer++ )
1323 *aPointer = theArray[i];
1324 aPointer = (char*)&myHighSelAll;
1325 for( ; i < anISize + 2*aFSize*myNumber + 2*aBSize; i++, aPointer++ )
1326 *aPointer = theArray[i];
1328 int aCurIndex = anISize + 2*aFSize*myNumber + 2*aBSize;
1330 aObject.resize( aSize - aCurIndex );
1331 for( ; i < aSize; i++ )
1332 aObject[i - aCurIndex] = theArray[i];
1334 if( !GLViewer_Object::initializeFromByteCopy( aObject ) || myType != "GLViewer_Polyline" )
1338 myUHNumbers.clear();
1339 mySelNumbers.clear();
1340 myUSelNumbers.clear();
1341 myCurSelNumbers.clear();
1342 myPrevHNumbers.clear();
1351 \param theStr - text string
1352 \param xPos - x position
1353 \param yPos - y position
1354 \param color - color of text
1355 \param toolTip - tooltip of text object
1357 GLViewer_TextObject::GLViewer_TextObject( const QString& theStr, float xPos, float yPos,
1358 const QColor& color, const QString& toolTip )
1361 myGLText = new GLViewer_Text( theStr, xPos, yPos, color );
1365 myHighFlag = GL_TRUE;
1367 myToolTipText = toolTip;
1373 GLViewer_TextObject::~GLViewer_TextObject()
1380 Saves text object to file PostScript
1381 \param hFile - file instance
1382 \param aViewerCS - viewer co-ordinates system
1383 \param aPSCS - paper co-ordinates system
1385 bool GLViewer_TextObject::translateToPS( QFile& hFile, GLViewer_CoordSystem* aViewerCS, GLViewer_CoordSystem* aPSCS )
1387 QString aText = myGLText->getText();
1389 myGLText->getPosition( xPos, yPos );
1391 QString aBuffer = "/Times-Roman findfont\n";
1392 aBuffer += "12 scalefont setfont\n";
1394 AddCoordsToPS( aBuffer, "moveto", aViewerCS, aPSCS, double(xPos), double(yPos) );
1395 aBuffer += "(" + aText + ") show\n";
1397 hFile.write( aBuffer.toLatin1() );
1403 Saves text object to file HPGL
1404 \param hFile - file instance
1405 \param aViewerCS - viewer co-ordinates system
1406 \param aHPGLCS - paper co-ordinates system
1408 bool GLViewer_TextObject::translateToHPGL( QFile& hFile, GLViewer_CoordSystem* aViewerCS, GLViewer_CoordSystem* aHPGLCS )
1410 QString aText = myGLText->getText();
1412 myGLText->getPosition( xPos, yPos );
1414 QString aBuffer = "";
1415 AddCoordsToHPGL( aBuffer, "PA", aViewerCS, aHPGLCS, double(xPos), double(yPos) );
1417 aBuffer = "LB" + aText + "#;";
1419 hFile.write( aBuffer.toLatin1() );
1426 Saves text object to EMF image
1427 \param dc - EMF image descriptor
1428 \param aViewerCS - viewer co-ordinates system
1429 \param aEMFCS - paper co-ordinates system
1431 bool GLViewer_TextObject::translateToEMF( HDC dc, GLViewer_CoordSystem* aViewerCS, GLViewer_CoordSystem* aEMFCS )
1433 QString aText = myGLText->getText();
1435 myGLText->getPosition( xPos, yPos );
1437 double x = double( xPos ),
1440 aViewerCS->transform( *aEMFCS, x, y );
1442 int nHeight = 35*14; // height of font
1443 int nWidth = 35*12; // average character width
1444 int nEscapement = 0; // angle of escapement
1445 int nOrientation = 0; // base-line orientation angle
1446 int fnWeight = FW_NORMAL; // font weight
1447 DWORD fdwItalic = false; // italic attribute option
1448 DWORD fdwUnderline = false; // underline attribute option
1449 DWORD fdwStrikeOut = false; // strikeout attribute option
1450 DWORD fdwCharSet = ANSI_CHARSET; // character set identifier
1451 DWORD fdwOutputPrecision = OUT_DEFAULT_PRECIS; // output precision
1452 DWORD fdwClipPrecision = CLIP_DEFAULT_PRECIS; // clipping precision
1453 DWORD fdwQuality = PROOF_QUALITY; // output quality
1454 DWORD fdwPitchAndFamily = FIXED_PITCH | FF_DONTCARE; // pitch and family
1455 LPCTSTR lpszFace = NULL; // typeface name
1458 HFONT aFont = CreateFont( nHeight, nWidth, nEscapement, nOrientation, fnWeight, fdwItalic,
1459 fdwUnderline, fdwStrikeOut, fdwCharSet, fdwOutputPrecision,
1460 fdwClipPrecision, fdwQuality, fdwPitchAndFamily, lpszFace );
1461 LOGBRUSH aBrushData;
1462 aBrushData.lbStyle = BS_HOLLOW;
1464 HBRUSH aBrush = CreateBrushIndirect( &aBrushData );
1466 HGDIOBJ old1 = SelectObject( dc, aFont );
1467 HGDIOBJ old2 = SelectObject( dc, aBrush );
1469 LPTSTR str = new TCHAR[aText.length() + 1];
1470 str[aText.toWCharArray(str)] = '\0';
1472 QByteArray arr = FileName.toLatin1();
1473 LPTSTR str = arr.constData();
1475 TextOut( dc, x, y, str, aText.length() );
1480 SelectObject ( dc, old1 );
1481 SelectObject ( dc, old2 );
1483 DeleteObject( aFont );
1490 Creates corresponding drawer
1492 GLViewer_Drawer* GLViewer_TextObject::createDrawer()
1494 myDrawer = new GLViewer_TextDrawer();
1500 Computes all necessary information about object for presentation in drawer
1502 void GLViewer_TextObject::compute()
1505 QString aStr = myGLText->getText();
1506 myGLText->getPosition( xPos, yPos );
1508 myWidth = myGLText->getWidth();
1509 myHeight = myGLText->getHeight();
1510 myRect->setLeft( xPos );
1511 myRect->setTop( yPos + myHeight );
1512 myRect->setRight( xPos + myWidth );
1513 myRect->setBottom( yPos );
1517 Installing already exist drawer with same type
1518 \param theDrawer - new drawer
1520 void GLViewer_TextObject::setDrawer( GLViewer_Drawer* theDrawer )
1522 myDrawer = theDrawer;
1527 \return update object rectangle
1528 Does not equal getRect() if object have a persistence to some viewer transformations
1530 GLViewer_Rect* GLViewer_TextObject::getUpdateRect()
1532 GLViewer_Rect* rect = new GLViewer_Rect();
1535 QString aStr = myGLText->getText();
1536 myGLText->getPosition( xPos, yPos );
1538 rect->setLeft( myRect->left() + myXGap - myWidth / myXScale );
1539 rect->setTop( myRect->top() + myYGap + myHeight / myYScale );
1540 rect->setRight( myRect->right() - myXGap + myWidth / myXScale );
1541 rect->setBottom( myRect->bottom() - myYGap - myHeight / myYScale );
1547 Computes highlight presentation
1550 \param tol - tolerance of detecting
1551 \param isCircle - true if sensitive area of detection is round
1552 \return true if highlight status is changed
1554 GLboolean GLViewer_TextObject::highlight( GLfloat theX, GLfloat theY, GLfloat theTol, GLboolean isCircle )
1560 myGLText->getPosition( xPos, yPos );
1563 aRect.setLeft( (int)xPos );
1564 aRect.setRight( (int)(xPos + myWidth / myXScale) );
1565 aRect.setTop( (int)yPos );// - myHeight / myYScale );
1566 aRect.setBottom( (int)(yPos + myHeight / myYScale) );
1568 //cout << "theX: " << theX << " theY: " << theY << endl;
1569 //cout << "aRect.left(): " << aRect.left() << " aRect.right(): " << aRect.right() << endl;
1570 //cout << "aRect.top(): " << aRect.top() << " aRect.bottom(): " << aRect.bottom() << endl;
1572 QRegion obj( aRect );
1573 QRegion intersection;
1576 region.setLeft( (int)(theX - theTol) );
1577 region.setRight( (int)(theX + theTol) );
1578 region.setTop( (int)(theY - theTol) );
1579 region.setBottom( (int)(theY + theTol) );
1581 QRegion circle( (int)(theX - theTol), (int)(theY - theTol),
1582 (int)(2 * theTol), (int)(2 * theTol), QRegion::Ellipse );
1584 intersection = obj.intersected( circle );
1586 intersection = obj.intersected( region );
1588 if( intersection.isEmpty() )
1593 if( !myHighFlag && myIsHigh )
1594 myIsHigh = GL_FALSE;
1596 myHighFlag = GL_TRUE;
1604 GLboolean GLViewer_TextObject::unhighlight()
1608 myIsHigh = GL_FALSE;
1617 /param x, y - co-ordinates of mouse
1618 /param tol - tolerance
1619 /param rect - rectangle (in case of rectangular selection)
1620 /param isFull - if it is true, then object may selected only if it lays whole in selection zone
1621 \param isCircle - true if sensitive area of detection is round
1622 \param isShift - true if selection exec with append option
1624 GLboolean GLViewer_TextObject::select( GLfloat theX, GLfloat theY, GLfloat theTol, GLViewer_Rect /*rect*/,
1625 GLboolean /*isFull*/, GLboolean isCircle, GLboolean /*isShift*/ )
1630 QRegion obj( myRect->toQRect() );
1631 QRegion intersection;
1634 region.setLeft( (int)(theX - theTol) );
1635 region.setRight( (int)(theX + theTol) );
1636 region.setTop( (int)(theY - theTol) );
1637 region.setBottom( (int)(theY + theTol) );
1639 QRegion circle( (int)(theX - theTol), (int)(theY - theTol),
1640 (int)(2 * theTol), (int)(2 * theTol), QRegion::Ellipse );
1642 intersection = obj.intersected( circle );
1644 intersection = obj.intersected( region );
1646 if( intersection.isEmpty() )
1653 myHighFlag = GL_FALSE;
1654 myIsHigh = GL_FALSE;
1657 myHighFlag = GL_TRUE;
1663 Unselects text object
1665 GLboolean GLViewer_TextObject::unselect()
1677 Moves object by recomputing
1678 \param dx - moving along X coord
1679 \param dy - moving along Y coord
1680 \param fromGroup - is true if this method called from group
1682 void GLViewer_TextObject::moveObject( float theX, float theY, bool fromGroup )
1684 if( !fromGroup && myGroup)
1686 myGroup->dragingObjects( theX, theY );
1690 myGLText->getPosition( aX, anY );
1693 myGLText->setPosition( aX, anY );
1698 Codes text object as byte copy
1701 QByteArray GLViewer_TextObject::getByteCopy()
1703 QByteArray aObject = GLViewer_Object::getByteCopy();
1709 Initialize text object by byte array
1710 \param theArray - byte array
1712 bool GLViewer_TextObject::initializeFromByteCopy( QByteArray theArray )
1714 if( !GLViewer_Object::initializeFromByteCopy( theArray ) || myType != "GLViewer_TextObject" )