]> Shamusworld >> Repos - architektonas/blob - src/base/snapper.cpp
28e600adee65ed2e09d7540062a4b65703627711
[architektonas] / src / base / snapper.cpp
1 // snapper.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 // Portions copyright (C) 2001-2003 RibbonSoft
7 // Copyright (C) 2010 Underground Software
8 // See the README and GPLv2 files for licensing and warranty information
9 //
10 // JLH = James L. Hammons <jlhamm@acm.org>
11 //
12 // Who  When        What
13 // ---  ----------  -----------------------------------------------------------
14 // JLH  05/21/2010  Added this text. :-)
15 // JLH  10/18/2010  Commented out all functions in preparation for deprecating
16 //                  this class.
17 //
18
19 #include "snapper.h"
20
21 #include "dialogfactory.h"
22 #include "drawing.h"
23 #include "entitycontainer.h"
24 #include "graphicview.h"
25 #include "grid.h"
26 #include "information.h"
27 #include "paintinterface.h"
28 #include "settings.h"
29
30 /**
31  * Constructor.
32  */
33 Snapper::Snapper(EntityContainer & c, GraphicView & gv):
34         container(&c), graphicView(&gv), finished(false)
35 {
36 #if 0
37         init();
38 #endif
39 }
40
41 Snapper::Snapper(void):
42         container(NULL), graphicView(NULL), finished(false)
43 {
44 #if 0
45         init();
46 #endif
47 }
48
49 /**
50  * Destructor.
51  */
52 Snapper::~Snapper()
53 {
54 }
55
56 /**
57  * Initialize (called by all constructors)
58  */
59 void Snapper::init()
60 {
61 #if 0
62         if (graphicView)
63         {
64                 snapMode = graphicView->getDefaultSnapMode();
65                 snapRes = graphicView->getSnapRestriction();
66         }
67
68         keyEntity = NULL;
69         snapSpot = Vector(false);
70         snapCoord = Vector(false);
71         visible = false;
72         distance = 1.0;
73
74         settings.beginGroup("Snap");
75         snapRange = settings.value("Range", 20).toInt();
76         settings.endGroup();
77         settings.beginGroup("Appearance");
78         showCrosshairs = settings.value("ShowCrosshairs", true).toBool();
79         settings.endGroup();
80
81         // Sanity check
82         if (snapRange < 2)
83                 snapRange = 20;
84 #endif
85 }
86
87 void Snapper::finish()
88 {
89 #if 0
90         finished = true;
91 #endif
92 }
93
94 //bleh
95 void Snapper::SetContainer(EntityContainer * c)
96 {
97 #if 0
98         container = c;
99 #endif
100 }
101
102 //bleh
103 void Snapper::SetGraphicView(GraphicView * v)
104 {
105 #if 0
106         graphicView = v;
107 #endif
108 }
109
110 /**
111  * @return Pointer to the entity which was the key entity for the last
112  * successful snapping action. If the snap mode is "end point" the key entity
113  * is the entity whose end point was caught. If the snap mode didn't require an
114  * entity (e.g. free, grid) this method will return NULL.
115  */
116 Entity * Snapper::getKeyEntity()
117 {
118 #if 0
119         return keyEntity;
120 #endif
121         return NULL;
122 }
123
124 /** Sets a new snap mode. */
125 void Snapper::setSnapMode(RS2::SnapMode snapMode)
126 {
127 #if 0
128         this->snapMode = snapMode;
129 #endif
130 }
131
132 /** Sets a new snap restriction. */
133 void Snapper::setSnapRestriction(RS2::SnapRestriction snapRes)
134 {
135 #if 0
136         this->snapRes = snapRes;
137 #endif
138 }
139
140 RS2::SnapMode Snapper::getSnapMode(void)
141 {
142 #if 0
143         return snapMode;
144 #endif
145         return RS2::SnapFree;
146 }
147
148 RS2::SnapRestriction Snapper::getSnapRestriction(void)
149 {
150 #if 0
151         return snapRes;
152 #endif
153         return RS2::RestrictNothing;
154 }
155
156 /**
157  * Sets the snap range in pixels for catchEntity().
158  *
159  * @see catchEntity()
160  */
161 void Snapper::setSnapRange(int r)
162 {
163 #if 0
164         snapRange = r;
165 #endif
166 }
167
168 #if 0
169 This should get moved into GraphicView...
170 #endif
171 /**
172  * Snap to a coordinate in the drawing using the current snap mode.
173  *
174  * @param e A mouse event.
175  * @return The coordinates of the point or an invalid vector.
176  */
177 Vector Snapper::snapPoint(QMouseEvent * e)
178 {
179 #if 0
180         DEBUG->print("Snapper::snapPoint");
181         snapSpot = Vector(false);
182
183         if (!e)
184         {
185                 DEBUG->print(Debug::D_WARNING, "Snapper::snapPoint: event is NULL");
186                 return snapSpot;
187         }
188
189         Vector mouseCoord = graphicView->toGraph(e->x(), e->y());
190
191         switch (snapMode)
192         {
193         case RS2::SnapFree:
194                 snapSpot = snapFree(mouseCoord);
195                 break;
196
197         case RS2::SnapEndpoint:
198                 snapSpot = snapEndpoint(mouseCoord);
199                 break;
200
201         case RS2::SnapGrid:
202                 snapSpot = snapGrid(mouseCoord);
203                 break;
204
205         case RS2::SnapOnEntity:
206                 snapSpot = snapOnEntity(mouseCoord);
207                 break;
208
209         case RS2::SnapCenter:
210                 snapSpot = snapCenter(mouseCoord);
211                 break;
212
213         case RS2::SnapMiddle:
214                 snapSpot = snapMiddle(mouseCoord);
215                 break;
216
217         case RS2::SnapDist:
218                 snapSpot = snapDist(mouseCoord);
219                 break;
220
221         case RS2::SnapIntersection:
222                 snapSpot = snapIntersection(mouseCoord);
223                 break;
224
225         default:
226                 break;
227         }
228
229         // Handle snap restrictions that can be activated in addition to the ones above:
230         switch (snapRes)
231         {
232         case RS2::RestrictOrthogonal:
233                 snapCoord = restrictOrthogonal(snapSpot);
234                 break;
235         case RS2::RestrictHorizontal:
236                 snapCoord = restrictHorizontal(snapSpot);
237                 break;
238         case RS2::RestrictVertical:
239                 snapCoord = restrictVertical(snapSpot);
240                 break;
241         default:
242         case RS2::RestrictNothing:
243                 snapCoord = snapSpot;
244                 break;
245         }
246
247         if (DIALOGFACTORY)
248                 DIALOGFACTORY->updateCoordinateWidget(snapCoord, snapCoord - graphicView->getRelativeZero());
249
250         DEBUG->print("Snapper::snapPoint: OK");
251
252         return snapCoord;
253 #endif
254         return Vector(false);
255 }
256
257 /**
258  * Snaps to a free coordinate.
259  *
260  * @param coord The mouse coordinate.
261  * @return The coordinates of the point or an invalid vector.
262  */
263 Vector Snapper::snapFree(Vector coord)
264 {
265 #if 0
266         keyEntity = NULL;
267         return coord;
268 #endif
269         return Vector(false);
270 }
271
272 /**
273  * Snaps to the closest endpoint.
274  *
275  * @param coord The mouse coordinate.
276  * @return The coordinates of the point or an invalid vector.
277  */
278 Vector Snapper::snapEndpoint(Vector coord)
279 {
280 #if 0
281         Vector vec(false);
282         vec = container->getNearestEndpoint(coord, NULL);
283
284         return vec;
285 #endif
286         return Vector(false);
287 }
288
289 /**
290  * Snaps to a grid point.
291  *
292  * @param coord The mouse coordinate.
293  * @return The coordinates of the point or an invalid vector.
294  */
295 Vector Snapper::snapGrid(Vector coord)
296 {
297 #if 0
298         DEBUG->print("Snapper::snapGrid begin");
299
300         Vector vec(false);
301         double dist = 0.0;
302
303         Grid * grid = graphicView->getGrid();
304
305         DEBUG->print("Snapper::snapGrid 001");
306
307         if (grid)
308         {
309                 DEBUG->print("Snapper::snapGrid 002");
310                 Vector * pts = grid->getPoints();
311                 DEBUG->print("Snapper::snapGrid 003");
312                 int closest = -1;
313                 dist = 32000.00;
314                 DEBUG->print("Snapper::snapGrid 004");
315
316                 for(int i=0; i<grid->count(); ++i)
317                 {
318                         double d = pts[i].distanceTo(coord);
319
320                         if (d < dist)
321                         {
322                                 closest = i;
323                                 dist = d;
324                         }
325                 }
326
327                 DEBUG->print("Snapper::snapGrid 005");
328
329                 if (closest >= 0)
330                         vec = pts[closest];
331
332                 DEBUG->print("Snapper::snapGrid 006");
333         }
334
335         keyEntity = NULL;
336
337         DEBUG->print("Snapper::snapGrid end");
338
339         return vec;
340 #endif
341         return Vector(false);
342 }
343
344 /**
345  * Snaps to a point on an entity.
346  *
347  * @param coord The mouse coordinate.
348  * @return The coordinates of the point or an invalid vector.
349  */
350 Vector Snapper::snapOnEntity(Vector coord)
351 {
352 #if 0
353         Vector vec(false);
354         vec = container->getNearestPointOnEntity(coord, true, NULL, &keyEntity);
355
356         return vec;
357 #endif
358         return Vector(false);
359 }
360
361 /**
362  * Snaps to the closest center.
363  *
364  * @param coord The mouse coordinate.
365  * @return The coordinates of the point or an invalid vector.
366  */
367 Vector Snapper::snapCenter(Vector coord)
368 {
369 #if 0
370         Vector vec(false);
371         vec = container->getNearestCenter(coord, NULL);
372
373         return vec;
374 #endif
375         return Vector(false);
376 }
377
378 /**
379  * Snaps to the closest middle.
380  *
381  * @param coord The mouse coordinate.
382  * @return The coordinates of the point or an invalid vector.
383  */
384 Vector Snapper::snapMiddle(Vector coord)
385 {
386 #if 0
387         Vector vec(false);
388         vec = container->getNearestMiddle(coord, NULL);
389
390         return vec;
391 #endif
392         return Vector(false);
393 }
394
395 /**
396  * Snaps to the closest point with a given distance to the endpoint.
397  *
398  * @param coord The mouse coordinate.
399  * @return The coordinates of the point or an invalid vector.
400  */
401 Vector Snapper::snapDist(Vector coord)
402 {
403 #if 0
404         Vector vec(false);
405         vec = container->getNearestDist(distance, coord, NULL);
406
407         return vec;
408 #endif
409         return Vector(false);
410 }
411
412 /**
413  * Snaps to the closest intersection point.
414  *
415  * @param coord The mouse coordinate.
416  * @return The coordinates of the point or an invalid vector.
417  */
418 Vector Snapper::snapIntersection(Vector coord)
419 {
420 #if 0
421         Vector vec(false);
422         vec = container->getNearestIntersection(coord, NULL);
423
424         return vec;
425 #endif
426         return Vector(false);
427 }
428
429 /**
430  * 'Corrects' the given coordinates to 0, 90, 180, 270 degrees relative to
431  * the current relative zero point.
432  *
433  * @param coord The uncorrected coordinates.
434  * @return The corrected coordinates.
435  */
436 Vector Snapper::restrictOrthogonal(Vector coord)
437 {
438 #if 0
439         Vector rz = graphicView->getRelativeZero();
440         Vector ret(coord);
441
442         Vector retx = Vector(rz.x, ret.y);
443         Vector rety = Vector(ret.x, rz.y);
444
445         if (retx.distanceTo(ret) > rety.distanceTo(ret))
446                 ret = rety;
447         else
448                 ret = retx;
449
450         return ret;
451 #endif
452         return Vector(false);
453 }
454
455 /**
456  * 'Corrects' the given coordinates to 0, 180 degrees relative to
457  * the current relative zero point.
458  *
459  * @param coord The uncorrected coordinates.
460  * @return The corrected coordinates.
461  */
462 Vector Snapper::restrictHorizontal(Vector coord)
463 {
464 #if 0
465         Vector rz = graphicView->getRelativeZero();
466
467         return Vector(coord.x, rz.y);
468 #endif
469         return Vector(false);
470 }
471
472 /**
473  * 'Corrects' the given coordinates to 90, 270 degrees relative to
474  * the current relative zero point.
475  *
476  * @param coord The uncorrected coordinates.
477  * @return The corrected coordinates.
478  */
479 Vector Snapper::restrictVertical(Vector coord)
480 {
481 #if 0
482         Vector rz = graphicView->getRelativeZero();
483
484         return Vector(rz.x, coord.y);
485 #endif
486         return Vector(false);
487 }
488
489 /**
490  * Catches an entity which is close to the given position 'pos'.
491  *
492  * @param pos A graphic coordinate.
493  * @param level The level of resolving for iterating through the entity
494  *        container
495  * @return Pointer to the entity or NULL.
496  */
497 Entity * Snapper::catchEntity(const Vector & pos, RS2::ResolveLevel level)
498 {
499 #if 0
500         DEBUG->print("Snapper::catchEntity");
501
502         // Set default distance for points inside solids
503         double dist = graphicView->toGraphDX(snapRange) * 0.9;
504         Entity * entity = container->getNearestEntity(pos, &dist, level);
505         int idx = -1;
506
507         if (entity && entity->getParent())
508                 idx = entity->getParent()->findEntity(entity);
509
510         if (entity && dist <= graphicView->toGraphDX(snapRange))
511         {
512                 // Highlight:
513                 DEBUG->print("Snapper::catchEntity: found: %d", idx);
514                 return entity;
515         }
516 //      else
517 //      {
518         DEBUG->print("Snapper::catchEntity: not found");
519         return NULL;
520 //      }
521
522 //      DEBUG->print("Snapper::catchEntity: OK");
523 #endif
524         return NULL;
525 }
526
527 /**
528  * Catches an entity which is close to the mouse cursor.
529  *
530  * @param e A mouse event.
531  * @param level The level of resolving for iterating through the entity
532  *        container
533  * @return Pointer to the entity or NULL.
534  */
535 Entity * Snapper::catchEntity(QMouseEvent * e, RS2::ResolveLevel level)
536 {
537 #if 0
538         return catchEntity(Vector(graphicView->toGraphX(e->x()),
539                 graphicView->toGraphY(e->y())), level);
540 #endif
541         return NULL;
542 }
543
544 #if 0
545 I think that these suspend() & resume() functions are not used anymore...
546 #endif
547 /**
548  * Suspends this snapper while another action takes place.
549  */
550 /*virtual*/ void Snapper::suspend()
551 {
552 #if 0
553 #warning "!!! This may need to have SetVisibility() called !!!"
554 //      deleteSnapper();
555         snapSpot = snapCoord = Vector(false);
556 #endif
557 }
558
559 /**
560  * Resumes this snapper after it has been suspended.
561  */
562 /*virtual*/ void Snapper::resume()
563 {
564 #if 0
565 #warning "!!! This may need to have SetVisibility() called !!!"
566 //      drawSnapper();
567 #endif
568 }
569
570 /**
571  * Hides the snapper options.
572  */
573 /*virtual*/ void Snapper::hideOptions()
574 {
575 #if 0
576         if (snapMode == RS2::SnapDist && DIALOGFACTORY)
577                 DIALOGFACTORY->requestSnapDistOptions(distance, false);
578 #endif
579 }
580
581 /**
582  * Shows the snapper options.
583  */
584 /*virtual*/ void Snapper::showOptions()
585 {
586 #if 0
587         if (snapMode == RS2::SnapDist && DIALOGFACTORY)
588                 DIALOGFACTORY->requestSnapDistOptions(distance, true);
589 #endif
590 }
591
592 void Snapper::SetVisible(bool visibility/*= true*/)
593 {
594 #if 0
595         visible = visibility;
596 #endif
597 }
598
599 bool Snapper::Visible(void)
600 {
601 #if 0
602         return visible;
603 #endif
604 }
605
606 /*
607 We need to figure out how to kick the GraphicView out of this class. Perhaps we
608 need to move the toGuiX/Y() functions into another class as static functions.
609 Further inspection seems to rule this out as they are pretty well coupled to the
610 GraphicView class... What to do?
611 */
612 void Snapper::Draw(GraphicView * view, PaintInterface * painter)
613 {
614 #if 0
615         if (finished || !snapSpot.valid || !snapCoord.valid)
616                 return;
617
618 //hm, I don't like graphicView kicking around in here, especially since it now
619 //lives inside GraphicView... How to !!! FIX !!!?
620 //We'll pass it in for now...
621         // Snap point (need to make sure the brush is NULL!)
622 //      painter->setPen(Pen(Color(0, 127, 255), RS2::Width00, RS2::DashLine));
623         painter->setPen(Pen(Color(255, 127, 0), RS2::Width00, RS2::DashLine));
624         painter->drawCircle(view->toGui(snapCoord), 4);
625
626         // Crosshairs
627         if (showCrosshairs)
628         {
629                 painter->setPen(Pen(Color(0, 255, 255), RS2::Width00, RS2::DashLine));
630                 painter->drawLine(Vector(0, view->toGuiY(snapCoord.y)),
631                         Vector(view->getWidth(), view->toGuiY(snapCoord.y)));
632                 painter->drawLine(Vector(view->toGuiX(snapCoord.x), 0),
633                         Vector(view->toGuiX(snapCoord.x), view->getHeight()));
634         }
635
636         if (snapCoord != snapSpot)
637         {
638                 painter->drawLine(view->toGui(snapSpot) + Vector(-5, 0),
639                         view->toGui(snapSpot) + Vector(-1, 4));
640                 painter->drawLine(view->toGui(snapSpot) + Vector(0, 5),
641                         view->toGui(snapSpot) + Vector(4, 1));
642                 painter->drawLine(view->toGui(snapSpot) + Vector(5, 0),
643                         view->toGui(snapSpot) + Vector(1, -4));
644                 painter->drawLine(view->toGui(snapSpot) + Vector(0, -5),
645                         view->toGui(snapSpot) + Vector(-4, -1));
646         }
647 #endif
648 }