Salome HOME
correct merge BR_hydro_v1_0_3 on BR_quadtree
[modules/hydro.git] / src / HYDROGUI / HYDROGUI_ShapeImage.cxx
1 // Copyright (C) 2007-2013  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
5 //
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.
10 //
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.
15 //
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
19 //
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22
23 #include <HYDROGUI_ShapeImage.h>
24 #include <HYDROGUI_DataObject.h>
25 #include <HYDROGUI_Tool.h>
26 #include <HYDROData_Document.h>
27 #include <HYDROData_Image.h>
28
29 #include <AIS_TexturedShape.hxx>
30 #include <BRepBuilderAPI_MakeEdge.hxx>
31 #include <BRepBuilderAPI_MakeWire.hxx>
32 #include <gp_Pnt.hxx>
33 #include <TopoDS_Edge.hxx>
34 #include <TopoDS_Wire.hxx>
35
36 #include <SUIT_MessageBox.h>
37 #include <QFile>
38
39 HYDROGUI_ShapeImage::HYDROGUI_ShapeImage( const Handle(AIS_InteractiveContext)& theContext,
40                                           const Handle_HYDROData_Image&         theImage,
41                                           const int                             theZLayer )
42 : HYDROGUI_Shape( theContext, theImage, theZLayer )
43 {
44 }
45
46 HYDROGUI_ShapeImage::~HYDROGUI_ShapeImage()
47 {
48   removeTextureFile();
49 }
50
51 void HYDROGUI_ShapeImage::update( bool theIsUpdateViewer, bool isDeactivateSelection )
52 {
53   setIsToUpdate( false );
54
55   // Try to retrieve information from object
56   Handle(HYDROData_Image) anImageObj = Handle(HYDROData_Image)::DownCast( getObject() );
57
58   if( !anImageObj.IsNull() )
59   {
60     removeTextureFile();
61
62     QString aTextureFileName = generateTextureFileName( anImageObj );
63
64     QImage anImage = anImageObj->Image();
65     QString aFilePath = anImageObj->GetFilePath();
66     QTransform aTrsf = anImageObj->Trsf();
67
68     int aWidth = anImage.width();
69     int aHeight = anImage.height();
70
71     QString anImageError = "";
72
73     QTransform anInversion = QTransform::fromScale( -1, -1 );
74     anImage = anImage.transformed( anInversion * aTrsf, Qt::SmoothTransformation );
75
76     if ( anImage.isNull() )
77       anImageError = QObject::tr( "IMAGE_TRANSFORMATION_CAN_NOT_BE_APPLYED" );
78     else
79     {
80       // Workaround: Scale the texture image to the nearest width multiple 4 due to the CASCADE bug 23813
81       int aTrsfWidth = anImage.width();
82       int aDelta = aTrsfWidth % 4;
83       if ( aDelta > 0 )
84       {
85         aTrsfWidth += ( 4 - aDelta );
86       }
87       anImage = anImage.scaledToWidth( aTrsfWidth );
88
89       // temporary optimization, to reduce the saved image size (and the texture quality)
90       QImage anImageToSave = anImage; //RKV:reduceTexture( anImage, 500 );
91
92       bool isSaved = anImageToSave.save( aTextureFileName );
93       if ( !isSaved )
94         anImageError = QObject::tr( "FILE_CAN_NOT_BE_CREATED" ).arg( aTextureFileName );
95       else
96         QFile::setPermissions( aTextureFileName, (QFile::Permissions)0x4FFFF );
97     }
98
99     if ( !anImageError.isEmpty() )
100     {
101       SUIT_MessageBox::warning( 0, QObject::tr( "SHAPE_IMAGE_ERROR" ),
102                                 QObject::tr( "IMAGE_CAN_NOT_BE_CREATED" ) + anImageError );
103     }
104
105     QPointF aPoint1( 0, 0 );            // 1: top left
106     QPointF aPoint2( aWidth, 0 );       // 2: top right
107     QPointF aPoint3( aWidth, aHeight ); // 3: bottom right
108     QPointF aPoint4( 0, aHeight );      // 4: bottom left
109
110     aPoint1 = aTrsf.map( aPoint1 );
111     aPoint2 = aTrsf.map( aPoint2 );
112     aPoint3 = aTrsf.map( aPoint3 );
113     aPoint4 = aTrsf.map( aPoint4 );
114
115     QPolygonF aPolygon = QPolygonF() << aPoint1 << aPoint2 << aPoint3 << aPoint4;
116     QRectF aRect = aPolygon.boundingRect();
117
118     gp_Pnt aPnt1( aRect.topLeft().x(), aRect.topLeft().y(), 0 );
119     gp_Pnt aPnt2( aRect.topRight().x(), aRect.topRight().y(), 0 );
120     gp_Pnt aPnt3( aRect.bottomRight().x(), aRect.bottomRight().y(), 0 );
121     gp_Pnt aPnt4( aRect.bottomLeft().x(), aRect.bottomLeft().y(), 0 );
122
123     Handle_HYDROData_Document aDoc = HYDROData_Document::Document( anImageObj->Label() );
124     aDoc->Transform( aPnt1, true );
125     aDoc->Transform( aPnt2, true );
126     aDoc->Transform( aPnt3, true );
127     aDoc->Transform( aPnt4, true );
128
129     TopoDS_Edge anEdge1 = BRepBuilderAPI_MakeEdge( aPnt1, aPnt2 ).Edge();
130     TopoDS_Edge anEdge2 = BRepBuilderAPI_MakeEdge( aPnt2, aPnt3 ).Edge();
131     TopoDS_Edge anEdge3 = BRepBuilderAPI_MakeEdge( aPnt3, aPnt4 ).Edge();
132     TopoDS_Edge anEdge4 = BRepBuilderAPI_MakeEdge( aPnt4, aPnt1 ).Edge();
133
134     TopoDS_Wire aWire = BRepBuilderAPI_MakeWire( anEdge1, anEdge2, anEdge3, anEdge4 ).Wire();
135     aWire.Closed( true );
136
137     setTextureFileName( aTextureFileName, false, false );
138     setFace( aWire, false, false, aTextureFileName );
139     isDeactivateSelection = true;
140   }
141  
142   HYDROGUI_Shape::update( theIsUpdateViewer, isDeactivateSelection );
143 }
144
145 void HYDROGUI_ShapeImage::setTextureFileName( const QString& theFileName,
146                                               const bool     theToDisplay,
147                                               const bool     theIsUpdateViewer )
148 {
149   myTextureFileName = theFileName;
150   updateShape( theToDisplay, theIsUpdateViewer );
151 }
152
153 QString HYDROGUI_ShapeImage::getTextureFileName() const
154 {
155   return myTextureFileName;
156 }
157
158 QString HYDROGUI_ShapeImage::generateTextureFileName( const Handle(HYDROData_Entity)& theImageObj )
159 {
160   QString aResult;
161   if( !theImageObj.IsNull() )
162   {
163     QString aTempDir = HYDROGUI_Tool::GetTempDir( true );
164
165     int aStudyId = HYDROGUI_Tool::GetActiveStudyId();
166     QString aPrefix = QString( "image_%1" ).arg( aStudyId );
167
168     QString anEntry = HYDROGUI_DataObject::dataObjectEntry( theImageObj, false );
169     anEntry.replace( ':', '_' );
170
171     QString anExtension = "bmp";
172
173     aResult = QString( "%1/%2_%3.%4" ).arg( aTempDir, aPrefix, anEntry, anExtension );
174   }
175   return aResult;
176 }
177
178 void HYDROGUI_ShapeImage::removeTextureFile() const
179 {
180   QFile aFile( getTextureFileName() );
181   if( aFile.exists() )
182     aFile.remove();
183 }
184
185 QImage HYDROGUI_ShapeImage::reduceTexture( const QImage& theImage, const int theSizeLimit )
186 {
187   double aSizeLimit = (double)theSizeLimit;
188   double aWidth = (double)theImage.width();
189   double aHeight = (double)theImage.height();
190   if( aWidth > aSizeLimit || aHeight > aSizeLimit )
191   {
192     if( aWidth > aHeight )
193     {
194       aHeight /= ( aWidth / aSizeLimit );
195       aWidth = aSizeLimit;
196     }
197     else
198     {
199       aWidth /= ( aHeight / aSizeLimit );
200       aHeight = aSizeLimit;
201     }
202   }
203   return theImage.scaled( aWidth, aHeight, Qt::KeepAspectRatio, Qt::SmoothTransformation );
204 }
205
206 Handle_AIS_InteractiveObject HYDROGUI_ShapeImage::createShape() const
207 {
208   QString aTextureFileName = getTextureFileName();
209   bool anIsTexture = !aTextureFileName.isEmpty();
210   if ( anIsTexture )
211   {
212     Handle_AIS_TexturedShape aTexturedShape = new AIS_TexturedShape( getTopoShape() );
213
214     aTexturedShape->SetTextureFileName( HYDROGUI_Tool::ToAsciiString( aTextureFileName ) );
215     aTexturedShape->SetTextureMapOn();
216     // Just use the texture image as is
217     aTexturedShape->DisableTextureModulate();
218     aTexturedShape->SetTextureRepeat( false ); // don't repeat the texture image on the face
219
220     return aTexturedShape;
221   }
222   else
223     return Handle_AIS_InteractiveObject();
224 }
225