]> Shamusworld >> Repos - architektonas/blob - src/base/rs_image.cpp
Refactoring: Moved RS_GraphicView to GraphicView.
[architektonas] / src / base / rs_image.cpp
1 // rs_image.cpp
2 //
3 // Part of the Architektonas Project
4 // Originally part of QCad Community Edition by Andrew Mustun
5 // Extensively rewritten and refactored by James L. Hammons
6 // (C) 2010 Underground Software
7 //
8 // JLH = James L. Hammons <jlhamm@acm.org>
9 //
10 // Who  When        What
11 // ---  ----------  -----------------------------------------------------------
12 // JLH  05/28/2010  Added this text. :-)
13 //
14
15 #include "rs_image.h"
16
17 #include "rs_constructionline.h"
18 #include "rs_debug.h"
19 #include "graphicview.h"
20 #include "rs_line.h"
21 #include "paintintf.h"
22
23 /**
24  * Constructor.
25  */
26 RS_Image::RS_Image(RS_EntityContainer * parent, const RS_ImageData & d):
27         RS_AtomicEntity(parent), data(d)
28 {
29         update();
30         calculateBorders();
31 }
32
33 /**
34  * Destructor.
35  */
36 RS_Image::~RS_Image()
37 {
38         /*if (img!=NULL) {
39                 delete[] img;
40            }*/
41 }
42
43 RS_Entity * RS_Image::clone()
44 {
45         RS_Image * i = new RS_Image(*this);
46         i->setHandle(getHandle());
47         i->initId();
48         i->update();
49         return i;
50 }
51
52 /**     @return RS2::EntityImage */
53 /*virtual*/ RS2::EntityType RS_Image::rtti() const
54 {
55         return RS2::EntityImage;
56 }
57
58 void RS_Image::update()
59 {
60         RS_DEBUG->print("RS_Image::update");
61
62         // the whole image:
63         //QImage image = QImage(data.file);
64         img = QImage(data.file);
65
66         if (!img.isNull())
67                 data.size = Vector(img.width(), img.height());
68
69         RS_DEBUG->print("RS_Image::update: OK");
70
71         /*
72            // number of small images:
73            nx = image.width()/100;
74            ny = image.height()/100;
75
76            // create small images:
77            img = new QImage*[nx];
78            RS_Pixmap pm;
79            int w,h;
80            for (int x = 0; x<nx; ++x) {
81                 img[x] = new QImage[ny];
82                 for (int y = 0; y<ny; ++y) {
83                         if (x<nx-1) {
84                                 w = 100;
85                         }
86                         else {
87                                 w = image.width()%100;
88                         }
89
90                         if (y<ny-1) {
91                                 h = 100;
92                         }
93                         else {
94                                 h = image.height()%100;
95                         }
96
97                         pm = RS_Pixmap(w, h);
98                         RS_PainterQt painter(&pm);
99                         painter.drawImage(-x*100, -y*100, image);
100                         img[x][y] = pm.convertToImage();
101                 }
102            }
103          */
104 }
105
106 /** @return Copy of data that defines the image. */
107 RS_ImageData RS_Image::getData() const
108 {
109         return data;
110 }
111
112 /** @return Insertion point of the entity */
113 /*virtual*/ Vector RS_Image::getInsertionPoint() const
114 {
115         return data.insertionPoint;
116 }
117
118 /** Sets the insertion point for the image. */
119 void RS_Image::setInsertionPoint(Vector ip)
120 {
121         data.insertionPoint = ip;
122         calculateBorders();
123 }
124
125 /** @return File name of the image. */
126 QString RS_Image::getFile() const
127 {
128         return data.file;
129 }
130
131 /** Sets the file name of the image.  */
132 void RS_Image::setFile(const QString & file)
133 {
134         data.file = file;
135 }
136
137 /** @return u Vector. Points along bottom, 1 pixel long. */
138 Vector RS_Image::getUVector() const
139 {
140         return data.uVector;
141 }
142
143 /** @return v Vector. Points along left, 1 pixel long. */
144 Vector RS_Image::getVVector() const
145 {
146         return data.vVector;
147 }
148
149 /** @return Width of image in pixels. */
150 int RS_Image::getWidth() const
151 {
152         return (int)data.size.x;
153 }
154
155 /** @return Height of image in pixels. */
156 int RS_Image::getHeight() const
157 {
158         return (int)data.size.y;
159 }
160
161 /** @return Brightness. */
162 int RS_Image::getBrightness() const
163 {
164         return data.brightness;
165 }
166
167 /** @return Contrast. */
168 int RS_Image::getContrast() const
169 {
170         return data.contrast;
171 }
172
173 /** @return Fade. */
174 int RS_Image::getFade() const
175 {
176         return data.fade;
177 }
178
179 /** @return Image definition handle. */
180 int RS_Image::getHandle() const
181 {
182         return data.handle;
183 }
184
185 /** Sets the image definition handle. */
186 void RS_Image::setHandle(int h)
187 {
188         data.handle = h;
189 }
190
191 /** @return The four corners. **/
192 VectorSolutions RS_Image::getCorners()
193 {
194         VectorSolutions sol(4);
195
196         sol.set(0, data.insertionPoint);
197         sol.set(1,
198                 data.insertionPoint + data.uVector * RS_Math::round(data.size.x));
199         sol.set(3,
200                 data.insertionPoint + data.vVector * RS_Math::round(data.size.y));
201         sol.set(2, sol.get(3) + data.uVector * RS_Math::round(data.size.x));
202
203         return sol;
204 }
205
206 /**
207  * @return image with in graphic units.
208  */
209 double RS_Image::getImageWidth()
210 {
211         return data.size.x * data.uVector.magnitude();
212 }
213
214 /**
215  * @return image height in graphic units.
216  */
217 double RS_Image::getImageHeight()
218 {
219         return data.size.y * data.vVector.magnitude();
220 }
221
222 void RS_Image::calculateBorders()
223 {
224         resetBorders();
225         VectorSolutions sol = getCorners();
226
227         for (int i = 0; i < 4; ++i)
228         {
229                 minV = Vector::minimum(minV, sol.get(i));
230                 maxV = Vector::maximum(maxV, sol.get(i));
231         }
232 }
233
234 Vector RS_Image::getNearestEndpoint(const Vector & coord, double * dist)
235 {
236         VectorSolutions corners = getCorners();
237         return corners.getClosest(coord, dist);
238 }
239
240 Vector RS_Image::getNearestPointOnEntity(const Vector & coord, bool onEntity, double * dist, RS_Entity * * entity)
241 {
242         if (entity != NULL)
243                 *entity = this;
244
245         VectorSolutions corners = getCorners();
246         VectorSolutions points(4);
247
248         RS_Line l[] = {
249                 RS_Line(NULL, RS_LineData(corners.get(0), corners.get(1))),
250                 RS_Line(NULL, RS_LineData(corners.get(1), corners.get(2))),
251                 RS_Line(NULL, RS_LineData(corners.get(2), corners.get(3))),
252                 RS_Line(NULL, RS_LineData(corners.get(3), corners.get(0)))
253         };
254
255         for (int i = 0; i < 4; ++i)
256                 points.set(i, l[i].getNearestPointOnEntity(coord, onEntity));
257
258         return points.getClosest(coord, dist);
259 }
260
261 Vector RS_Image::getNearestCenter(const Vector & coord, double * dist)
262 {
263         VectorSolutions points(4);
264         VectorSolutions corners = getCorners();
265
266         points.set(0, (corners.get(0) + corners.get(1)) / 2.0);
267         points.set(1, (corners.get(1) + corners.get(2)) / 2.0);
268         points.set(2, (corners.get(2) + corners.get(3)) / 2.0);
269         points.set(3, (corners.get(3) + corners.get(0)) / 2.0);
270
271         return points.getClosest(coord, dist);
272 }
273
274 Vector RS_Image::getNearestMiddle(const Vector & coord, double * dist)
275 {
276         return getNearestCenter(coord, dist);
277 }
278
279 Vector RS_Image::getNearestDist(double distance, const Vector & coord, double * dist)
280 {
281         VectorSolutions corners = getCorners();
282         VectorSolutions points(4);
283
284         RS_Line l[] =
285         {
286                 RS_Line(NULL, RS_LineData(corners.get(0), corners.get(1))),
287                 RS_Line(NULL, RS_LineData(corners.get(1), corners.get(2))),
288                 RS_Line(NULL, RS_LineData(corners.get(2), corners.get(3))),
289                 RS_Line(NULL, RS_LineData(corners.get(3), corners.get(0)))
290         };
291
292         for (int i = 0; i < 4; ++i)
293                 points.set(i, l[i].getNearestDist(distance, coord, dist));
294
295         return points.getClosest(coord, dist);
296 }
297
298 double RS_Image::getDistanceToPoint(const Vector & coord, RS_Entity * * entity, RS2::ResolveLevel /*level*/,        double /*solidDist*/)
299 {
300         if (entity != NULL)
301                 *entity = this;
302
303         VectorSolutions corners = getCorners();
304         double dist;
305         double minDist = RS_MAXDOUBLE;
306
307         RS_Line l[] =
308         {
309                 RS_Line(NULL, RS_LineData(corners.get(0), corners.get(1))),
310                 RS_Line(NULL, RS_LineData(corners.get(1), corners.get(2))),
311                 RS_Line(NULL, RS_LineData(corners.get(2), corners.get(3))),
312                 RS_Line(NULL, RS_LineData(corners.get(3), corners.get(0)))
313         };
314
315         for (int i = 0; i < 4; ++i)
316         {
317                 dist = l[i].getDistanceToPoint(coord, NULL);
318
319                 if (dist < minDist)
320                         minDist = dist;
321         }
322
323         return minDist;
324 }
325
326 /*virtual*/ double RS_Image::getLength()
327 {
328         return -1.0;
329 }
330
331 void RS_Image::move(Vector offset)
332 {
333         data.insertionPoint.move(offset);
334         calculateBorders();
335 }
336
337 void RS_Image::rotate(Vector center, double angle)
338 {
339         data.insertionPoint.rotate(center, angle);
340         data.uVector.rotate(angle);
341         data.vVector.rotate(angle);
342         calculateBorders();
343 }
344
345 void RS_Image::scale(Vector center, Vector factor)
346 {
347         data.insertionPoint.scale(center, factor);
348         data.uVector.scale(factor);
349         data.vVector.scale(factor);
350         calculateBorders();
351 }
352
353 void RS_Image::mirror(Vector axisPoint1, Vector axisPoint2)
354 {
355         data.insertionPoint.mirror(axisPoint1, axisPoint2);
356         data.uVector.mirror(Vector(0.0, 0.0), axisPoint2 - axisPoint1);
357         data.vVector.mirror(Vector(0.0, 0.0), axisPoint2 - axisPoint1);
358         calculateBorders();
359 }
360
361 void RS_Image::draw(PaintInterface * painter, GraphicView * view, double /*patternOffset*/)
362 {
363         if (painter == NULL || view == NULL || img.isNull())
364                 return;
365
366         // erase image:
367         //if (painter->getPen().getColor()==view->getBackground()) {
368         //      VectorSolutions sol = getCorners();
369         //
370         //}
371
372         int ox = 0;
373         int oy = 0;
374         int width = view->getWidth();
375         int height = view->getHeight();
376
377         Vector scale = Vector(view->toGuiDX(data.uVector.magnitude()),
378                         view->toGuiDY(data.vVector.magnitude()));
379         double angle = data.uVector.angle();
380
381         int startX, stopX, startY, stopY;
382
383         if (data.uVector.x > 1.0e-6 && data.vVector.y > 1.0e-6)
384         {
385                 startX = (int)((view->toGraphX(ox) - data.insertionPoint.x) / data.uVector.x) - 1;
386
387                 if (startX < 0)
388                         startX = 0;
389
390                 stopX = (int)((view->toGraphX(width) - data.insertionPoint.x) / data.uVector.x) + 1;
391
392                 if (stopX > (int)data.size.x)
393                         stopX = (int)data.size.x;
394
395                 startY = -(int)((view->toGraphY(oy) - (data.insertionPoint.y + getImageHeight()))
396                                 / data.vVector.y) - 1;
397
398                 if (startY < 0)
399                         startY = 0;
400
401                 stopY = -(int)((view->toGraphY(height) - (data.insertionPoint.y + getImageHeight()))
402                                / data.vVector.y) + 1;
403
404                 if (stopY > (int)data.size.y)
405                         stopY = (int)data.size.y;
406         }
407         else
408         {
409                 startX = 0;
410                 startY = 0;
411                 stopX = 0;
412                 stopY = 0;
413         }
414
415         painter->drawImg(img, view->toGui(data.insertionPoint), angle, scale,
416                 startX, startY, stopX - startX, stopY - startY);
417
418         if (isSelected())
419         {
420                 VectorSolutions sol = getCorners();
421
422                 painter->drawLine(view->toGui(sol.get(0)), view->toGui(sol.get(1)));
423                 painter->drawLine(view->toGui(sol.get(1)), view->toGui(sol.get(2)));
424                 painter->drawLine(view->toGui(sol.get(2)), view->toGui(sol.get(3)));
425                 painter->drawLine(view->toGui(sol.get(3)), view->toGui(sol.get(0)));
426         }
427 }
428
429 /**
430  * Dumps the point's data to stdout.
431  */
432 std::ostream & operator<<(std::ostream & os, const RS_Image & i)
433 {
434         os << " Image: " << i.getData() << "\n";
435         return os;
436 }