]> Shamusworld >> Repos - architektonas/blob - src/base/rs_image.cpp
Initial import
[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 "rs_graphicview.h"
20 #include "paintintf.h"
21
22 /**
23  * Constructor.
24  */
25 RS_Image::RS_Image(RS_EntityContainer * parent, const RS_ImageData & d):
26         RS_AtomicEntity(parent), data(d)
27 {
28         update();
29         calculateBorders();
30 }
31
32 /**
33  * Destructor.
34  */
35 RS_Image::~RS_Image()
36 {
37         /*if (img!=NULL) {
38                 delete[] img;
39         }*/
40 }
41
42 RS_Entity * RS_Image::clone()
43 {
44         RS_Image * i = new RS_Image(*this);
45         i->setHandle(getHandle());
46         i->initId();
47         i->update();
48         return i;
49 }
50
51 void RS_Image::update()
52 {
53         RS_DEBUG->print("RS_Image::update");
54
55         // the whole image:
56         //QImage image = QImage(data.file);
57         img = QImage(data.file);
58
59         if (!img.isNull())
60                 data.size = Vector(img.width(), img.height());
61
62         RS_DEBUG->print("RS_Image::update: OK");
63
64         /*
65         // number of small images:
66         nx = image.width()/100;
67         ny = image.height()/100;
68
69         // create small images:
70         img = new QImage*[nx];
71         RS_Pixmap pm;
72         int w,h;
73         for (int x = 0; x<nx; ++x) {
74                 img[x] = new QImage[ny];
75                 for (int y = 0; y<ny; ++y) {
76                         if (x<nx-1) {
77                                 w = 100;
78                         }
79                         else {
80                                 w = image.width()%100;
81                         }
82
83                         if (y<ny-1) {
84                                 h = 100;
85                         }
86                         else {
87                                 h = image.height()%100;
88                         }
89
90                         pm = RS_Pixmap(w, h);
91                         RS_PainterQt painter(&pm);
92                         painter.drawImage(-x*100, -y*100, image);
93                         img[x][y] = pm.convertToImage();
94                 }
95         }
96         */
97 }
98
99 void RS_Image::calculateBorders()
100 {
101         resetBorders();
102         VectorSolutions sol = getCorners();
103
104         for(int i=0; i<4; ++i)
105         {
106                 minV = Vector::minimum(minV, sol.get(i));
107                 maxV = Vector::maximum(maxV, sol.get(i));
108         }
109 }
110
111 Vector RS_Image::getNearestEndpoint(const Vector & coord, double * dist)
112 {
113         VectorSolutions corners = getCorners();
114         return corners.getClosest(coord, dist);
115 }
116
117 Vector RS_Image::getNearestPointOnEntity(const Vector & coord, bool onEntity, double * dist,
118         RS_Entity ** entity)
119 {
120         if (entity != NULL)
121                 *entity = this;
122
123         VectorSolutions corners = getCorners();
124         VectorSolutions points(4);
125
126         RS_Line l[] = {
127                 RS_Line(NULL, RS_LineData(corners.get(0), corners.get(1))),
128                 RS_Line(NULL, RS_LineData(corners.get(1), corners.get(2))),
129                 RS_Line(NULL, RS_LineData(corners.get(2), corners.get(3))),
130                 RS_Line(NULL, RS_LineData(corners.get(3), corners.get(0)))
131         };
132
133         for(int i=0; i<4; ++i)
134                 points.set(i, l[i].getNearestPointOnEntity(coord, onEntity));
135
136         return points.getClosest(coord, dist);
137 }
138
139 Vector RS_Image::getNearestCenter(const Vector & coord, double * dist)
140 {
141         VectorSolutions points(4);
142         VectorSolutions corners = getCorners();
143
144         points.set(0, (corners.get(0) + corners.get(1))/2.0);
145         points.set(1, (corners.get(1) + corners.get(2))/2.0);
146         points.set(2, (corners.get(2) + corners.get(3))/2.0);
147         points.set(3, (corners.get(3) + corners.get(0))/2.0);
148
149         return points.getClosest(coord, dist);
150 }
151
152
153
154 Vector RS_Image::getNearestMiddle(const Vector& coord,
155                                      double* dist) {
156     return getNearestCenter(coord, dist);
157 }
158
159
160
161 Vector RS_Image::getNearestDist(double distance,
162                                    const Vector& coord,
163                                    double* dist) {
164
165     VectorSolutions corners = getCorners();
166     VectorSolutions points(4);
167
168     RS_Line l[] =
169         {
170             RS_Line(NULL, RS_LineData(corners.get(0), corners.get(1))),
171             RS_Line(NULL, RS_LineData(corners.get(1), corners.get(2))),
172             RS_Line(NULL, RS_LineData(corners.get(2), corners.get(3))),
173             RS_Line(NULL, RS_LineData(corners.get(3), corners.get(0)))
174         };
175
176     for (int i=0; i<4; ++i) {
177         points.set(i, l[i].getNearestDist(distance, coord, dist));
178     }
179
180     return points.getClosest(coord, dist);
181 }
182
183
184
185 double RS_Image::getDistanceToPoint(const Vector& coord,
186                                     RS_Entity** entity,
187                                     RS2::ResolveLevel /*level*/,
188                                                                         double /*solidDist*/) {
189     if (entity!=NULL) {
190         *entity = this;
191     }
192
193     VectorSolutions corners = getCorners();
194     double dist;
195     double minDist = RS_MAXDOUBLE;
196
197     RS_Line l[] =
198         {
199             RS_Line(NULL, RS_LineData(corners.get(0), corners.get(1))),
200             RS_Line(NULL, RS_LineData(corners.get(1), corners.get(2))),
201             RS_Line(NULL, RS_LineData(corners.get(2), corners.get(3))),
202             RS_Line(NULL, RS_LineData(corners.get(3), corners.get(0)))
203         };
204
205     for (int i=0; i<4; ++i) {
206         dist = l[i].getDistanceToPoint(coord, NULL);
207         if (dist<minDist) {
208             minDist = dist;
209         }
210     }
211
212     return minDist;
213 }
214
215
216
217 void RS_Image::move(Vector offset) {
218     data.insertionPoint.move(offset);
219     calculateBorders();
220 }
221
222
223
224 void RS_Image::rotate(Vector center, double angle) {
225     data.insertionPoint.rotate(center, angle);
226     data.uVector.rotate(angle);
227     data.vVector.rotate(angle);
228     calculateBorders();
229 }
230
231
232
233 void RS_Image::scale(Vector center, Vector factor) {
234     data.insertionPoint.scale(center, factor);
235     data.uVector.scale(factor);
236     data.vVector.scale(factor);
237     calculateBorders();
238 }
239
240
241
242 void RS_Image::mirror(Vector axisPoint1, Vector axisPoint2) {
243     data.insertionPoint.mirror(axisPoint1, axisPoint2);
244     data.uVector.mirror(Vector(0.0,0.0), axisPoint2-axisPoint1);
245     data.vVector.mirror(Vector(0.0,0.0), axisPoint2-axisPoint1);
246     calculateBorders();
247 }
248
249 //void RS_Image::draw(RS_Painter* painter, RS_GraphicView* view, double /*patternOffset*/) {
250 void RS_Image::draw(PaintInterface * painter, RS_GraphicView * view, double /*patternOffset*/)
251 {
252         if (painter == NULL || view == NULL || img.isNull())
253                 return;
254
255         // erase image:
256         //if (painter->getPen().getColor()==view->getBackground()) {
257         //      VectorSolutions sol = getCorners();
258         //
259         //}
260
261         int ox = 0;
262         int oy = 0;
263         int width = view->getWidth();
264         int height = view->getHeight();
265
266         Vector scale = Vector(view->toGuiDX(data.uVector.magnitude()),
267                 view->toGuiDY(data.vVector.magnitude()));
268         double angle = data.uVector.angle();
269
270         int startX, stopX, startY, stopY;
271
272         if (data.uVector.x > 1.0e-6 && data.vVector.y > 1.0e-6)
273         {
274                 startX = (int)((view->toGraphX(ox)-data.insertionPoint.x) / data.uVector.x) - 1;
275
276                 if (startX < 0)
277                 {
278                         startX = 0;
279                 }
280
281                 stopX = (int)((view->toGraphX(width)-data.insertionPoint.x) / data.uVector.x) + 1;
282
283                 if (stopX > (int)data.size.x)
284                 {
285                         stopX = (int)data.size.x;
286                 }
287
288                 startY = -(int)((view->toGraphY(oy) - (data.insertionPoint.y+getImageHeight())) /
289                         data.vVector.y) - 1;
290
291                 if (startY<0)
292                 {
293                         startY = 0;
294                 }
295
296                 stopY = -(int)((view->toGraphY(height) - (data.insertionPoint.y+getImageHeight())) /
297                         data.vVector.y) + 1;
298
299                 if (stopY>(int)data.size.y)
300                 {
301                         stopY = (int)data.size.y;
302                 }
303         }
304         else
305         {
306                 startX = 0;
307                 startY = 0;
308                 stopX = 0;
309                 stopY = 0;
310         }
311
312         painter->drawImg(img, view->toGui(data.insertionPoint), angle, scale,
313                 startX, startY, stopX-startX, stopY-startY);
314
315         if (isSelected())
316         {
317                 VectorSolutions sol = getCorners();
318
319                 painter->drawLine(view->toGui(sol.get(0)), view->toGui(sol.get(1)));
320                 painter->drawLine(view->toGui(sol.get(1)), view->toGui(sol.get(2)));
321                 painter->drawLine(view->toGui(sol.get(2)), view->toGui(sol.get(3)));
322                 painter->drawLine(view->toGui(sol.get(3)), view->toGui(sol.get(0)));
323         }
324 }
325
326 /**
327  * Dumps the point's data to stdout.
328  */
329 std::ostream & operator<<(std::ostream & os, const RS_Image & i)
330 {
331         os << " Image: " << i.getData() << "\n";
332         return os;
333 }
334